CPython在CPU密集型應用下的並發
阿新 • • 發佈:2017-07-11
orm tel log 發揮 狀態 intel 測試 blog sin
Python是解釋型語言,根據不同的底層協議有很多種版本,最常見的是基於C的Cpython,默認情況下我們所說的Python就是Cpython。
Python的GIL(global interpreter lock):
用於解決多線程之間的數據完整性和狀態同步而存在,使得不管線程分布在多少個CPU上,解釋器同一時刻只允許1個線程運行。
所以Python是thread_safe的。這樣其實Python就幾乎只能進行單線程編程了。
CPU密集型應用:(頻繁計算)
從1開始累加,到1億
1 def foo(): 2 num = 0 3 for i in range(100000001):4 num += i
現在進行一個任務,完成三次函數foo()的運行,計算總耗時,給出四種方案
1、單線程,1,2,3,4串行
2、多線程,1,2,3,4並行
3、單進程,1,2,3,4串行
4、多進程,1,2,3,4並行
通過實驗驗證在CPU秘籍應用下Python並發的最佳實現方式
測試電腦CPU:
intel_I7-4700(4核8線程)
方案1;
1 if __name__ == "__main__": 2 t_list = [] 3 start_time = time.time() 4 for i in range(5): 5 i = threading.Thread(target=foo)6 t_list.append(i) 7 i.start() 8 i.join() 9 end_time = time.time() 10 print("Totally time:{}".format(end_time-start_time))
方案2;
1 if __name__ == "__main__": 2 t_list = [] 3 start_time = time.time() 4 for i in range(5): 5 i = threading.Thread(target=foo)6 t_list.append(i) 7 i.start() 8 for i in t_list: 9 i.join() 10 end_time = time.time() 11 print("Totally time:{}".format(end_time-start_time))
方案3;
1 if __name__ == "__main__": 2 p_list = [] 3 start_time = time.time() 4 for i in range(5): 5 i = multiprocessing.Process(target=foo) 6 p_list.append(i) 7 i.start() 8 i.join() 9 end_time = time.time() 10 print("Totally time:{}".format(end_time-start_time))
方案4;
1 if __name__ == "__main__": 2 p_list = [] 3 start_time = time.time() 4 for i in range(5): 5 i = multiprocessing.Process(target=foo) 6 p_list.append(i) 7 i.start() 8 for i in p_list: 9 i.join() 10 end_time = time.time() 11 print("Totally time:{}".format(end_time-start_time))
方案與實踐的對應:
方案1:——42.97582244873047
方案2:——44.63868308067322
方案3:——45.94909477233887
方案4:——15.7623131275177
總結:
這裏multi_thread的效率竟然低於single_thread!所以,計算密集型應用,千萬不要使用多線程,反而增加累贅!(GIL導致的)。
最能發揮性能的就是多進程!
CPython在CPU密集型應用下的並發