You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python3.10中纯CPU密集型多线程代码为何比串行代码更快?

问题:CPU密集型代码多线程版本比串行更快,不符合GIL认知的原因?

我有两段执行相同CPU密集型计算的代码示例,串行版本的运行速度明显慢于多线程版本。根据我对GIL(全局解释器锁)的理解,这种情况本不应出现——因为同一时间仅能有一个线程运行,且代码无IO等待,总运行时间应大致相同。

此外,我还有一个使用multiprocessing库实现的示例,其运行速度比多线程版本更快,这符合预期,因为它能并行利用3个核心。

串行代码(耗时约27秒)

import time

start_time = time.time()
my_threads = [100000000, 200000000, 300000000]
for x in my_threads:
    print(f"start {x}")
    for y in range(x):
        y*y
    print(f"finished input {x}: {time.time() - start_time:.2f} seconds")

print(f"{time.time() - start_time:.2f} seconds")

多线程代码(耗时约14.68秒)

编辑说明:已移除冗余代码,简化后结果不变

import threading
import time

def my_threaded_function(s, x):
    with s:
        start_time = time.time()
        for y in range(x):
            y*y
        print(f"finished input {x}: {time.time() - start_time:.2f} seconds")

s = threading.Semaphore(25)

my_threads = [100000000, 200000000, 300000000]
threads = []

start_time = time.time()

for x in my_threads:
    t = threading.Thread(
        target=my_threaded_function, name=f"Thread-{x}",
        args=(s, x,)
    )
    t.daemon = True
    threads.append(t)
    t.start()

[thread.join() for thread in threads]

print(f"{time.time() - start_time:.2f} seconds")

完整运行输出

❯ python3 code/sequential.py
finished input 100000000: 4.57 seconds
finished input 200000000: 13.61 seconds
finished input 300000000: 27.09 seconds
27.09 seconds
❯ python3 code/threading_example.py
finished input 100000000: 7.84 seconds
finished input 200000000: 12.44 seconds
finished input 300000000: 14.65 seconds
14.68 seconds

我原本预期这两个示例的运行时间相同,请问这种现象的原因是什么?


解答

核心原因是串行版本是依次执行三个计算任务,总时间为各任务耗时之和;而多线程版本是并发执行三个任务,即使受GIL限制,总时间也远低于串行的总和。具体拆解:

  1. 任务执行模式差异

    • 串行代码中,三个计算任务按顺序逐个完成:先跑完1e8次循环,再跑2e8次,最后跑3e8次。总时间等于三个任务的耗时相加(4.57 + (13.61-4.57) + (27.09-13.61) ≈ 27.09秒)。
    • 多线程代码中,三个线程同时启动,各自执行循环任务。虽然GIL限制同一时间只有一个线程能执行Python字节码,但CPython的GIL会在执行一定数量的字节码后自动释放,让其他线程获取锁继续执行。这种定期切换让三个任务交替推进,总时间接近单个最长任务的耗时(≈14.65秒),而非三个任务耗时相加。
  2. GIL的实际行为
    你对GIL“同一时间仅能有一个线程运行”的理解没错,但GIL不会锁定某个线程直到任务结束,而是会定期释放并切换线程。对于CPU密集型任务,虽然无法像多进程那样真正并行利用多核,但并发执行依然能让多个任务同时推进,大幅缩短总耗时。

  3. 多进程更快的合理性
    multiprocessing库创建的每个进程都有独立的Python解释器和GIL,完全避开了GIL的限制,能真正并行利用多个CPU核心,所以运行速度比多线程版本更快,这符合预期。


内容的提问来源于stack exchange,提问作者micha.net

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 21:55:55