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限制,总时间也远低于串行的总和。具体拆解:
任务执行模式差异
- 串行代码中,三个计算任务按顺序逐个完成:先跑完1e8次循环,再跑2e8次,最后跑3e8次。总时间等于三个任务的耗时相加(4.57 + (13.61-4.57) + (27.09-13.61) ≈ 27.09秒)。
- 多线程代码中,三个线程同时启动,各自执行循环任务。虽然GIL限制同一时间只有一个线程能执行Python字节码,但CPython的GIL会在执行一定数量的字节码后自动释放,让其他线程获取锁继续执行。这种定期切换让三个任务交替推进,总时间接近单个最长任务的耗时(≈14.65秒),而非三个任务耗时相加。
GIL的实际行为
你对GIL“同一时间仅能有一个线程运行”的理解没错,但GIL不会锁定某个线程直到任务结束,而是会定期释放并切换线程。对于CPU密集型任务,虽然无法像多进程那样真正并行利用多核,但并发执行依然能让多个任务同时推进,大幅缩短总耗时。多进程更快的合理性
multiprocessing库创建的每个进程都有独立的Python解释器和GIL,完全避开了GIL的限制,能真正并行利用多个CPU核心,所以运行速度比多线程版本更快,这符合预期。
内容的提问来源于stack exchange,提问作者micha.net
相关产品推荐
相关产品推荐

