web-dev-qa-db-fra.com

À quoi sert la fonction delay () (lorsqu'elle est utilisée avec joblib en Python)

J'ai lu la documentation , mais je ne comprends pas ce que l'on entend par: The delayed function is a simple trick to be able to create a Tuple (function, args, kwargs) with a function-call syntax.

Je l'utilise pour parcourir la liste sur laquelle je veux opérer (allImages) comme suit:

def joblib_loop():
    Parallel(n_jobs=8)(delayed(getHog)(i) for i in allImages)

Cela renvoie mes fonctionnalités HOG, comme je le veux (et avec le gain de vitesse en utilisant tous mes 8 cœurs), mais je ne suis tout simplement pas sûr de ce qu'il fait réellement.

Mes connaissances Python sont au mieux correctes, et il est très possible que je manque quelque chose de basique. Tout pointeur dans la bonne direction serait le plus apprécié

31
orrymr

Peut-être que les choses deviennent plus claires si nous regardons ce qui se passerait si, au lieu de cela, nous écrivions simplement

Parallel(n_jobs=8)(getHog(i) for i in allImages)

La façon dont Python fonctionne, getHog(i) for i in allImages crée une liste où chaque élément est déjà évalué . Cette signifie que tous les appels getHog sont déjà retournés au moment où la liste est passée à votre objet Parallel, et il n'y a plus rien pour que Parallel s'exécute en parallèle! Tout le travail a déjà été fait dans le fil que nous sommes en ce moment, de manière séquentielle.

Nous devons donc retarder l'exécution en préservant a.) la fonction que nous voulons appeler et b .) les arguments avec lesquels nous voulons appeler la fonction, mais sans réellement exécuter la fonction déjà.

C'est ce que delayed fait commodément pour nous avec une syntaxe claire. Si nous voulons "conserver" l'appel foo(2, g=3) pour plus tard, nous pouvons simplement appeler delayed(foo)(2, g=3) et le tuple (foo, [2], {g: 3}) Est retourné, prêt à être exécuté par quelqu'un d'autre.


Donc, dans votre exemple, en bref, ce qui suit se produit.

  1. Vous avez créé une liste de delayed(getHog)(i)

  2. Chacune de ces delayed(getHog)(i) renvoie le Tuple (function, args, kwargs) (Comme vous le lisez dans la documentation) qui est dans ce cas le Tuple (getHog, [i], {})

  3. Votre objet Parallel précédemment construit crée un nouveau thread pour chaque élément de la liste et leur distribue les tuples

  4. Sur chacun de ces nouveaux threads, il exécute l'un des éléments de la liste: il appelle le premier élément du tuple avec les deuxième et troisième éléments décompressés en arguments el[0](*el[1], **el[2]) ou function(*args, **kwargs), qui dans ce cas, entraîne l'appel getHog(i).
28
Nearoo