Skip to main content
 首页 » 编程设计

python之为什么这个例子中的 Python 多线程这么慢

2024年08月13日28飞鱼

据我了解,当程序受 IO 限制时,多线程应该会加速。为什么下面的示例慢得多,我怎样才能让它产生与单线程版本完全相同的结果?

单线程:

时间:1.8115384578704834

import time 
 
start_time = time.time() 
 
def testThread(num): 
    num = "" 
    for i in range(500): 
        num += str(i % 10) 
        a.write(num) 
 
 
def main(): 
    test_list = [x for x in range(3000)] 
 
    for i in test_list: 
        testThread(i) 
 
if __name__ == '__main__': 
    a = open('single.txt', 'w') 
    main() 
    print(time.time() - start_time) 

多线程:

时间:22.509746551513672

import threading 
from concurrent.futures import ThreadPoolExecutor 
from multiprocessing.pool import ThreadPool 
import time 
 
start_time = time.time() 
 
 
def testThread(num): 
    num = "" 
    for i in range(500): 
        num += str(i % 10) 
        with global_lock: 
            a.write(num) 
 
 
def main(): 
    test_list = [x for x in range(3000)] 
 
    with ThreadPool(4) as executor: 
        results = executor.map(testThread, test_list) 
 
    # with ThreadPoolExecutor() as executor: 
    #    results = executor.map(testThread, test_list) 
 
 
if __name__ == '__main__': 
    a = open('multi.txt', 'w') 
    global_lock = threading.Lock() 
    main() 
    print(time.time() - start_time) 

此外,ThreadPoolExecutor 与 ThreadPool 有何不同

请您参考如下方法:

编辑。忘了 GIL,傻我。

下面的代码显示了其他多线程语言的通用方法,因为它们会遇到同样的问题。

但是,在这种情况下,语言是 Python。由于 GIL,在这种情况下,一次只会有一个事件线程,因为没有一个线程真正让出。 (操作系统可能会在中途强制交换线程,但这不会改变一次只能运行一个线程的事实。

对于计算和文件 I/O,Python 看不到多线程带来的任何好处。
为了增加计算量,您可以进行多进程处理。但是,您仍然无法加速文件 I/O


for i in range(500): 
        num += str(i % 10) 
        with global_lock: 
            a.write(num) 

您现在有 4 个线程锁定和写入,这是函数中较慢的部分。
本质上,您有 4 个线程执行 1 个任务,如果是这样的话,您会增加大量的开销和等待时间。


根据评论,以下内容可能会有所帮助:

unordered_output_list = [] 
def testThread(num): 
    num = "" 
    for i in range(500): 
        num += str(i % 10) 
        unordered_output_list.append(num) 
 
def main(): 
    test_list = [x for x in range(3000)] 
 
    with ThreadPool(4) as executor: 
        results = executor.map(testThread, test_list) 
 
    # with ThreadPoolExecutor() as executor: 
    #    results = executor.map(testThread, test_list) 
      for num in unordered_output_list: 
          a.write(num) 
 
if __name__ == '__main__': 
    a = open('multi.txt', 'w') 
    main() 
    print(time.time() - start_time) 

这里我们并行处理(稍微提速),然后我们顺序写入。

来自 this answer

Short answer: physically writing to the same disk from multiple threads at the same time, will never be faster than writing to that disk from one thread (talking about normal hard disks here). In some cases it can even be a lot slower.