Python异步增加相同的变量来提高性能?



如何使用多个线程并行地增加相同的变量,以便将所花费的总时间减少到原始同步进程所花费的时间的倍数?

的例子:

num = 0                     
def incrementer():               
for i in range(100):    
global num
num += 1            
for i in range(100):        
th=Thread(target=incrementer)
th.start()              
num                         

上面的代码确实给出了预期的结果(10000),但是所花费的时间比同步方法要长得多:

In [114]: %%timeit                                                     
...: num = 0                                                      
...: def incrementer():                                                
...:     for i in range(100):                                     
...:         global num                                           
...:         num += 1                                             
...: for i in range(100):                                         
...:     th=Thread(target=incrementer)                                 
...:     th.start()                                               
25.3 ms ± 2.27 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [113]: %%timeit                                                     
...: num = 0                                                      
...: for i in range(10000):                                       
...:     num += 1                                                 
596 µs ± 84.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

我期望多线程方法所花费的时间是同步方法所花费时间的1%…

对于n个线程,我怎样才能使异步方法只花费同步方法所花费时间的n倍,或者这显然是不可能的?

多线程性能提升并不像你想象的那样线性。

假设您有一个4核CPU (nc=4),从单线程(t=1)到4线程(t=4)应该会显示总体计算时间的减少。如果你有一个4核CPU,你可能期望减少75%的计算时间,但在现实世界中,仍然需要做一些工作来保持操作系统的运行。

拥有比物理内核数量更多的线程(t>nc)最多可以提供与匹配这些值(t=nc)相同的性能,但在现实世界中,使用t>>nc管理资源实际上可能会运行得慢一点。

接下来,你的方法是使用一个计数器,由所有线程更新,这增加了复杂性,因为你需要一个互斥锁/信号量等。为了确保计数器更新在多方读写的情况下按预期运行——多方越多,执行起来就越困难,而且,您猜对了,又会对性能造成影响。

我建议将你的问题空间划分为线程的数量(t=nc,如果你正在阅读上面的内容),这样(例如)threadA进程0-24,threadB: 25-49,threadC 50-74threadD: 75-99-这样它们就不需要相互通信,因为每个线程都在处理自己的问题空间。

tl;博士:

  • 当多线程时,超越t=nc几乎没有任何优势,但在功能上,你甚至可能想要停止在t=(nc-1),为你的操作系统/等留下一些CPU时间。
  • 线程同步需要仔细完成;在将作业发送到线程之前,尝试将饼切成t

最新更新