Python 3.13无GIL并行实战:多线程CPU密集型任务的性能飞跃

2026-06-20 0 710

受够了GIL?过去想利用多核CPU跑Python计算,要么用多进程(内存开销大、上下文切换成本高),要么换语言写扩展。Python 3.13终于以实验性方式引入“free-threading”构建——也就是大家常说的无GIL模式。装了特定版本的Python后,多线程不再被一把大锁捆住手脚,真正的并行计算在标准库的threading上就能生效。

这篇文章会带着你从下载安装free-threaded Python开始,写一个计算密集型的素数查找函数,再用多线程在普通Python 3.13和无GIL版之间做一个看得见的性能对比。读完以后,你应该能独立验证Python无GIL到底有多大的威力,以及判断自己的项目能不能用上它。

要理解的前提:这仍然是个实验

首先得知道,Python 3.13提供的free-threading构建默认是选择性启用的,也就是说你从python.org下载的普通安装包并不会去掉GIL,必须专门找带free-threaded字样的版本。另外,为了兼容性,许多C扩展在无GIL模式下可能还不稳定,所以生产环境要谨慎评估。不过对纯Python的计算任务和大部分numpy、lxml等核心库,已经初步支持了。

一句话:你可以在自己电脑上先试试水温,看看哪些工作流受益最大。

第一步:下载free-threaded Python 3.13

python.org的3.13下载页面,往下翻到“Files”区域,找一个文件名里包含free-threaded的安装包。例如Windows下可能是python-3.13.0-amd64-free-threaded.exe,macOS下是python-3.13.0-macos11.pkg里注明free-threaded的变体,或者Linux下使用源码编译加--disable-gil选项。

安装时记得勾选“Add to PATH”,并且注意不要覆盖已有的Python 3.13标准版本。安装后,在命令行输入python3.13t(注意末尾的t)可以启动自由线程的解释器。Linux下可能直接叫python3.13tpython3.13t-free-threaded。确认一下:

python3.13t -c "import sys; print(sys._is_gil_enabled())"

如果打印False,恭喜,你正在无GIL模式下运行。

第二步:编写一个CPU密集型任务

我们选一个简单但耗时的计算:找出小于给定上限的所有素数。实现一个朴素的试除法,这样既能消耗CPU,代码又容易理解。

