将 PyTorch 与 Celery 结合使用

JOS*_*UEN 5 python django multiprocessing celery pytorch

我正在尝试在 Django 应用程序中运行 PyTorch 模型。由于不建议在视图中执行模型(或任何长时间运行的任务),我决定在 Celery 任务中运行它。我的模型很大,加载大约需要 12 秒,推断大约需要 3 秒。这就是为什么我决定不能在每次请求时都加载它。所以我尝试在设置中加载它并将其保存在那里供应用程序使用。所以我的最终方案是:

  • 当 Django 应用程序启动时,在设置中会加载 PyTorch 模型并且可以从应用程序访问它。
  • 当 views.py 收到请求时,它会延迟 celery 任务
  • celery 任务使用 settings.model 来推断结果

这里的问题是celery任务在尝试使用模型时抛出以下错误

[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
Run Code Online (Sandbox Code Playgroud)

这是我的 settings.py 中加载模型的代码:

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()
Run Code Online (Sandbox Code Playgroud)

和任务代码

@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 ""
Run Code Online (Sandbox Code Playgroud)

任务中的打印显示 "Executing on GPU: true"

我已经尝试torch.multiprocessing.set_start_method('spawn')在 settings.py 之前和之后进行设置,torch.cuda.init()但它给出了相同的错误。

小智 8

一个快速的解决方法是使事情成为单线程。为此,在启动 celery 工作线程时将 celery 的工作池类型设置为 single

celery -A your_proj worker -P solo -l info
Run Code Online (Sandbox Code Playgroud)


Krz*_*arz 5

只要您还使用Process同一个库,设置此方法就可以工作。

from torch.multiprocessing import Pool, Process
Run Code Online (Sandbox Code Playgroud)

Celery 使用“常规”multiprocessing库,因此出现此错误。

如果我是你,我会尝试:

  • 不需要“torch.multiprocessing.set_start_method('spawn')”或“from torch.multiprocessing import Pool, Process”。使用eventlet和并发0解决了问题 (2认同)