Prompts-MCP 686 skills · ai / design / design-pattern / framework / fundamentals / habit / lang / tech-selection /mcp/sse
lang lang/python/performance/process-vs-thread-vs-async.md high

py-perf-process-vs-thread-vs-async

Python 并发模型选型 — CPU 密集走多进程、I/O 密集走 async、阻塞库走线程,及 free-threading 影响。Use when 选并发模型 / 绕开 GIL / CPU 与 IO 任务提速。

并发选型gil多进程multiprocessingprocesspoolexecutorasyncio
paths
  • *.py
  • py/**/*.py

Python · 并发模型选型

这里只回答「选哪个模型」。具体 asyncio 写法见 ../async/asyncio-pattern.md

核心约束:CPython 默认有 GIL,多线程跑不满多核做 CPU 密集任务。先判断任务是 CPU 密集还是 I/O 密集。

规则

任务类型 选什么 为什么
CPU 密集(计算/编码/压缩) multiprocessing / ProcessPoolExecutor 每进程独立解释器,绕开 GIL,吃满多核
I/O 密集(网络/磁盘/DB,库支持 async) asyncio 单线程协程,万级并发连接、内存开销最小
I/O 密集,但只有同步阻塞库 ThreadPoolExecutor / asyncio.to_thread 阻塞时 GIL 释放,线程可重叠 I/O 等待
已在 async 里却要跑 CPU 重活 run_in_executor(ProcessPool) 别在事件循环里算,会卡死所有协程

正例

from concurrent.futures import ProcessPoolExecutor

# CPU 密集:多进程吃满多核
def crunch(chunk: bytes) -> int:
    return sum(expensive_transform(b) for b in chunk)

with ProcessPoolExecutor() as pool:
    totals = list(pool.map(crunch, split_into_chunks(data)))
import asyncio

# I/O 密集 + 支持 async 的客户端:协程并发
async def fetch_all(urls: list[str]) -> list[bytes]:
    async with httpx.AsyncClient() as client:
        return await asyncio.gather(*(client.get(u) for u in urls))
# 在 async 上下文里调阻塞库:丢给线程,别阻塞事件循环
def blocking_pdf_render(doc: bytes) -> bytes: ...

async def handler(doc: bytes) -> bytes:
    return await asyncio.to_thread(blocking_pdf_render, doc)

反例

# ❌ 用线程池做 CPU 密集 —— GIL 让它们串行执行,4 线程 ≈ 1 核
with ThreadPoolExecutor(max_workers=4) as pool:
    pool.map(crunch, chunks)        # 加速比接近 1,白忙

# ❌ 在事件循环里直接跑重计算 —— 阻塞期间所有协程全部停摆
async def handler(data):
    return heavy_cpu_work(data)     # 应 run_in_executor(ProcessPool)

理由:GIL 同一时刻只让一个线程执行 Python 字节码,CPU 密集任务用线程无加速,必须用进程。free-threading 构建(3.13 实验 / 3.14 PEP 779 官方支持)可移除 GIL 让线程真并行,但单线程性能有约 5-10% 损耗,且依赖需全部兼容 no-GIL,迁移前务必实测。

自检

  • [ ] 先判断了 CPU 密集还是 I/O 密集,再选模型?
  • [ ] CPU 密集用进程(不是线程)绕开 GIL?
  • [ ] async 上下文里的阻塞调用都丢进 executor,没卡事件循环?
  • [ ] 评估 free-threading 时实测过单线程损耗与依赖兼容性?

相关