python真正的多線程,python計算密集型任務_Python多進程和多線程測試比高低,只為證明誰是最快的“仔”

 2023-10-04 阅读 27 评论 0

摘要:目的前面分別詳細介紹了python的多進程和多線程,如果還沒看前面文章的,請先看下之前的文章詳解內容。有任何疑問請留言。那這里就不再對多線程和多進程的實現和用法再贅述了。那各位同學學習了python的多線程和多進程,那么到底是多進程有優勢呢?還

目的

前面分別詳細介紹了python的多進程和多線程,如果還沒看前面文章的,請先看下之前的文章詳解內容。有任何疑問請留言。那這里就不再對多線程和多進程的實現和用法再贅述了。那各位同學學習了python的多線程和多進程,那么到底是多進程有優勢呢?還是多線程比較快呢?他們兩個哪個運行比較快呢?在代碼編程時到底是用多進程呢,還是用多線程呢,如何最優選擇呢?本篇文章就讓我們討論下python多進程和多線程的應用場景選擇和最優選問題。

1c065bfa2107df82742a80f6cfd68a60.png

python最優選

進程快的佐證測試

當你理解了多線程和多進程后,你是否有過這樣的疑問,它們兩個到底誰更快呢?網上很多都會說那肯定是多進程更快了,因為線程中GIL(全局解釋器鎖)存在,實際上是串行執行的,同一時刻只能有一個線程再跑,而進程是相互獨立,多個進程是同時執行的。那么,到底是不是這樣的呢?我們通過測試一探究竟。

帶著上面的疑問進行了測試,根據測試結果圖,我們不難看出線程和進程到底哪個快,哪個效率高了。

3ef7f2338dbcf7a068f0576de3dcb03c.png

線程和進程對比圖

python真正的多線程?那么根據上圖的測試結果,可以看出進程耗時比較少,線程耗時較多,那說明線程沒有進程快,似乎證實了網上很多人的想法呢。但真是這樣嗎?

線程快的佐證測試

我們都知道:python中的多線程需要先拿到GIL,才能執行代碼,然后釋放GIL。所以由于GIL的存在,實際上它的并發,即多個事件在同一時間是間隔的。而進程有獨立GIL,可以并行實現。因此,針對多核CPU,理論上采用多進程更能有效利用資源,效率更高,耗時更少。但是現實問題是,很多教程中經常能見到python多線程的身影。尤其是:網絡爬蟲、端口掃描等教程中。這是為什么呢,難道這些教程都是騙人的,寫教程的人都是傻子嗎?顯然不是,認為別人傻的人才是真的傻呢。那么又是問什么呢?

這里舉端口掃描的例子來說吧,代碼如下:

import sys,threadingfrom socket import * host = "127.0.0.1" if len(sys.argv)==1 else sys.argv[1]portList = [i for i in range(1,1000)]scanList = []lock = threading.Lock()print('Please waiting... From ',host)  def scanPort(port): ? ?try: ? ? ? ?tcp = socket(AF_INET,SOCK_STREAM) ? ? ? ?tcp.connect((host,port)) ? ?except: ? ? ? ?pass ? ?else: ? ? ? ?if lock.acquire(): ? ? ? ? ? ?print('[+]port',port,'open') ? ? ? ? ? ?lock.release() ? ?finally: ? ? ? ?tcp.close() for p in portList: ? ?t = threading.Thread(target=scanPort,args=(p,)) ? ?scanList.append(t)for i in range(len(portList)): ? ?scanList[i].start()for i in range(len(portList)): ? ?scanList[i].join()

測試結果:你會發現python多進程更快些。那么就是和我們想當然分析得出的結論相悖了嗎?

假設

python中or的用法。那這時可能有的同學就懵逼了,那到底是多進程快的還是多線程快呢?這里,我們根據上面兩個測試不妨大膽假設一下:

CPU密集型場景下,多進程更快,效率更高;而在IO密集型場景下,多線程更有優勢。

為了驗證大家假設,代碼如下:

?import timeimport threadingimport multiprocessing max_process = 4max_thread = max_process def fun(n,n2): ? ?#cpu密集型 ? ?for ?i in range(0,n): ? ? ? ?for j in range(0,(int)(n*n*n*n2)): ? ? ? ? ? ?t = i*j def thread_main(n2): ? ?thread_list = [] ? ?for i in range(0,max_thread): ? ? ? ?t = threading.Thread(target=fun,args=(50,n2)) ? ? ? ?thread_list.append(t)  ? ?start = time.time() ? ?print(' [+] much thread start') ? ?for i in thread_list: ? ? ? ?i.start() ? ?for i in thread_list: ? ? ? ?i.join() ? ?print(' [-] much thread use ',time.time()-start,'s') def process_main(n2): ? ?p = multiprocessing.Pool(max_process) ? ?for i in range(0,max_process): ? ? ? ?p.apply_async(func = fun,args=(50,n2)) ? ?start = time.time() ? ?print(' [+] much process start') ? ?p.close()#關閉進程池 ? ?p.join()#等待所有子進程完畢 ? ?print(' [-] much process use ',time.time()-start,'s') if __name__=='__main__': ? ?print("[++]When n=50,n2=0.1:") ? ?thread_main(0.1) ? ?process_main(0.1) ? ?print("[++]When n=50,n2=1:") ? ?thread_main(1) ? ?process_main(1) ? ?print("[++]When n=50,n2=10:") ? ?thread_main(10) ? ?process_main(10)

