J'utilise essentiellement le module de multiprocessing, j'apprends toujours les capacités du multiprocessing. J'utilise le livre de Dusty Phillips et ce code lui appartient.
import multiprocessing
import random
from multiprocessing.pool import Pool
def prime_factor(value):
factors = []
for divisor in range(2, value-1):
quotient, remainder = divmod(value, divisor)
if not remainder:
factors.extend(prime_factor(divisor))
factors.extend(prime_factor(quotient))
break
else:
factors = [value]
return factors
if __name__ == '__main__':
pool = Pool()
to_factor = [ random.randint(100000, 50000000) for i in range(20)]
results = pool.map(prime_factor, to_factor)
for value, factors in Zip(to_factor, results):
print("The factors of {} are {}".format(value, factors))
Sur Windows PowerShell (pas sur le portable jupyter), je vois ce qui suit
Process SpawnPoolWorker-5:
Process SpawnPoolWorker-1:
AttributeError: Can't get attribute 'prime_factor' on <module '__main__' (built-in)>
Je ne sais pas pourquoi la cellule ne s'arrête jamais de fonctionner?
Il semble que le problème dans le cahier Jupyter comme dans une autre idée soit la fonctionnalité de conception. Par conséquent, nous devons écrire la fonction (prime_factor) dans un fichier différent et importer le module. De plus, nous devons nous occuper des ajustements. Par exemple, dans mon cas, j'ai codé la fonction dans un fichier appelé defs.py
def prime_factor(value):
factors = []
for divisor in range(2, value-1):
quotient, remainder = divmod(value, divisor)
if not remainder:
factors.extend(prime_factor(divisor))
factors.extend(prime_factor(quotient))
break
else:
factors = [value]
return factors
Puis dans le cahier jupyter j'ai écrit les lignes suivantes
import multiprocessing
import random
from multiprocessing import Pool
import defs
if __name__ == '__main__':
pool = Pool()
to_factor = [ random.randint(100000, 50000000) for i in range(20)]
results = pool.map(defs.prime_factor, to_factor)
for value, factors in Zip(to_factor, results):
print("The factors of {} are {}".format(value, factors))
Cela a résolu mon problème
Pour exécuter une fonction sans avoir à l'écrire manuellement dans un fichier séparé:
Nous pouvons écrire dynamiquement la tâche à traiter dans un fichier temporaire, l'importer et exécuter la fonction.
from multiprocessing import Pool
from functools import partial
import inspect
def parallal_task(func, iterable, *params):
with open(f'./tmp_func.py', 'w') as file:
file.write(inspect.getsource(func).replace(func.__name__, "task"))
from tmp_func import task
if __name__ == '__main__':
func = partial(task, params)
pool = Pool(processes=8)
res = pool.map(func, iterable)
pool.close()
return res
else:
raise "Not in Jupyter Notebook"
Nous pouvons alors simplement l'appeler dans une cellule de carnet comme ceci:
def long_running_task(params, id):
# Heavy job here
return params, id
data_list = range(8)
for res in parallal_task(long_running_task, data_list, "a", 1, "b"):
print(res)
Sortie:
('a', 1, 'b') 0
('a', 1, 'b') 1
('a', 1, 'b') 2
('a', 1, 'b') 3
('a', 1, 'b') 4
('a', 1, 'b') 5
('a', 1, 'b') 6
('a', 1, 'b') 7
Remarque: Si vous utilisez Anaconda et si vous souhaitez voir la progression de la tâche lourde, vous pouvez utiliser print()
dans long_running_task()
. Le contenu de l'impression sera affiché dans la console Anaconda Prompt.