2013-07-29 56 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密集型負載。