運行代碼從測試結果如下圖

da19a9ee2d1fb2e26d665ccd90f20b84.png

java線程與并發編程實踐,根據上面的測試圖可以看出,cpu使用率越來越高的時(即代碼循環越多的時),兩者之間的差距越來越大。從而驗證我們的假設

CPU密集型場景下,多進程更快,效率更高;而在IO密集型場景下,多線程更有優勢。

結論

根據上面的測試,我們得到如下結論:

在CPU密集型場景中(如:各種循環處理、計數等等),適合用多進程;

自學編程的app?在IO密集型場景中(如:文件處理、網絡爬蟲等),適合用多線程。

方法選擇

那么有同學看到上面的結論就明白了,多進程和多線程的效率快慢,不是始終不變的,是要應對不通場景的,不一樣的場景,用不同的方法,這才是正確的選擇。那么cpu密集型場景和io密集型場景我怎么區分和判斷呢,只有知道當前是何場景,才能做出最優的選擇。下面我就教大家來分辨場景。

簡單的辦法

直接看CPU的占用率或磁盤的IO讀寫速度。

python多線程與多進程,歸納為:計算較多就是為CPU密集型;時間等待較多(如網絡爬蟲)就是IO密集型。

下面是測試代碼,各位同學不妨自己手動測測,來讓自己有更深層的認識。

#coding=utf-8import?sysimport?multiprocessingimport?timeimport?threading??# 定義全局變量Queueg_queue?=?multiprocessing.Queue()?def?init_queue():????print("init g_queue start")????while?not?g_queue.empty():????????g_queue.get() ? ? ? ?????for?_index?in?range(10):????????g_queue.put(_index)????print("init g_queue end")????return?# 定義一個IO密集型任務:利用time.sleep()?def?task_io(task_id):????print("IOTask[%s] start"?%?task_id)????while?not?g_queue.empty():????????time.sleep(1)????????try:????????????data?=?g_queue.get(block=True, timeout=1)????????????print("IOTask[%s] get data: %s"?%?(task_id, data))????????except?Exception as excep:????????????print("IOTask[%s] error: %s"?%?(task_id,?str(excep)))????print("IOTask[%s] end"?%?task_id)????return?g_search_list?=?list(range(10000))# 定義一個計算密集型任務:利用一些復雜加減乘除、列表查找等def?task_cpu(task_id):????print("CPUTask[%s] start"?%?task_id)????while?not?g_queue.empty():????????count?=?0????????for?i?in?range(10000):????????????count?+=?pow(3*2,?3*2)?if?i?in?g_search_list?else?0????????try:????????????data?=?g_queue.get(block=True, timeout=1)????????????print("CPUTask[%s] get data: %s"?%?(task_id, data))????????except?Exception as excep:????????????print("CPUTask[%s] error: %s"?%?(task_id,?str(excep)))????print("CPUTask[%s] end"?%?task_id)????return?task_id?if?__name__?==?'__main__':????print("cpu count:", multiprocessing.cpu_count(),?"")????print(u"========== 直接執行IO密集型任務 ==========")????init_queue()????time_0?=?time.time()????task_io(0)????print(u"結束:", time.time()?-?time_0,?"")?????print("========== 多線程執行IO密集型任務 ==========")????init_queue()????time_0?=?time.time()????thread_list?=?[threading.Thread(target=task_io, args=(i,))?for?i?in?range(10)]?????for?t?in?thread_list:????????t.start()?????for?t?in?thread_list:????????if?t.is_alive():????????????t.join()????print("結束:", time.time()?-?time_0,?"")?????print("========== 多進程執行IO密集型任務 ==========")????init_queue()????time_0?=?time.time()????process_list?=?[multiprocessing.Process(target=task_io, args=(i,))?for?i?in?range(multiprocessing.cpu_count())]?????for?p?in?process_list:????????p.start()?????for?p?in?process_list:????????if?p.is_alive():????????????p.join()????print("結束:", time.time()?-?time_0,?"")?????print("========== 直接執行CPU密集型任務 ==========")????init_queue()????time_0?=?time.time()????task_cpu(0)????print("結束:", time.time()?-?time_0,?"")?????print("========== 多線程執行CPU密集型任務 ==========")????init_queue()????time_0?=?time.time()????thread_list?=?[threading.Thread(target=task_cpu, args=(i,))?for?i?in?range(10)]?????for?t?in?thread_list:????????t.start()?????for?t?in?thread_list:????????if?t.is_alive():????????????t.join()?????print("結束:", time.time()?-?time_0,?"")?????print("========== 多進程執行cpu密集型任務 ==========")????init_queue()????time_0?=?time.time()????process_list?=?[multiprocessing.Process(target=task_cpu, args=(i,))?for?i?in?range(multiprocessing.cpu_count())]?????for?p?in?process_list:????????p.start()?????for?p?in?process_list:????????if?p.is_alive():????????????p.join()?????print("結束:", time.time()?-?time_0,?"")

謝謝大家的閱讀,如果你有任何疑問和想法,請關注留言評論,第一時間為你解答心中疑惑。

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/1/111797.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息