2016-09-19 66 views
2

我想要使用線程在python中獲得更好的性能。Python中的線程-

我的程序需要返回線程執行的每個函數的值。

而且我需要知道線程何時完成。

有3種方法我試圖執行這個小程序。

import thread 
import datetime 
from threading import Thread 
import threading 
from multiprocessing.pool import ThreadPool 


def func1(word): 
    i=0 
    while i<100000: 
     if 1<2: 
      i=i+1 
    return "func1" 


def func2(): 
    i=0 
    while i<100000: 
     if 1<2: 
      i=i+1 
    return "func2" 

word="hiiii" 

""" 
#--------------------------------example1-------------------------------- 
pool = ThreadPool(processes=2) 

print str(datetime.datetime.now().time()) 
async_result1 = pool.apply_async(func1, (word,)) 

async_result2 = pool.apply_async(func2) 

print async_result1.get() 
print async_result2.get() 
print str(datetime.datetime.now().time()) 


print func1(word) 
print func2() 
print str(datetime.datetime.now().time()) 
#with threads-71000 
#without threads- 40000 
#--------------------------------example1-------------------------------- 
""" 

""" 
#--------------------------------example2-------------------------------- 

t1 = Thread(target=func1, args=(word,)) 
t2 = Thread(target=func2, args=()) 
print str(datetime.datetime.now().time()) 

t1.start() 
t2.start() 

t1.join() 
t2.join() 
print str(datetime.datetime.now().time()) 

func1(word) 
func2() 
print str(datetime.datetime.now().time()) 

#with threads-75000 
#without threads-42000 
#--------------------------------example2-------------------------------- 
""" 

""" 
#--------------------------------example3 without sending value-------------------------------- 
print str(datetime.datetime.now().time()) 

t1 = threading.Thread(name=func1,target=func1) 
t2= threading.Thread(name=func2,target=func2) 
t1.start() 
t2.start() 

t1.join() 
t2.join() 
print str(datetime.datetime.now().time()) 
func1() 
func2() 
print str(datetime.datetime.now().time()) 

#with threads- 73000 
#without threads- 42000 
#--------------------------------example3 without sending value------------- ------------------- 
    """ 

但是,你可以看到更好的運行方式是沒有線程的! 爲什麼?我做錯了什麼?如何使用線程?

+1

線程通常只在任務是IO綁定時纔有用;這段代碼顯然是CPU綁定的。 –

+0

GIL(全局解釋器鎖),python線程不是本地線程 –

回答

3

當你有多個任務爭奪CPU時,線程主要用於處理,但大部分時間都花在等待網絡讀取或數據庫寫入等外部事件。

多線程處於活動狀態時,它決定切換到另一個線程(假設還有其他可運行線程)花費的每個(某些數量)操作碼。如果你的線程都沒有做任何事情,除了計算,那麼實際上沒有時間通過​​在線程之間切換來節省。由於所有線程都在同一進程中運行,並且Python進程無法(通常)利用多個CPU,因此不會看到任何加速(實際上,可能由於線程切換活動而導致速度減慢)。

tl; dr:CPU綁定的任務不能通過多線程加速。

1

要追加對方回答:

原因線程版本實際上是CPU密集型操作慢是(如前所述)GIL,全局解釋鎖。 GIL作爲一個互斥體,一次只允許一個線程訪問它。所以線程只在等待IO操作時有用。

但是,有一種方法可以在多個內核中實際執行代碼,繞過GIL的問題。解決方案是使用multiprocessing庫。

所以你的情況:

process1 = multiprocessing.Process(target=func1, args=(word,)) 
process1.start() 
process2 = multiprocessing.Process(target=func2) 
process2.start() 

process.join() 
process2.join() 

兩個過程應該在不同的內核啓動,有效地使程序執行得更快。對我來說,它幾乎減半執行時間。請注意,產生比核心更多的進程將再次使其運行速度變慢。