EADST

Python 多线程 vs 多进程对比

🎯 背景

你是否也遇到过这种情况:

明明 CPU 是多核的,代码也用了 ThreadPoolExecutor 开了很多线程,结果速度不仅没有变快,反而变慢了……

最近,我就踩了这个坑:处理 GGUF 模型文件中的张量数据时,原始多线程版本耗时 300 分钟,而换成多进程后,只用了 3 分钟,性能差距高达 100 倍!


🧱 为什么多线程在 Python 中这么慢?

罪魁祸首就是 Python 的 GIL(全局解释器锁)。

GIL 是什么?

在 CPython(最常用的 Python 解释器)中,GIL 是一个互斥锁,用于保证任何时刻只有一个线程能执行 Python 字节码。

GIL 的影响:

  • ✅ I/O 密集型任务(如网络请求、文件读写):线程会在等待时释放 GIL,效率还不错。
  • ❌ 计算密集型任务(如矩阵计算、数据转换):所有线程争抢 GIL,根本没法并行,性能下降!

✅ 正确做法:使用多进程

GIL 只存在于单个进程中,多进程意味着每个子进程有自己的 GIL,可以在多个 CPU 核心上并行运行。


🧪 实战代码对比


🚫 多线程版本(ThreadPoolExecutor)

from concurrent.futures import ThreadPoolExecutor, as_completed
from tqdm import tqdm

def process_tensor(tensor):
    # 模拟计算密集型任务
    return tensor.name, tensor.data.sum()

if __name__ == '__main__':
    tasks_to_process = [...]  # 张量任务列表

    results = []
    with ThreadPoolExecutor(max_workers=8) as executor:
        futures = {
            executor.submit(process_tensor, t): t.name
            for t in tasks_to_process
        }

        for future in tqdm(as_completed(futures), total=len(futures), desc="Threading"):
            results.append(future.result())

⏱️ 耗时约 300 分钟,CPU 利用率低。


🚀 多进程版本(ProcessPoolExecutor)

from concurrent.futures import ProcessPoolExecutor, as_completed
from tqdm import tqdm

def process_tensor(tensor):
    return tensor.name, tensor.data.sum()

if __name__ == '__main__':
    tasks_to_process = [...]  # 张量任务列表

    results = []
    with ProcessPoolExecutor() as executor:  # 默认使用所有核心
        futures = {
            executor.submit(process_tensor, t): t.name
            for t in tasks_to_process
        }

        for future in tqdm(as_completed(futures), total=len(futures), desc="Multiprocessing"):
            results.append(future.result())

⚡ 耗时仅 3 分钟,CPU 多核并行利用率高。


✅ 结果输出(通用)

for name, result in results:
    print(f"{name}: {result}")

📊 对比总结

| 类型  | 实现方式                | 预计耗时     | 核心利用率        |
| 多线程 | ThreadPoolExecutor  | \~300 分钟 | ❌ 低,受 GIL 限制 |
| 多进程 | ProcessPoolExecutor | \~3 分钟   | ✅ 高,真并行      |

📌 何时用线程?何时用进程?

| 任务类型    | 推荐方式  | 原因             |
| CPU 密集型 | ✅ 多进程 | 避免 GIL,真正并行    |
| I/O 密集型 | ✅ 多线程 | 阻塞时释放 GIL,提高吞吐 |

🛠️ 小贴士

  • tqdm(as_completed(...)) 让你轻松跟踪任务完成进度。
  • 多进程任务函数必须能被 Pickle 序列化。
  • 若需支持错误捕获、失败重试、进度恢复,可结合日志模块扩展。

🧠 最后总结

Python 并发并不神秘,关键在于:

  • 辨别任务类型(CPU-bound vs I/O-bound)
  • 选对模型(Threading vs Multiprocessing)

一旦用对方式,性能可不是提升一点,而是飞跃几十倍、甚至百倍!

相关标签
About Me
XD
Goals determine what you are going to be.
Category
标签云
mmap LaTeX News Augmentation 第一性原理 VSCode LoRA Diagram NameSilo Nginx TSV Transformers Linux UI Tracking AI 多线程 LLAMA Clash Crawler Django COCO Quantize Anaconda FastAPI GGML RAR tar 云服务器 Distillation FP32 Video PDB Pickle Knowledge llama.cpp LeetCode CV Cloudreve VPN 多进程 SVR API网关 GIT git 算法题 Tiktoken hf Bitcoin C++ icon Git 论文 Statistics Llama OpenCV Card QWEN 财报 Magnet 证件照 Agent Miniforge Harness Hungarian Qwen2.5 Safetensors WebCrawler FlashAttention NLTK Hotel WAN Pandas TTS Password Streamlit SQLite HaggingFace GPTQ Qwen LLM Claude Image2Text CTC Plate SQL 图形思考法 Jupyter 公式 Ptyhon 递归学习法 Heatmap Freesound Rebuttal Hilton Permission Jev Quantization CSV BF16 tqdm CC MD5 logger 图标 Zip 报税 腾讯云 Random v2ray ms-swift SPIE Excel FP16 Breakpoint SAM RL printf uwsgi Numpy Mixtral 阿里云 Gemma Color GoogLeNet DeepSeek 顶会 Github git-lfs Data Input Logo Animate Paper diffusers Bin VGG-16 Proxy ONNX TensorRT XGBoost ModelScope Firewall Conda GPT4 Shortcut XML scipy BeautifulSoup 净利润 JSON EXCEL 继承 HuggingFace IndexTTS2 Vim Pillow Tensor 版权 PDF Baidu Template 音频 CEIR Markdown Dataset ResNet-50 Base64 Docker Review Website Plotly Michelin Interview Jetson OpenAI Domain Attention PyTorch Math FP64 签证 CAM Web Search Land YOLO Pytorch torchinfo Sklearn RGB 飞书 UNIX 关于博主 uWSGI Ubuntu Bipartite 域名 Use 论文速读 TensorFlow 强化学习 DeepStream Disk FP8 PIP Google BTC Vmess NLP Paddle Datetime 搞笑 Translation Python CLAP API Food CUDA InvalidArgumentError Qwen2 v0.dev PyCharm Windows Bert ChatGPT OCR transformers Algorithm
站点统计

本站现有博文337篇,共被浏览961437次

本站已经建立2673天!

热门文章
文章归档
回到顶部