V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
gosky
V2EX  ›  Python

Python asyncio 中怎么执行 cpu 密集型任务?

  •  
  •   gosky · 151 天前 · 2924 次点击
    这是一个创建于 151 天前的主题,其中的信息可能已经有所发展或是发生改变。
    理论上讲,两个办法:
    一、多线程,但不知道怎么全局解释锁被优化得怎么样
    二、多进程,消耗更多内存,因为需要加载模型,内存复制必须要考虑。多进程管理是个麻烦,启动耗时也得考虑

    期望有个轻量级的开源程序,轻松完成这个活……
    第 1 条附言  ·  151 天前
    其中的 cpu 密集型,依赖 python 库
    第 2 条附言  ·  151 天前
    问了下 ai ,pytorch c 扩展大部分会释放 gil ,于是决定采用多线程的方式
    但……实际运行后,发现虽然自己撸灵活,还是专用推理服务更节省资源
    25 条回复    2024-08-02 10:49:58 +08:00
    changz
        1
    changz  
       151 天前 via Android
    多线程+c/c++ ffi
    gaogang
        2
    gaogang  
       151 天前
    cpu 密集的任务 用其他合适的语言实现
    然后通过 rpc 暴露出来 正好给 python 的 asyncio 调
    lambdaq
        3
    lambdaq  
       151 天前   ❤️ 1
    asyncio 顾名思义是 异步 io 。。。众所周知,py 要么卡 cpu 要么卡 io ,asyncio 只解决卡 io 的问题啊。
    ysn2233
        5
    ysn2233  
       151 天前   ❤️ 1
    用 c/c++/rust 的 ffi 做 binding 吧,实在不行 java/go 什么的也行,python 就做个前端调一下
    mirrornighth
        6
    mirrornighth  
       151 天前
    多进程
    ipwx
        7
    ipwx  
       151 天前
    “因为需要加载模型,内存复制必须要考虑。”

    你是啥模型。有些模型开多线程是可以并行的。
    Goooooos
        8
    Goooooos  
       151 天前
    python 3.13 可以加个参数去掉 GIL
    guochao
        9
    guochao  
       151 天前
    针对锁和 python 效率的问题:
    - 如果你的计算任务可以用 c/rust 的模块,最好是在 c/rust 的部分处理,最好能批处理
    - 如果是 pure python ,也许可以试试 taichi 或者类似的东西。因为 python 可以被再次编译成 native 或者 gpu kernel ,并针对架构优化
    针对 asyncio 只管异步切换,计算存在长时间阻塞的问题
    - (不同进程、单独服务的方案)要么 celery ,或者自己搓一个简单的队列
    - (简单在同一个进程中的方案)要么 thread pool executor
    chenqh
        11
    chenqh  
       151 天前
    你加载的模型很大吗?不然想不出来为什么不用多进程
    ruanimal
        12
    ruanimal  
       151 天前
    跑模型还是多进程好
    razertory
        13
    razertory  
       151 天前
    asyncio 是做 IO 密集任务的,不是做 CPU 密集任务
    scipelaina
        14
    scipelaina  
       151 天前
    `asyncio.to_thread`; `concurrent.futures`.
    日经问题,Mark as Duplicated.
    wujian752
        15
    wujian752  
       151 天前 via iPhone
    如果是神经网络模型现在 onnxruntime 在 inference 的时候可以不受 GIL 影响
    crackidz
        16
    crackidz  
       151 天前
    Python 主要冷启动耗时几十 ms 左右,剩下的交到你的代码中了,启动时间主要取决于你的代码吧...

    上面说的基本差不多了,但现在不推荐用那个 nogil 版本,要改你的代码支持部分功能,第三方库也未见得支持。另外还有一些隐蔽 bug...
    yoiteshaw
        17
    yoiteshaw  
       151 天前   ❤️ 1
    我工作中遇到过类似的事情,两年前,无论怎么优化都收效甚微,多线程因为 GIL 反而更慢,最后不得已用多进程去做,用 socket 去通信。
    今年我推翻用 rust 重写了,一些逻辑直接的遍历,简简单单 pair_iter 解决,心情舒畅。
    sagaxu
        18
    sagaxu  
       151 天前
    Python 的 CPU 密集型库大都用 C 实现,大部分时间不会持有 GIL
    skuuhui
        19
    skuuhui  
       151 天前
    最简单是写个 c++模块,用 python 去调。
    其他方法有
    1. 换个没锁的解释器
    2. wasm
    3. https://numba.pydata.org/https://www.trypyjion.com/
    Nich0la5
        20
    Nich0la5  
       151 天前
    asyncio 就不是给你做 cpu 密集型用的
    gray0
        21
    gray0  
       151 天前
    何必多 BB 直接上代码

    from concurrent.futures import ProcessPoolExecutor
    import asyncio

    async def integration_process_and_gather():
    with ProcessPoolExecutor() as process_pool:
    loop = asyncio.get_running_loop()
    numbers = [100000000, 1, 100, 10000, 1000000, 1000, 100000]
    tasks = [
    loop.run_in_executor(process_pool, do_count_number, n) for n in numbers
    ]
    [print(type(task)) for task in tasks]
    results = await asyncio.gather(*tasks)
    print(f"integration_hello_world {results}")
    yh7gdiaYW
        22
    yh7gdiaYW  
       151 天前
    简单点就多进程,复杂点就上 ray ,可以分布式计算用得很爽
    lttzzlll
        23
    lttzzlll  
       149 天前
    你提出的问题,限制你的思路。web 服务要简单,轻量,快速响应。推理服务耗时耗资源。正确的方式应该是 同一个项目(git repo),部署多个进程。经典的做法应该是 一个 web 服务进程,多个 worker 进程,web 服务和 worker 进程之间用队列。以 django/flask 举例:
    lttzzlll
        24
    lttzzlll  
       149 天前
    @lttzzlll 。。。你面的问题不是“Python asyncio 中怎么执行 cpu 密集型任务?”。 换成其他的 web 框架或语言,就没有这种问题了吗?而是在 web 服务中,如何处理比较耗时/耗资源的任务。这些问题都有很经典很成熟的方案。把这类任务放到 worker 节点上,用队列传递消息,不够就增加 replica 的数量。非常成熟和广泛使用的方案,你的场景也不例外。
    cooljiang
        25
    cooljiang  
       142 天前
    CPU 密集型任务建议换个没 GIL 的 Python 解释器,如 PyPy 之类的。
    关于 GIL: https://mp.weixin.qq.com/s/lIkcTuCX5htQcteklCFaZw
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2542 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 04:22 · PVG 12:22 · LAX 20:22 · JFK 23:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.