多線程和單線程的執行效率問題


一提到多線程一般大家的第一感覺就是可以提升程序性能,在實際的操作中往往遇到性能的問題,都嘗試使用多線程來解決問題,但多線程程序並不是在任何情況下都能提升效率,在一些情況下恰恰相反,反而會降低程序的性能。這里給出兩個簡單的例子來說明下:

程序1:

 1 import threading
 2 from time import ctime
 3 
 4 class MyThread(threading.Thread):
 5     def __init__(self, func, args, name):
 6         threading.Thread.__init__(self)
 7         self.name = name
 8         self.func = func
 9         self.args = args
10 
11     def run(self):
12         print 'starting', self.name, 'at:',ctime()
13         apply(self.func, self.args)
14         print self.name, 'finished at:', ctime()
15 
16 def fun1(x):
17     y = 0
18     for i in range(x):
19         y+=1
20 
21 def fun2(x):
22     y = 0
23     for i in range(x):
24         y+=1
25         
26 def main():
27     print 'staring single thread at:',ctime()
28     fun1(10000000)
29     fun2(10000000)
30     print 'finished single thread at:',ctime()
31 
32     t1 = MyThread(fun1,(10000000,),fun1.__name__)
33     t2 = MyThread(fun2,(10000000,),fun2.__name__)
34     t1.start()
35     t2.start()
36     t1.join()
37     t2.join()
38     
39     print 'all done'
40     
41 if __name__ == '__main__':
42     main()

 該程序執行結果為:

staring single thread at: Sat Dec 08 10:27:11 2012
finished single thread at: Sat Dec 08 10:27:14 2012
starting  fun1  at:  Sat Dec 08 10:27:14 2012
starting  fun2  at:  Sat Dec 08 10:27:14 2012
fun1  finished at:Sat Dec 08 10:27:21 2012
fun2  finished at:Sat Dec 08 10:27:21 2012
all done

結果顯示對於同樣的問題多線程耗費了多一倍的時間,fun1,、fun2都是計算型程序,這就意味着兩個代碼都需要占用CPU資源,雖然采用了多線 程但CPU資源是唯一的(不考慮多CPU多核的情況),同一時刻只能一個線程使用,導致多線程無法真正的並發,相反由於線程的切換的開銷,效率反而有明顯 的下降。由此看以在單CPU的場景下對於計算密集型的程序,多線程並不能帶來效率的提升。

程序2:

 1 import threading
 2 from time import ctime
 3 
 4 class MyThread(threading.Thread):
 5     def __init__(self, func, args, name):
 6         threading.Thread.__init__(self)
 7         self.name = name
 8         self.func = func
 9         self.args = args
10 
11     def run(self):
12         print 'starting', self.name, 'at:',ctime()
13         apply(self.func, self.args)
14         print self.name, 'finished at:', ctime()
15 
16 def fun1(x):
17     for i in range(x):
18         fd = open('1','w')
19         fd.close()
20 
21 def fun2(x):
22     y = 0
23     for i in range(x):
24         y+=1
25         
26 def main():
27     print 'staring single thread at:',ctime()
28     fun1(15000)
29     fun2(50000000)
30     print 'finished single thread at:',ctime()
31 
32     t1 = MyThread(fun1,(15000,),fun1.__name__)
33     t2 = MyThread(fun2,(50000000,),fun2.__name__)
34     t1.start()
35     t2.start()
36     t1.join()
37     t2.join()
38     
39     print 'all done'
40     
41 if __name__ == '__main__':
42     main()
View Code

該程序執行結果為:

staring single thread at: Sat Dec 08 11:03:30 2012
finished single thread at: Sat Dec 08 11:03:46 2012
starting  fun1  at:  Sat Dec 08 11:03:46 2012
starting  fun2  at:  Sat Dec 08 11:03:46 2012
fun2 finished at: Sat Dec 08 11:03:55 2012
fun1 finished at: Sat Dec 08 11:03:58 2012
all done

結果顯示這個程序采用多線程比單線程的效率有明顯的提升。這是由於fun1主要是文件的操作,fun2是計算操作,單線程的情況下,雖然兩個程序主 要使用不同的資源但是在線程內部只能串行執行,在IO操作的時候,CPU實際是無事可做。多線程的情況下,如果一個線程在等待IO操作,線程會馬上調度到 另外一個線程上,並發的使用了不同的資源。

結論:

線程本身由於創建和切換的開銷,采用多線程不會提高程序的執行速度,反而會降低速度,但是對於頻繁IO操作的程序,多線程可以有效的並發。

對於包含不同任務的程序,可以考慮每個任務使用一個線程。這樣的程序在設計上相對於單線程做所有事的程序來說,更為清晰明了,比如生產、消費者問題。

在實際的開發中對於性能優化的問題需要考慮到具體的場景來考慮是否使用多線程技術。

 

 

操作系統 並發程序執行的特點:
並發環境下,由於程序的封閉性被打破,出現了新的特點:
①程序與計算不再一一對應,一個程序副本可以有多個計算
並發程序之間有相互制約關系,直接制約體現為一個程序需要另一個程序的計算結果,間接制約體現為多個程序競爭某一資源,如處理機、 緩沖區等。
並發程序在執行中是走走停停,斷續推進的。

與並行區別 編輯

並發當有多個線程在操作時,如果系統只有一個CPU,則它根本不可能真正同時進行一個以上的線程,它 只能把CPU運行時間划分成若干個時間段,再將時間 段分配給各個線程執行,在一個時間段的線程代碼運行時,其它線程處於掛起狀。.這種方式我們稱之為並發(Concurrent)。
並行:當系統有一個以上CPU時,則線程的操作有可能非並發。當一個CPU執行一個線程時,另一個CPU可以執行另一個線程,兩個線程互不搶占CPU資源,可以同時進行,這種方式我們稱之為並行(Parallel)。
區別:並發和並行是即相似又有區別的兩個概念,並行是指兩個或者多個事件在同一時刻發生;而並發是指兩個或多個事件在同一時間間隔內發生。在 多道程序環境下, 並發性是指在一段時間內宏觀上有多個程序在同時運行,但在 單處理機系統中,每一時刻卻僅能有一道程序執行,故微觀上這些程序只能是分時地交替執行。倘若在 計算機系統中有多個 處理機,則這些可以並發執行的程序便可被分配到多個處理機上,實現 並行執行,即利用每個處理機來處理一個可並發執行的程序,這樣,多個程序便可以同時執行。 [2]  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM