2016-07-06 68 views
2

我一直在玩弄多处理问题,并注意到我的算法在并行化时比在单线程时慢。Python多处理速度比单线程慢

在我的代码中,我不共享内存。 我很确定我的算法(见代码),它只是嵌套循环是CPU绑定的。

但是,无论我做什么。并行代码在我所有的计算机上运行速度慢10-20%。

我也在20个CPU虚拟机上运行这个程序,每次单线程都击败多线程(实际上甚至比我的电脑慢)。

from multiprocessing.dummy import Pool as ThreadPool 
from multi import chunks 
from random import random 
import logging 
import time 
from multi import chunks 

## Product two set of stuff we can iterate over 
S = [] 
for x in range(100000): 
    S.append({'value': x*random()}) 
H =[] 
for x in range(255): 
    H.append({'value': x*random()}) 

# the function for each thread 
# just nested iteration 
def doStuff(HH): 
    R =[] 
    for k in HH['S']: 
    for h in HH['H']: 
     R.append(k['value'] * h['value']) 
    return R 

# we will split the work 
# between the worker thread and give it 
# 5 item each to iterate over the big list 
HChunks = chunks(H, 5) 
XChunks = [] 

# turn them into dictionary, so i can pass in both 
# S and H list 
# Note: I do this because I'm not sure if I use the global 
# S, will it spend too much time on cache synchronizatio or not 
# the idea is that I dont want each thread to share anything. 
for x in HChunks: 
    XChunks.append({'H': x, 'S': S}) 

print("Process") 
t0 = time.time() 
pool = ThreadPool(4) 
R = pool.map(doStuff, XChunks) 
pool.close() 
pool.join() 

t1 = time.time() 

# measured time for 4 threads is slower 
# than when i have this code just do 
# doStuff(..) in non-parallel way 
# Why!? 

total = t1-t0 
print("Took", total, "secs") 

有很多相关的问题已经打开,但很多都是针对错误构造的代码 - 每个工人都是IO绑定等等。

+0

可能重复的[Python中的multiprocessing.dummy](http://stackoverflow.com/questions/26432411/multiprocessing-dummy-in-python) – MisterMiyagi

回答

6

您正在使用多线程而不是多处理。尽管许多语言允许线程并行运行,但python却没有。线程只是一个单独的控制状态,即它拥有自己的堆栈,当前的函数等。python解释器只是在每次执行堆栈之间进行切换。

基本上,所有线程都运行在单个内核上。当你是而不是 CPU绑定时,他们只会加速你的程序。

multiprocessing.dummy复制了多处理的API,但不过是线程模块的一个包装。

多线程通常是比单线程如果你是CPU的约束。这是因为工作和处理资源保持不变,但是会增加管理线程的开销,例如,在它们之间切换。

如何解决此问题:而不是使用from multiprocessing.dummy import Pool as ThreadPoolmultiprocessing.Pool as ThreadPool


您可能想要阅读GIL(全局解释器锁)。这是阻止线程并行运行的原因(以及对单线程性能的影响)。除CPython之外的Python解释器可能没有GIL,并且能够在多个内核上运行多线程。

+6

我的生活一直是个谎言。 – 40Plot

+1

@ 40Plot不,Python的方法很奇怪,古怪 – tfb