Si vous effectuez un apprentissage automatique ou une exécution approfondie avec Python, le traitement devient lourd et peut poser un problème en termes de performances.
Récemment, j'ai également un traitement intensif et j'ai décidé d'ajouter un traitement parallèle pour améliorer les performances.
Une amélioration des performances a été observée en utilisant une bibliothèque de traitement parallèle appelée joblib
localement.
Cependant, dans l'erreur qui a exécuté le même processus sur l'environnement de développement. .. .. Apparemment, joblib ne fonctionne pas dans l'environnement uWSGI. J'ai résumé les mesures à ce sujet.
――UWSGI est un serveur d'applications permettant d'exécuter des services Web en Python.
length = 1000
def sum(i, j):
return i + j
--Parallélisation
from joblib import Parallel, delayed
sum_list = Parallel(n_jobs=-1)( [delayed(calc_sum)(i, j) for j in range(length) for i in range(length)])
-Cependant, quand je l'exécute sur uWSGI, j'obtiens une erreur comme celle-ci
exception calling callback for <Future at 0x7fbc520c7eb8 state=finished raised TerminatedWorkerError>
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/joblib/externals/loky/_base.py", line 625, in _invoke_callbacks
callback(self)
File "/usr/local/lib/python3.7/site-packages/joblib/parallel.py", line 309, in __call__
self.parallel.dispatch_next()
File "/usr/local/lib/python3.7/site-packages/joblib/parallel.py", line 731, in dispatch_next
if not self.dispatch_one_batch(self._original_iterator):
File "/usr/local/lib/python3.7/site-packages/joblib/parallel.py", line 759, in dispatch_one_batch
self._dispatch(tasks)
File "/usr/local/lib/python3.7/site-packages/joblib/parallel.py", line 716, in _dispatch
job = self._backend.apply_async(batch, callback=cb)
File "/usr/local/lib/python3.7/site-packages/joblib/_parallel_backends.py", line 510, in apply_async
future = self._workers.submit(SafeFunction(func))
File "/usr/local/lib/python3.7/site-packages/joblib/externals/loky/reusable_executor.py", line 151, in submit
fn, *args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/joblib/externals/loky/process_executor.py", line 1022, in submit
raise self._flags.broken
joblib.externals.loky.process_executor.TerminatedWorkerError: A worker process managed by the executor was unexpectedly terminated. This could be caused by a segmentation fault while calling the function or by an excessive memory usage causing the Operating System to kill the worker. The exit codes of the workers are {EXIT(1), EXIT(1), EXIT(1), EXIT(1)}
from joblib import Parallel, delayed
sum_list = Parallel(n_jobs=-1, prefer='threads')( [delayed(calc_sum)(i, j) for j in range(length) for i in range(length)])
――Bien sûr, en fonction du traitement, cela peut être lent si vous utilisez des threads.
import multiprocessing
from multiprocessing import Process
with multiprocessing.Pool() as pool:
process = [pool.apply_async(calc_sum, (i, j)) for j in range(length) for i in range(length)]
sum_list = [f.get() for f in process]
Je n'ai pas fait ça cette fois. La raison en est que changer le serveur AP est risqué car il fonctionnait déjà sur uWSGI.
Ordinaire | joblib(multiprocess) | joblib(threads) | multiprocessing |
---|---|---|---|
32.9 µs | 11 µs | 40.1 µs | 4.05 µs |
Joblib est plus lisible et plus facile à écrire, mais le multitraitement est une fonctionnalité intégrée à Python lui-même, donc il surpasse souvent. De plus, il semble peu probable que vous fassiez une erreur comme celle-ci.