将PyTorch与芹菜一起使用



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

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

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

[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

这是我设置中的代码。通过加载模型:

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()

任务代码

@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 ""

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

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

只要同时使用同一库中的Process,设置此方法就可以工作。

from torch.multiprocessing import Pool, Process

芹菜使用";常规的";multiprocessing库,因此出现此错误。

如果我是你,我会试试其中一种:

  • 单线程运行它,看看这是否有帮助
  • 使用eventlet运行它,看看这是否有帮助
  • 读这个

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

celery -A your_proj worker -P solo -l info

这是由于Celery工作程序本身正在使用分叉。这似乎是Celery目前已知的问题>4.0

您过去可以将芹菜配置为产卵,而不是分叉,但该功能(CELERYD_FORCE_EXECV(在4.0中被删除。

没有内置的选项可以绕过这一点。一些自定义的猴痘接种可能是可能的,但YMMV

一些潜在可行的选择可能是:

  • 在启用CELERYD_FORCE_EXECV的情况下使用芹菜<4.0
  • 在Windows上启动芹菜工人(无论如何都不可能分叉(

最新更新