多進程與多線程

Python發揮不了多核處理器的性能(聽說是受限於GIL,被鎖住只能用一個CPU核心,關於這個,這裏有篇文章),可是能夠經過Python的multiprocessing(多進程)模塊或者並行運算模塊(例如,pprocess)來使用到多核。html

測試代碼以下,程序前後分別測試了串行運算、並行運算以及多線程和多進程執行同一個函數所花費的時間。python

  1. #! /usr/local/bin/python2.7  
  2. # test.py  
  3.   
  4. import time  
  5. import pprocess # 該模塊只能在linux下使用  
  6. import threading  
  7. from multiprocessing import Process   
  8.   
  9. def takeuptime(n):  
  10.     chars = 'abcdefghijklmnopqrstuvwxyz0123456789'  
  11.     s = chars * 1000  
  12.     for i in range(10*n):  
  13.         for c in chars:  
  14.             s.count(c)  
  15.   
  16. if __name__ == '__main__':  
  17.     list_of_args = [1000, 1000, 1000, 1000]  
  18.   
  19.     # Serial computation  
  20.     start = time.time()  
  21.     serial_results = [takeuptime(args) for args in list_of_args]  
  22.     print "%f s for traditional, serial computation." % (time.time() - start)  
  23.   
  24.     # Parallel computation  
  25.     nproc = # maximum number of simultaneous processes desired  
  26.     results = pprocess.Map(limit=nproc, reuse=1)  
  27.     parallel_function = results.manage(pprocess.MakeReusable(takeuptime))  
  28.     start = time.time()  
  29.     # Start computing things  
  30.     for args in list_of_args:  
  31.         parallel_function(args)  
  32.     parallel_results = results[:]  
  33.     print "%f s for parallel computation." % (time.time() - start)  
  34.   
  35.     # Multithreading computation  
  36.     nthead = # number of threads  
  37.     threads = [threading.Thread(target=takeuptime, args=(list_of_args[i],)) for i in range(nthead)]  
  38.     start = time.time()  
  39.     # Start threads one by one  
  40.     for thread in threads:  
  41.         thread.start()  
  42.     # Wait for all threads to finish  
  43.     for thread in threads:  
  44.         thread.join()  
  45.     print "%f s for multithreading computation." % (time.time() - start)  
  46.   
  47.   
  48.     # Multiprocessing computation  
  49.     process = []  
  50.     nprocess = # number of processes  
  51.     for i in range(nprocess):  
  52.         process.append(Process(target=takeuptime, args=(list_of_args[i],)))  
  53.     start = time.time()  
  54.     # Start processes one by one  
  55.     for p in process:  
  56.         p.start()  
  57.     # Wait for all processed to finish  
  58.     for i in process:  
  59.         p.join()  
  60.     print "%f s for multiprocessing computation." % (time.time() - start)  

運行結果以下:linux

[root@localhost test]# python test.pyc++

62.452934 s for traditional, serial computation.多線程

20.665276 s for parallel computation.併發

64.835923 s for multithreading computation.app

18.392281 s for multiprocessing computation.python2.7

從測試結果能夠明顯看出並行運算和多進程計算速度明顯要快於串行計算和多線程計算。函數

 

這裏有個問題,爲何多線程的所花的時間不比串行單線程的少呢(64.873760 > 62.452934)?性能

根據咱們的常規經驗,多線程確定要比單線程要快,爲何測試結果卻不是這樣呢?

前面已經提到了,Python只能用到一個CPU核心,所以即使是多線程,在同一時間CPU也只能處理一個線程運算,多個線程並不能並行的運行,他們是輪流切換執行的。

所以,只有當線程中會出現阻塞時,多線程纔有意義,好比線程中有數據下載,在等待數據返回時線程阻塞了,此時CPU就能夠來處理其它線程的運算。

上面測試程序中的takeuptime()函數沒有阻塞,它不停地在進行着運算,因此多線程和單線程的效果是同樣的(線程切換也會花費時間,因此此時多線程花費的時候甚至比單線程多一些)。

並行運算和多進程運算之因此快,就是由於他們能同時利用多個CPU核心,多個數據運算能同時進行。

咱們把takeuptime()函數改爲有阻塞的,再測試一下:

  1. def takeuptime(n):  
  2.     def download(url):  
  3.         # simulate downloading  
  4.         time.sleep(2)  
  5.     for i in range(5):  
  6.         html = download('http://www.redicecn.com/page%d.html' % i)  

新的運行結果以下:

[root@localhost test]# python test.py

39.996438 s for traditional, serial computation.

10.003863 s for parallel computation.

10.003480 s for multithreading computation.

10.008936 s for multiprocessing computation.

能夠看到在有阻塞的數據處理過程當中,多線程的做用仍是很明顯的。

上面是對python而言的,若是是對c++而言,多線程是能夠應用到多個核上的。也就是說當多線程未綁定cpu時,是能夠實行多個cpu的並行處理,和多進程同樣。可是一旦綁定到某個cpu,則變成了併發,此時因爲是共享同一cpu,並且有切換,和上面講到的python例子同樣。

相關文章
相關標籤/搜索