是否可以在启动时将变量传递给芹菜工人,并在执行时在工人内部使用它?
我正在写服务器,将负责机器学习培训和评估。我想动态地启动worker的新实例,并将变量传递给它,该变量将用于加载内部的特定模型。
我发现如何用worker_main方法从答案here开始工作。
我在考虑两个解决方案:
设为环境变量。此解决方案的问题是,当同时创建两个worker实例时,它可能会损坏。
将其作为argv传递,但我不知道如何读取worker中的变量。
编辑
我找到了this线程,但它只谈到在任务中访问自定义参数。我的问题是在工人初始化时访问它。
灵感来自this线,我会尝试芹菜信号。
http://docs.celeryproject.org/en/latest/userguide/signals.html#worker-init

最佳答案

也许我的问题不够准确,但我自己用doc和stackoverflow线程找到了答案。
我想为凯拉斯模特单独经营一个工人在工作机初始化中,我需要将模型加载到内存中,在任务中,模型用于预测。
我的解决方案:
用model\u id命名worker(因为id是唯一的,而且每个model只需要一个worker)
在celerid_after_setup signal函数中,我在worker中解析了名称并设置了全局变量
在worker_process_in it signal函数中,我在本例中加载了model,它是Grasper类中的静态字段
在任务中,我使用了grasper类中的静态字段
下面是一些精确描述解决方案的代码。

from celery.signals import worker_process_init, celeryd_after_setup
from celery.concurrency import asynpool

# my custom class containing static fields for model and tokenizer
# it also can be global variable as model_id
from myapp.ml import Grasper

# set to have some time for model loading otherwise worker_process_init can terminate
asynpool.PROC_ALIVE_TIMEOUT = 100.0
model_id = None

@celeryd_after_setup.connect()
def set_model_id(sender, instance, **kwargs):
    global model_id
    model_id = instance.hostname.split('@')[1]

@worker_process_init.connect()
def configure_worker(signal=None, sender=None, **kwargs):
    Grasper.load_model(model_id)

然后在芹菜任务中,可以使用带有加载模型的Grasper类。
这个解决方案有效,但我知道有一个改进的地方,所以如果你有一些想法,请评论。

07-28 02:12
查看更多