2013-07-29 63 views
2

美好的一天!多线程工作较慢

我想学多线程在python的功能和我写了下面的代码:有4个CPU

import time, argparse, threading, sys, subprocess, os 

def item_fun(items, indices, lock): 
    for index in indices: 
     items[index] = items[index]*items[index]*items[index] 

def map(items, cores): 

    count = len(items) 
    cpi = count/cores 
    threads = [] 
    lock = threading.Lock() 
    for core in range(cores): 
     thread = threading.Thread(target=item_fun, args=(items, range(core*cpi, core*cpi + cpi), lock)) 
     threads.append(thread) 
     thread.start() 
    item_fun(items, range((core+1)*cpi, count), lock) 
    for thread in threads: 
     thread.join() 


parser = argparse.ArgumentParser(description='cube', usage='%(prog)s [options] -n') 
parser.add_argument('-n', action='store', help='number', dest='n', default='1000000', metavar = '') 
parser.add_argument('-mp', action='store_true', help='multi thread', dest='mp', default='True') 
args = parser.parse_args() 

items = range(NUMBER_OF_ITEMS) 
# print 'items before:' 
# print items 
mp = args.mp 
if mp is True: 
    NUMBER_OF_PROCESSORS = int(os.getenv("NUMBER_OF_PROCESSORS")) 
    NUMBER_OF_ITEMS = int(args.n) 
    start = time.time() 
    map(items, NUMBER_OF_PROCESSORS) 
    end = time.time() 
else: 
    NUMBER_OF_ITEMS = int(args.n) 
    start = time.time() 
    item_fun(items, range(NUMBER_OF_ITEMS), None) 
    end = time.time()  
#print 'items after:' 
#print items 
print 'time elapsed: ', (end - start) 

当我使用MP的说法,它的工作原理比较慢,我的机器上,它需要大约0.5秒来计算结果,而如果我使用单线程,则需要大约0.3秒。

我做错了什么?

我知道有Pool.map()和e.t.c,但它产生的子进程不线程,它的工作原理更快据我知道,但我想我自己写的线程池。

回答

4

你只看到在Python线程吞吐量增加,如果有一个是IO绑定线程。如果你正在做的是CPU绑定,那么你不会看到吞吐量的增加。

打开Python中的线程支持(通过启动另一个线程)也似乎让一些事情慢,所以你可能会发现,整体性能仍然受到影响。

当然,这是所有CPython的,其他的Python实现具有不同的行为。

+1

这个答案稍微不明确,线程也可以提高CPU绑定工作负载的性能,如果它不是GIL。事实上,这就是人们来自其他线程环境的人们所期望的线程。当然,还有其他一些方法可以增强Python中CPU绑定负载的处理。总的来说,答案为+1。 –

5

Python有没有真正的多线程,由于被称为“GIL”的实现细节。一次只有一个线程实际运行,并且Python在线程之间切换。 (Python中的第三方实现,如Jython,可以actually run parallel threads

至于为什么实际程序慢的多线程版本的依赖,但编码为Python时,一个需要注意的GIL的,所以人们不相信通过向程序添加线程可以更有效地处理CPU绑定负载。

其他的事情需要注意的是,例如multiprocessingnumpy解决CPU绑定的负荷,并PyEv(最小)和Tornado(巨大的厨房水槽)解决I/O密集型负载。