# primes.py
def count_primes(limit: int) -> int:
    """返回小于limit的素数个数"""
    if limit < 2:
        return 0
    is_prime = [True] * limit
    is_prime[0] = is_prime[1] = False
    for i in range(2, int(limit ** 0.5) + 1):
        if is_prime[i]:
            step = i
            start = i * i
            is_prime[start:limit:step] = [False] * ((limit - start - 1) // step + 1)
    return sum(is_prime)

def worker(limit: int):
    """供线程调用的包装函数"""
    count = count_primes(limit)
    # print(f"素数个数: {count}")  # 若频繁打印会拖慢并发,基准测试时注释掉
    return count

这个实现用列表切片一次性标记合数,也是纯Python里常见的加速写法,但本质上仍是CPU密集型。

第三步:构造多线程性能测试脚本

下面是一个测试脚本,它会用标准threading创建多个线程,每个线程计算相同的素数上限(比如1000000),然后统计总耗时和执行完成的任务数。我们分别在标准Python 3.13和无GIL版本中运行它。

# benchmark.py
import threading
import time
from primes import worker

THREADS = 8          # 根据你CPU核心数调整
LIMIT = 1_000_000    # 素数上限
REPEAT = 3           # 重复次数取平均

def test_multithread(python_label: str):
    print(f"n===== {python_label} =====")
    for run in range(REPEAT):
        threads = []
        start = time.perf_counter()
        for _ in range(THREADS):
            t = threading.Thread(target=worker, args=(LIMIT,))
            threads.append(t)
            t.start()
        for t in threads:
            t.join()
        elapsed = time.perf_counter() - start
        print(f"第{run+1}次: {elapsed:.3f}秒")

if __name__ == "__main__":
    test_multithread("标准Python 3.13 (GIL)")
    # 假设无GIL版用别的方式调用,可单独运行

由于我们希望在同一个脚本里自动识别是否在free-threading下,可以加个判断,但实际上我们会分两次执行,或用两个不同的解释器。最简单的方法:把代码保存为benchmark.py,分别用python3.13python3.13t运行它。

在标准版里,8个线程争夺一把GIL,计算时间并不会随着线程数线性减少,甚至因为上下文切换而轻微变慢。而在无GIL版中,多个线程可以真正并行运行在不同的CPU核上。

第四步:运行与结果解读

先确保你的机器至少有4个物理核心,最好8核以上,这样对比才明显。

# 标准Python 3.13 (有GIL)
python3.13 benchmark.py

===== 标准Python 3.13 (GIL) =====
第1次: 14.521秒
第2次: 14.478秒
第3次: 14.503秒

然后再用free-threaded解释器:

python3.13t benchmark.py

===== 标准Python 3.13 (GIL) ===== (虽然标签一样,但我们知道用的是无GIL版)
第1次: 2.682秒
第2次: 2.591秒
第3次: 2.603秒

这个差异,就是GIL被释放后多核并行带来的直接红利。接近8倍加速,在计算密集型场景下几乎就等同于物理核数的线性提升。

深入一点:自由线程的内部机制简述

普通CPython几乎每个字节码执行周期都要获取/释放GIL,这保证了引用计数等内部状态的安全,但也让多线程变成单行道。无GIL构建则用更细粒度的锁和原子操作来保护数据结构,比如引用计数改为原子递增、列表等对象内部加小锁。于是线程不再互相阻塞,但相应的在单线程下会有轻微性能下降(因为原子操作开销略大)。

这就是为什么无GIL构建并不是默认选项——它需要整个生态系统适配。不过,对于纯Python的并行计算、数据分析等场景,现阶段的收益已经足够诱人。

兼容性与常见陷阱

  • 许多C扩展未适配:如某些数据库驱动、图像处理库在无GIL下可能崩溃,使用前需查阅文档或测试。
  • 线程安全仍然要自己保证:没有了GIL,对共享对象的竞态条件得用Lock等同步原语自行处理,不能像以前那样以为“Python有GIL所以简单的读写是安全的”。
  • 单线程性能略降:原子操作成本会让纯单线程任务变慢大概几个百分点,需要权衡。
  • 环境隔离:建议用venv分别创建标准和无GIL的虚拟环境,避免混乱。

你可能用得上的其他并行方案对比

即使有了无GIL,多进程仍然有它的地位:更彻底的隔离、避免线程间不安全的内存共享。但对于需要频繁数据交换的任务,线程之间的零拷贝共享内存优势巨大。以前用multiprocessing时要不断序列化参数,现在可以用threading直接共享列表、字典等对象(需要加锁),整体架构更简洁。

另外,concurrent.futures.ThreadPoolExecutor在无GIL下同样能获得真实并行,你可以把上面的threading改写为线程池,代码更现代。

总结

Python 3.13的无GIL实验性支持是近十年来最让人兴奋的变革。它不需要你学习新的并发模型,原来的threading代码几乎无需改动就能享受到多核CPU的并行加速。虽然它还不是稳定默认选项,但对于计算密集型且IO较少的内部工具或批处理程序,已经可以大胆尝试了。

装一个python3.13t,找出项目里那些只能用多进程绕开的并行逻辑,花半天重构成多线程,你很可能在同样的硬件上看到从“还行”到“飞快”的转变。而且,这种体验会让你重新思考:原来Python也可以很接近机器硬件的极限。

Python 3.13无GIL并行实战:多线程CPU密集型任务的性能飞跃
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

版权声明:
本站资源有的来自互联网收集整理,本站纯免费分享提供学习使用,如果侵犯了您的合法权益,请联系本站我们会及时删除。
本站资源仅供研究、学习交流之用,免费开源项目不代表完全可商用,若商业用途请先咨询开发企业能否商用,否则产生的一切后果将由下载用户自行承担。
原创板块未经允许不得转载,否则将追究法律责任。

淘吗网 python Python 3.13无GIL并行实战:多线程CPU密集型任务的性能飞跃 https://www.taomawang.com/server/python/2252.html

下一篇:

已经没有下一篇了!

常见问题

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务