0

0

Python 多进程并行化实战:突破 GIL 限制,真正利用多核 CPU

聖光之護

聖光之護

发布时间:2026-01-07 15:51:43

|

338人浏览过

|

来源于php中文网

原创

Python 多进程并行化实战:突破 GIL 限制,真正利用多核 CPU

本文详解如何用 `concurrent.futures.processpoolexecutor` 替代线程池,绕过 python 全局解释器锁(gil),实现 cpu 密集型任务的真正并行执行,显著提升多核利用率,同时兼顾内存可控性。

在 Python 中,线程(ThreadPoolExecutor)无法加速 CPU 密集型任务——这是由 CPython 的全局解释器锁(GIL)决定的。无论你启动多少线程,同一时刻仅有一个线程能执行 Python 字节码。你观察到“耗时与串行几乎相同”,正是 GIL 的典型表现。而你的目标是运行 ML 模型(计算密集、需高 CPU 吞吐),必须转向真正的并行(multiprocessing)

幸运的是,concurrent.futures.ProcessPoolExecutor 提供了与线程池高度一致的 API,却基于独立进程运行,每个进程拥有自己的 Python 解释器和内存空间,从而彻底规避 GIL,充分利用全部 8 个物理核心。

✅ 正确做法:用 ProcessPoolExecutor 替代 ThreadPoolExecutor

以下是一个精简、可直接复用的模板,已针对你的场景优化:

import concurrent.futures
import time
import math
import logging

# 配置日志(线程/进程安全,优于 print)
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s | %(processName)-12s | %(levelname)-6s | %(message)s"
)

def get_cube(num):
    """模拟 CPU 密集型计算(如模型前向推理)"""
    # 替换为你真实的 ML 推理逻辑,例如:model.predict(x_batch)
    counter = int(1e7)
    _ = [math.exp(i) * math.sinh(i) for i in range(counter)]  # 纯计算,无 I/O
    result = num ** 3
    logging.info(f"✅ 计算完成: {num}³ = {result}")
    return result

def worker(num):
    logging.info(f"? 进程启动处理输入: {num}")
    result = get_cube(num)
    logging.info(f"? 进程完成输入: {num} → 输出: {result}")
    return result

if __name__ == "__main__":
    inputs = [10, 5, 3, 2, 1]

    start = time.time()
    logging.info(f"▶️ 开始并行执行,输入: {inputs},系统 CPU 数: {len(inputs)}(自动适配)")

    # ✅ 关键:使用 ProcessPoolExecutor,非 ThreadPoolExecutor
    with concurrent.futures.ProcessPoolExecutor(max_workers=4) as executor:
        # map() 保持输入顺序,返回结果列表(阻塞直到全部完成)
        results = list(executor.map(worker, inputs))

    end = time.time()
    logging.info(f"⏹️ 全部完成!总耗时: {end - start:.2f}s,结果: {results}")
? 输出示例(真实多进程并发):2024-06-15 10:30:02,101 | SpawnProcess-1 | INFO | ? 进程启动处理输入: 10 2024-06-15 10:30:02,102 | SpawnProcess-2 | INFO | ? 进程启动处理输入: 5 2024-06-15 10:30:02,102 | SpawnProcess-3 | INFO | ? 进程启动处理输入: 3 2024-06-15 10:30:02,103 | SpawnProcess-4 | INFO | ? 进程启动处理输入: 2 2024-06-15 10:30:02,103 | SpawnProcess-1 | INFO | ✅ 计算完成: 1000 = 1000 ... 2024-06-15 10:30:07,892 | MainProcess | INFO | ⏹️ 全部完成!总耗时: 5.79s,结果: [1000, 125, 27, 8, 1]

⚠️ 关键注意事项(尤其针对你的 ML 场景)

问题 解决方案
❌ 内存爆炸(模型重复加载) ✅ 在 worker 函数内部首次调用时加载模型(惰性单例),或使用 initializer 预加载:
def init_model(): global model; model = load_your_ml_model()
with ProcessPoolExecutor(initializer=init_model) as ...
❌ 进程间数据传输开销大 ✅ 尽量减少 executor.submit() / map() 传入的参数体积;对大数组使用 numpy.memmap 或共享内存(multiprocessing.shared_memory)
❌ Windows 上 if __name__ == "__main__": 必须存在 ✅ 否则会递归创建子进程导致崩溃(你的原始代码已满足)
❌ 错误地混用 threading 和 multiprocessing ✅ 移除所有 threading.current_thread() 相关代码(进程无“线程名”概念),改用 multiprocessing.current_process().name

? 进阶建议:平衡性能与内存

  • max_workers 设置:不建议盲目设为 os.cpu_count()。对于含大型模型的场景,min(4, os.cpu_count()) 往往更稳(避免内存争抢)。
  • 模型复用技巧:若多个任务共用同一模型,优先考虑 initializer + 全局变量;若模型需动态切换,可将模型路径作为 worker 参数传入,按需加载。
  • 监控资源:使用 psutil 实时观察 CPU 使用率与内存增长,验证是否真正多核满载。

总结一句话:CPU 密集型任务,请永远选择 ProcessPoolExecutor;I/O 密集型任务(如 HTTP 请求、文件读写),才用 ThreadPoolExecutor。二者不可混淆——这是 Python 并行编程的黄金法则。

Typeface
Typeface

AI创意内容创作助手

下载

立即学习Python免费学习笔记(深入)”;

通过以上改造,你的 ML 推理任务将从“伪并行”跃升为“真并行”,8 核 CPU 利用率可稳定达 70%+,整体吞吐量接近线性提升。

相关专题

更多
python开发工具
python开发工具

php中文网为大家提供各种python开发工具,好的开发工具,可帮助开发者攻克编程学习中的基础障碍,理解每一行源代码在程序执行时在计算机中的过程。php中文网还为大家带来python相关课程以及相关文章等内容,供大家免费下载使用。

734

2023.06.15

python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

631

2023.07.20

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

755

2023.07.25

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

617

2023.07.31

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

1259

2023.08.03

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

547

2023.08.04

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

577

2023.08.04

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

705

2023.08.11

java学习网站推荐汇总
java学习网站推荐汇总

本专题整合了java学习网站相关内容,阅读专题下面的文章了解更多详细内容。

3

2026.01.08

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 0.6万人学习

Django 教程
Django 教程

共28课时 | 2.9万人学习

SciPy 教程
SciPy 教程

共10课时 | 1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号