pip install celery
or pip install celery --upgrade
gevent mode : pip install gevent
注意:
celery==5.2.3
, python==3.8
;
python 版本为3.7时,多进程会出现re-initialized错误。
celery -A celery_main:celery worker -l DEBUG --concurrency 1 -P solo
celery: celery -A tasks worker --loglevel=info --pidfile=celery.pid --logfile=celery.log
using purge:
$celery_bin -A celery_main:celery worker -l debug -c $worker_num --purge
purge: Purge messages from all configured task queues.
kill -INT [WorkerMainProcessID] # worker主进程的进程ID需要通过ps -ef | grep celery获取;或者通过 celery -A app inspect stats的输出结果获取
kill -TERM [WorkerMainProcessID]
installation: pip install flower
run: celery -A celery_main:celery flower --port=8080
pool eventlet: eventlet==0.25.1
;
pool gevnet: gevent==1.4
;
celery: celery-5.1.2
(Read the official documents in case of revised api )
在prefork模式下,单独使用一个加载的模型不能实现多进程; 想要实现是的是对于每一个并发量,加载一个模型,即每一个worker根据并发量来控制模型的数量,从而使处理速度增加,负载均衡;
@worker_process_init.connect()
def init_worker_process(**kwargs):
"""
load model before running tasks
:param kwargs:
:return:
"""
global pytorch_model
pytorch_model = load_model()
load_model()
必须是定义在同一个文件下,如果是不同文件,那么在init_worker_process中import相应文件;
from model_threads import loadModel
model_dict = loadModel()
ref:
Unable to use Pytorch with CUDA in Celery task
bind=True
;@task(bind=True, name="my_add")
def add(self, x, y):
return x + y
ref:
Serving ML Models in Production with FastAPI and Celery
class CustomTask(celery.Task):
def after_return(self, status, retval, task_id, args, kwargs, einfo):
try:
th = threading.Thread(target=push_results, args=(retval,))
th.start()
except Exception as e:
raise ActiveException(code=ErrorCode.ABNORMAL, msg='the after return function run error
@task_prerun.connect
def task_prerun_handler(signal, sender, task_id, task, args, kwargs):
tasks[task_id] = time()
@task_postrun.connect
def task_postrun_handler(signal, sender, task_id, task, args, kwargs, retval, state):
try:
cost = time() - tasks.pop(task_id)
ref:
per-task-name
celery中-c参数和-P参数
celery里面的-c参数指定的是并发度,而-P参数指定并发的实现方式,有 prefork(default)、eventlet、gevent等,prefork就是多进程的方式去实现并发。
supervisord 中使用celery
在使用supervisord过程中,应该先退出supervisord,然后再进行celery的kill;
ps auxww | grep celery|grep -v grep|awk '{print $2}'
同下:ps -ef|grep gunicorn|grep -v grep|awk '{print $2}'|xargs -i kill -9 {}
关于tasks结束后,redis依然贮留数据的问题;
对于异步的任务,可直接在任务装饰器中使用ignore_results即可,如@celery.task(base=CustomTask, ignore_result=True)
但是,对于同步任务,即使用get()
获得结果的任务,此方法无效,解决办法在是celery配置文件中设置redis_results过期时间,即result_expires = 300
;
Don’t store task state. Note that this means you can’t use AsyncResult to check if the task is ready, or get its return value.
Received unregistered task of type 'tasks.tasks.detect_img_asy'.
文件层级结构问题;在celery_main
文件中的task路径,需要与主程序导入异步任务函数的路径相同;
如:from tasks.tasks import detect_invasion
和include=['tasks.tasks']
;
@celery_app.task
;name
属性可以声明确定具体路径。@celery.task(name="modelPipline", ignore_result=True)
ModuleNotFoundError: No module named 'celery.app.task'
celery TypeError: 'type' object is not subscriptable
celery cannot combined with flower to start;
celery worker cannot start in srcipts by threaing or process;
RuntimeError: Cannot re-initialize CUDA in forked subprocess. To use CUDA with multiprocessing, you must use the 'spawn' start method
ref: 1
fork 与 spawn 模式的区别;
这里有问题,就是 forked 是啥,spawn 又是啥?这里就需要了解创建子进程的方式了。
通过torch.multiprocessing.Process(target=training, args=(train_queue))
创建一个子进程fork和spawn是构建子进程的不同方式,区别在于
\1. fork: 除了必要的启动资源,其余的变量,包,数据等都集成自父进程,也就是共享了父进程的一些内存页,因此启动较快,但是由于大部分都是用的自父进程数据,所有是不安全的子进程。
\2. spawn:从头构建一个子进程,父进程的数据拷贝到子进程的空间中,拥有自己的Python解释器,所有需要重新加载一遍父进程的包,因此启动叫慢,但是由于数据都是自己的,安全性比较高。回到刚刚那个报错上面去。为啥提示要不能重复加载。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eh9iQy1o-1683875960593)(Notes/fork.png)]
CUDA initialization error
错误原因:
P.S 在celery使用过程中,利用init_worker_process
来根据并发量来创建模型个数时,大概率会出现此问题,主要原因是在model.cuda
或者model.to(device)
之前,有其他CUDA的操作。
例如,在Fairmot进行worker重复加载时,出现此错误主要是因为import DCN
时会进行CUDA上的initialization操作;暂且未找到解决DCNv2包的解决办法,折衷处理是将原来的DCN替换为pytorch中自带的DCN模块,即from .dcn import DeformableConv2d as DCN
, 具体代码参考附录。
4/1添加:
当使用fork模式时,主进程的变量被子进程变量共享,而CUDA的上下文环境是不支持这种共享的,因为CUDA每个子进程的变量都是独立的;
因此才会报re-initialized错误;
解决办法是:在init_worker_process中导入模型,包括:
@worker_process_init.connect
def init_worker_process():
model_id = "stabilityai/stable-diffusion-2"
from diffusers import StableDiffusionPipeline, DDIMScheduler, EulerDiscreteScheduler
# Use the Euler scheduler here instead
scheduler = EulerDiscreteScheduler.from_pretrained(model_id, subfolder="scheduler")
pipe = StableDiffusionPipeline.from_pretrained(model_id, scheduler=scheduler, torch_dtype=torch.float16)
是要统一写在init_worker下的,如果不是这样stablediffusionpipline是被其他子进程共享。
ref:
PyTorch-Deformable-Convolution-v2
TypeError: __init__() got an unexpected keyword argument 'username'
celery中的redis使用localhost有问题,需要指明ip地址;
celery中的redis安装一定需要按照官方文档安装!
$ pip install -U "celery[redis]"
ref:official documents
设置多进程启动方法。
import torch.multiprocessing as mp
mp.set_start_method('spawn')
此方法是使用multiprocessing时需要使用pytorch模型时,需要设置的方法;但是,如果使用fork似乎也运行正常。
CUDA kernel errors might be asynchronously reported at some other API call,so the stacktrace below might be incorrect.
直接运行时export CUDA_LAUNCH_BLOCKING=1
;
运行过程中提升没有torch
-U
的形式安装在.local
, 而在此环境中没有安装pytorch;因此,需要使用在特定的anaconda环境下安装celery,然后使用celery命令时指明位置,如(zzzj_test) zzzj@alpha-AI:~/Projects/task_intrusion_celery/server$ /home/zzzj/.conda/envs/zzzj_nni/bin/celery -A celery_main:celery worker -l INFO -c 1 -P solo
celery使用redis作为broker,报错ConnectionError: Too many connections
主要是在进行高并发测试时,解决方法为将celery.conf.broker_pool_limit = 20
数目调大,默认为10.
TypeError: Object of type ndarray is not JSON serializable
主要原因是redis中储存的数据不能是自定义的数据类型或者numpy.array类型,对于图像数据转换为base64,对于自定义数据类型,使用object.__dict__
以字符串形式传递。
ImportError:cannot import name ‘Celery‘ from ‘celery
python 版本和celery版本问题。
RuntimeError: Never call result.get() within a task!
使用celery canvas中的group任务类型实现分组任务
Celery批量异步调用任务一直等待结果
使用group异步调用时,如果一直等待结果,部分原因是任务没有保存结果,即ignore_result=True; 应该设置为默认值False;
使用两个celery时,会出现 Received unregistered task of type 'celery.atomTask'.
Celery: stuck in infinitly repeating timeouts (Timed out waiting for UP message)
主要是worker在init时耗时过长,提升PROC_ALIVE_TIMEOUT
时长;
RuntimeWarning:You're running the worker with superuser privileges:this is absolutely not recommended
from celery import platforms
platforms.C_FORCE_ROOT=True
或者使用uid,ugroup
exec celery --app=app worker \
--loglevel=INFO --logfile=/var/log/celery/worker-example.log \
--statedb=/var/run/celery/worker-example@%h.state \
--hostname=worker-example@%h \
--queues=celery.example -O fair \
--uid=nobody --gid=nogroup
当两者无效时,使用multi运行时,就可以了。
celery在docker中使用时,会出现stuck现象,
主要原因是docker需要使用本机的redis;(保留)
ref:
Celery: number of workers vs concurrency
Celery Task中一些有用的回调函数
Python分布式任务框架Celery的异步任务实现
Unable to use Pytorch with CUDA in Celery task