Python代码在多线程下性能下降

31 投票
2 回答
28564 浏览
提问于 2025-04-16 22:14

我写了一个用Python编写的程序,主要是处理一批二进制文件,把里面的数据提取到一个数据结构中。每个文件解析大约需要一秒钟,这对于成千上万的文件来说就变成了几个小时。我成功实现了一个多线程的批量解析方法,可以调整线程的数量。我在100个文件上测试了这个方法,使用不同数量的线程,并记录了每次运行的时间。以下是结果(0线程指的是我最初的代码,没有使用多线程,1线程则是新版本只用一个线程运行的情况)。

0 threads: 83.842 seconds
1 threads: 78.777 seconds
2 threads: 105.032 seconds
3 threads: 109.965 seconds
4 threads: 108.956 seconds
5 threads: 109.646 seconds
6 threads: 109.520 seconds
7 threads: 110.457 seconds
8 threads: 111.658 seconds

虽然启动一个线程比让主线程自己完成所有工作稍微快一点,但实际上增加线程的数量反而会让性能下降。我本以为性能会提高,至少在使用四个线程(每个核心一个线程)时会有提升。我知道线程会有一些额外的开销,但我没想到在使用少量线程时,这个开销会这么明显。

我听说过“全局解释器锁”,但当我使用四个线程时,确实能看到相应数量的核心在工作——用两个线程时,有两个核心在解析时显示活动,依此类推。

我还测试了一些不同版本的解析代码,想看看我的程序是否受限于输入输出(IO)。结果似乎并不是;读取文件的时间占比相对较小,处理文件几乎占用了所有时间。如果我不进行IO,而是处理一个已经读取的文件,添加第二个线程会导致性能下降,而第三个线程则稍微改善了一下。我只是想知道为什么我不能利用电脑的多个核心来加快速度。如果有任何问题或者需要我进一步解释的地方,请告诉我。

2 个回答

9

线程库实际上并不会同时利用多个核心来进行计算。如果你想要进行计算方面的多线程处理,应该使用多进程库。

46

很遗憾,CPython(Python的一种实现)就是这样的情况,主要是因为有一个叫做全局解释器锁(GIL)的东西。简单来说,Python中那些需要大量计算的代码在多个线程中运行时效果不好(而那些主要进行输入输出的代码在某种程度上可以做到多线程)。

有一个非常有用的演讲,是David Beazley做的,他讨论了关于GIL的一些问题。你可以在这里找到这个视频(感谢@Ikke!)

我建议使用multiprocessing模块,而不是使用多个线程。

撰写回答