網站首頁 編程語言 正文
前言
我們都知道python因為其GIL鎖導致每一個線程被綁定到一個核上,導致python無法通過線程實現真正的平行計算。從而導致大量的核算力的浪費。但是
concurrent.futures模塊,可以利用multiprocessing實現真正的平行計算。
但是在提高python的計算性能前,首先要明白自己的程序目前是什么類型? 對于不同類型的程序,如果安裝下述方法進行改造,可能效率并不會提高。
IO密集型:讀取文件,讀取網絡套接字頻繁。
計算密集型:大量消耗CPU的數學與邏輯運算,也就是我們這里說的平行計算。
IO密集型
可以使用asyncio 來進行優化,jit的原理是編譯為機器碼執行,但是io中可能會存在異常字符,所以也不推薦使用,當然在存在多態主機的情況下,可以采用分布式編程來提高效率,或者過concurrent.futures模塊來實現。
詳情請看下一篇博文?python 性能的優化
計算密集型
當然我們可以使用jit,分布式編程,python 調用c編程來優化性能,但是要充分利用計算機的核數,可以通過concurrent.futures模塊來實現,其在實現提高并行計算能力時時通過多進程實現。
該concurrent.futures模塊提供了一個用于異步執行callables的高級接口。
可以使用線程,使用ThreadPoolExecutor或單獨的進程 來執行異步執行 ProcessPoolExecutor。兩者都實現相同的接口,由抽象Executor類定義。
concurrent.futures會以子進程的形式,平行的運行多個python解釋器,從而令python程序可以利用多核CPU來提升執行速度。由于子進程與主解釋器相分離,所以他們的全局解釋器鎖也是相互獨立的。每個子進程都能夠完整的使用一個CPU內核。
def gcd(pair):
a, b = pair
low = min(a, b)
for i in range(low, 0, -1):
if a % i == 0 and b % i == 0:
return i
numbers = [
(1963309, 2265973), (1879675, 2493670), (2030677, 3814172),
(1551645, 2229620), (1988912, 4736670), (2198964, 7876293)
]
import time
start = time.time()
results = list(map(gcd, numbers))
end = time.time()
print 'Took %.3f seconds.' % (end - start)
Took 2.507 seconds.
import time
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor, Executor
start = time.time()
pool = ProcessPoolExecutor(max_workers=2)
results = list(pool.map(gcd, numbers))
end = time.time()
print 'Took %.3f seconds.' % (end - start)
Took 1.861 seconds.
在兩個CPU核心的機器上運行多進程程序,比其他兩個版本都快。這是因為,ProcessPoolExecutor類會利用multiprocessing模塊所提供的底層機制,完成下列操作:
1)把numbers列表中的每一項輸入數據都傳給map。
2)用pickle模塊對數據進行序列化,將其變成二進制形式。
3)通過本地套接字,將序列化之后的數據從煮解釋器所在的進程,發送到子解釋器所在的進程。
4)在子進程中,用pickle對二進制數據進行反序列化,將其還原成python對象。
5)引入包含gcd函數的python模塊。
6)各個子進程并行的對各自的輸入數據進行計算。
7)對運行的結果進行序列化操作,將其轉變成字節。
8)將這些字節通過socket復制到主進程之中。
9)主進程對這些字節執行反序列化操作,將其還原成python對象。
10)最后,把每個子進程所求出的計算結果合并到一份列表之中,并返回給調用者。
multiprocessing開銷比較大,原因就在于:主進程和子進程之間通信,必須進行序列化和反序列化的操作。
submit(fn,* args,** kwargs ) 將可調用的fn調度為執行, 并返回表示可調用執行的對象。
fn(*args **kwargs)Future
with ThreadPoolExecutor(max_workers=1) as executor:
future = executor.submit(pow, 323, 1235)
print(future.result())
map(func,* iterables,timeout = None,chunksize = 1 )
與以下類似:map(func, *iterables)
在iterables收集立即而不是懶洋洋地; func以異步方式執行,并且可以同時對func進行多次調用 。 返回的迭代器引發一個concurrent.futures.TimeoutError if next()被調用,并且在從原始調用到超時秒后結果不可用Executor.map()。 timeout可以是int或float。如果未指定 超時None,則等待時間沒有限制。
如果func調用引發異常,則在從迭代器檢索其值時將引發該異常。
使用時ProcessPoolExecutor,此方法將iterables切割 為多個塊,并將其作為單獨的任務提交給池。可以通過將chunksize設置為正整數來指定這些塊的(近似)大小。對于很長的iterables,采用大值CHUNKSIZE可以顯著改善性能相比的1.默認大小 ThreadPoolExecutor,CHUNKSIZE沒有效果。
在3.5版中更改:添加了chunksize參數。
shutdown(wait = True ) 向執行者發出信號,表示當目前待處理的期貨執行完畢時,它應該釋放它正在使用的任何資源。關機后撥打電話Executor.submit()和撥打電話 Executor.map()將會提出RuntimeError。
如果等待是True那么這種方法將不會返回,直到所有懸而未決的期貨執行完畢,并與執行相關的資源已被釋放。如果等待,False那么此方法將立即返回,并且當執行所有未決期貨時,將釋放與執行程序關聯的資源。無論wait的值如何,整個Python程序都不會退出,直到所有待處理的期貨都執行完畢。
如果使用with語句,則可以避免必須顯式調用此方法 ,該語句將關閉Executor (等待,就像Executor.shutdown()使用wait set 調用一樣True):
import shutil
with ThreadPoolExecutor(max_workers=4) as e:
e.submit(shutil.copy, 'src1.txt', 'dest1.txt')
e.submit(shutil.copy, 'src2.txt', 'dest2.txt')
e.submit(shutil.copy, 'src3.txt', 'dest3.txt')
e.submit(shutil.copy, 'src4.txt', 'dest4.txt')
原文鏈接:https://cloud.tencent.com/developer/article/1673881
相關推薦
- 2022-11-26 React常見跨窗口通信方式實例詳解_React
- 2022-06-23 Python基于鏈接表實現無向圖最短路徑搜索_python
- 2022-11-02 Go?并發編程協程及調度機制詳情_Golang
- 2022-04-17 合并兩個遞增有序的單鏈表,使合并后仍遞增有序
- 2022-02-17 不懂就問:map中使用await為什么會失效?
- 2023-05-21 C#?Replace替換的具體使用_C#教程
- 2023-05-15 使用Bash讀取和處理CSV文件的方法_linux shell
- 2024-07-18 maven:解決release錯誤:Artifact updating: Repository =‘
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支