亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

python asyncio as_completed的疑惑

python asyncio as_completed的疑惑

慕無忌1623718 2024-01-27 15:28:39
在閱讀了相當多關于 asyncio 的內容之后(我對它完全是菜鳥),我已經成功編寫了一些簡單的程序來完成我想要它們做的事情。然而,我對 as_completed 方法有一些疑問:它的內部工作原理以及它如何影響我的 CPU 使用率。因此,讓有以下片段:#as_completed_example.pyimport asyncioimport tqdmimport datetimeimport sysimport signalimport random#--------------------------------------------------------------------------------------async def heavy_load(i):    #tqdm.tqdm.write('#DEBUG    '+datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')+' '+str(i))    await asyncio.sleep(random.random())    return None#--------------------------------------------------------------------------------------async def main():    length  =   int(sys.argv[1])    inputs  =   list(range(length))    pbar    =   tqdm.tqdm(total=len(inputs),position=0,leave=True,bar_format='#PROGRESS {desc}: {percentage:.3f}%|{bar}| {n_fmt}/{total_fmt} [{elapsed}<{remaining}')    tasks   =   [heavy_load(i) for i in inputs]    for future in asyncio.as_completed(tasks):        _ = await future        pbar.update(1)        pbar.refresh()            #---------------------------------------------------------------------------    def sigint_handler(signum,frame):    tqdm.tqdm.write('#INFO '+datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')+' user aborted execution!')    sys.exit(0)#---------------------------------------------------------------------------    if(__name__=='__main__'):    signal.signal(signal.SIGINT,sigint_handler)    asyncio.run(main())     如果我將其稱為 python3 as_completed_example.py 1000,它會完美地工作。然而,如果我將其稱為as_completed_example.py 1000000 (large number),我會觀察到我的進度條在相當長的一段時間內卡在 0% :-雖然我的進度條為 0%,--我的 CPU 發生了什么?因為需要一個核心才能達到 100% 使用率-為什么我future在相當長一段時間后沒有從 as_completed得到任何信息?
查看完整描述

1 回答

?
猛跑小豬

TA貢獻1858條經驗 獲得超8個贊

這里有幾個問題,如果可能的話應該避免。但對于你的前兩個問題有一個簡單的答案。為什么它固定單個CPU,為什么在打印進度條之前有延遲?有很多單線程工作要做。

asyncio在單個線程中運行所有內容,除非您明確這樣做。您正在構建的任務需要在 內部進行大量設置asyncio,尤其是對as_completed.?但它必須:

  • 創造set你的未來。不太貴,但不是免費的。

  • 設置生產者和消費者隊列來控制尚未運行的任務和已完成的任務。對于您正在使用的如此大量的任務,這可能會導致多次、大量的分配,這可能是一個真正的殺手。

  • 安排回調在 future 完成時運行。這主要是將它們從隊列移動到另一個隊列,并將它們從setfuture 中刪除,這些都不是免費的。

  • 成就每一個未來

事實上,這里有很多設置,并且這需要相當多的時間,通過改變輸入的大小可以很容易地看到這一點。在我的筆記本電腦上,運行任何期貨之前的時間確實從 size 開始急劇下降100000。此外,它會非線性下降,這表明這個大小對于我的機器上的內存層次結構特別不利(例如,在這個大小之后,會有更多的緩存未命中)。

asyncio我還發現事件循環的解析可能在這里發揮了作用。期貨的消耗必須經過一定的時間。您正在創建許多 future,其中許多幾乎是在事件循環的單個滴答內同時完成的(正如 @user4815162342 在評論中正確指出的那樣)。事件循環的每個周期都有大量工作,并且必須全部在單個線程上完成。

考慮到整個事情需要超過 1 秒才能完成這一事實,這一點非常清楚。最大睡眠間隔為 1 秒,因為random.random為您提供了 上的值[0, 1.0),但整個應用程序需要更長的時間。因此,這里正在進行的工作不僅僅是“一秒鐘的價值”,而且全部都在一個線程中進行。


查看完整回答
反對 回復 2024-01-27
  • 1 回答
  • 0 關注
  • 250 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號