1
votes

Utilisation de PyTorch avec du céleri

J'essaye d'exécuter un modèle PyTorch dans une application Django. Comme il n'est pas recommandé d'exécuter les modèles (ou toute tâche de longue durée) dans les vues, j'ai décidé de l'exécuter dans une tâche Celery. Mon modèle est assez grand et il faut environ 12 secondes pour charger et environ 3 secondes pour en déduire. C'est pourquoi j'ai décidé que je ne pouvais pas me permettre de le charger à chaque demande. J'ai donc essayé de le charger dans les paramètres et de l'enregistrer là-bas pour que l'application l'utilise. Donc mon dernier schéma est:

  • Lorsque l'application Django démarre, dans les paramètres, le modèle PyTorch est chargé et accessible depuis l'application.
  • Lorsque views.py reçoit une demande, cela retarde une tâche de céleri
  • La tâche céleri utilise le settings.model pour déduire le résultat

Le problème ici est que la tâche de céleri génère l'erreur suivante lors de la tentative d'utilisation du modèle

@task
def getResult(name):
    print("Executing on GPU:", torch.cuda.is_available())
    if os.path.isfile(name):
        try:
            outpath = model_inference(name)
            os.remove(name)
            return outpath
        except OSError as e:
            print("Error", name, "doesn't exist")
    return ""

Voici le code dans mon settings.py chargeant le modèle:

if sys.argv and sys.argv[0].endswith('celery') and 'worker' in sys.argv: #In order to load only for the celery worker
    import torch
    torch.cuda.init()
    torch.backends.cudnn.benchmark = True
    load_model_file()

Et le code de tâche

[2020-08-29 09:03:04,015: ERROR/ForkPoolWorker-1] Task app.tasks.task[458934d4-ea03-4bc9-8dcd-77e4c3a9caec] raised unexpected: RuntimeError("Cannot re-initialize CUDA in forked subprocess. To use CUDA with multiprocessing, you must use the 'spawn' start method")
Traceback (most recent call last):
  File "/home/ubuntu/anaconda3/envs/tensor/lib/python3.7/site-packages/celery/app/trace.py", line 412, in trace_task
    R = retval = fun(*args, **kwargs)
  File "/home/ubuntu/anaconda3/envs/tensor/lib/python3.7/site-packages/celery/app/trace.py", line 704, in __protected_call__
    return self.run(*args, **kwargs)
  /*...*/
  File "/home/ubuntu/anaconda3/envs/tensor/lib/python3.7/site-packages/torch/cuda/__init__.py", line 191, in _lazy_init
    "Cannot re-initialize CUDA in forked subprocess. " + msg)
RuntimeError: Cannot re-initialize CUDA in forked subprocess. To use CUDA with multiprocessing, you must use the 'spawn' start method

L'impression dans la tâche indique "Executing on GPU: true"

J'ai essayé de définir torch.multiprocessing.set_start_method('spawn') dans le settings.py avant et après torch.cuda.init() mais cela donne la même erreur.


0 commentaires

3 Réponses :


1
votes

La définition de cette méthode fonctionne tant que vous utilisez également Process de la même bibliothèque.

from torch.multiprocessing import Pool, Process

Celery utilise une bibliothèque multiprocessing "régulière", d'où cette erreur.

Si j'étais vous, j'essaierais soit:


2 commentaires

Il n'y a pas besoin de "torch.multiprocessing.set_start_method ('spawn')", ni de "from torch.multiprocessing import Pool, Process". L'utilisation de Eventlet et de la concurrence 0 a résolu le problème


single threaded fonctionne aussi - celery -A your_proj worker -P solo y a-t-il un moyen de savoir laquelle est la meilleure solution ici - single threaded in solo pool vs eventlet / gevent avec concurrence 0?



0
votes

Cela est dû au fait que le céleri lui-même utilise la fourche. Cela semble être un problème actuellement connu avec Celery> = 4.0

Vous aviez l'habitude de configurer le céleri pour engendrer, plutôt que pour la fourche, mais cette fonctionnalité ( CELERYD_FORCE_EXECV ) a été supprimée dans la version 4.0 .

Il n'y a pas d'options intégrées pour contourner ce problème. Un monkeypatching personnalisé pour ce faire est probablement possible, mais YMMV

Certaines options potentiellement viables pourraient être:

  • Utilisez du céleri <4.0 avec CELERYD_FORCE_EXECV activé.
  • Lancez les ouvriers de céleri sur Windows (où la fourche n'est pas possible de toute façon)

0 commentaires

1
votes

Une solution rapide consiste à créer un seul thread. Pour ce faire, définissez le type de céleri de la réserve de céleri en solo tout en démarrant le céleri

celery -A your_proj worker -P solo -l info


0 commentaires