Python多线程能否用于计算密集型任务?实测案例求解答
Python多线程与计算密集型任务的多核利用
首先先明确一个大家常说的结论:
纯Python代码无法同时利用多CPU核心,但调用Numpy等C编写的库时可实现多核利用
你提到之前听说“GIL限制下Python多线程不是真正的多线程”“仅适合IO密集型任务”,但自己的实测却得到了计算密集型任务的3倍加速,CPU全核心跑满——这其实完全符合CPython的运行逻辑,核心在于GIL的作用范围:
关于GIL的核心要点
GIL(全局解释器锁)是CPython解释器的一个机制,它的限制是:同一时间只能有一个线程执行纯Python字节码。但这里有个关键例外:当线程调用的是用C/C++编写的扩展库函数时,这些函数通常会临时释放GIL,让其他线程可以同时执行;更重要的是,很多这类C扩展库(比如Numpy、Scipy的核心计算模块)本身就支持多核并行,会直接利用多个CPU核心完成计算。
你的实测结果解释
看你的代码,核心计算部分都是依赖Numpy和Scipy的函数:
import threading import time import numpy as np from scipy import interpolate number_list = list(range(10)) def image_interpolation(): while True: number = None with threading.Lock(): if len(number_list): number = number_list.pop() if number is not None: # 生成一张模拟图像——你可以替换为自己的图像 image = np.ones((20000, 20000)) # 创建原始数组(省略额外维度) orig = np.random.rand(12800, 16000) # 创建坐标;x为水平方向 x = np.linspace(0, image.shape[1], orig.shape[1]) y = np.linspace(0, image.shape[0], orig.shape[0]) # 创建插值函数 f = interpolate.interp2d(x, y, orig, kind='linear') else: return 1 workers=5 thd_list = [] t1 = time.time() for i in range(workers): thd = threading.Thread(target=image_interpolation) thd.start() thd_list.append(thd) for thd in thd_list: thd.join() t2 = time.time() print("total time cost with multithreading: " + str(t2-t1)) number_list = list(range(10)) for i in range(10): image_interpolation() t3 = time.time() print("total time cost without multithreading: " + str(t3-t2))
你的输出结果:
total time cost with multithreading: 112.71922039985657
total time cost without multithreading: 328.45561170578003
这些np.random.rand、interpolate.interp2d都是C实现的核心函数,执行时会释放GIL:
- 多个线程可以同时调用这些函数,不会被GIL卡住;
- 这些函数本身(比如Numpy的随机数生成、Scipy的插值)可能会利用OpenBLAS、MKL这类多核线性代数库,直接占用多个CPU核心。
这就是为什么你的多线程实现了接近3倍的加速,并且CPU全核心跑满。
你的问题答案
1. Python多线程能否应用于计算密集型任务?
- 如果你的计算密集型任务核心逻辑依赖于释放GIL的C扩展库(比如Numpy、Scipy、PyTorch、TensorFlow等),那么多线程可以有效利用多核,实现明显加速;
- 如果是纯Python代码编写的计算(比如纯Python循环处理数据、自定义计算逻辑),GIL会限制同一时间只有一个线程执行,多线程无法实现多核并行,这时应该用
multiprocessing模块的多进程来利用多核。
2. Python中多线程/多核能否同时运行?
- 执行纯Python字节码时:不行,GIL限制同一时间只有一个线程运行,无法利用多核;
- 执行释放GIL的C扩展库代码时:可以,此时GIL被释放,多个线程可以同时执行这些C代码,而且很多C扩展库本身支持多核并行,能让多个CPU核心同时工作。
内容的提问来源于stack exchange,提问作者Jingnan Jia
相关产品推荐
相关产品推荐

