<tr id="tp1vn"><td id="tp1vn"><dl id="tp1vn"></dl></td></tr>
  1. <p id="tp1vn"></p>
  2. <sub id="tp1vn"><p id="tp1vn"></p></sub>
    <u id="tp1vn"><rp id="tp1vn"></rp></u>
    <meter id="tp1vn"></meter>
      <wbr id="tp1vn"><sup id="tp1vn"></sup></wbr>
      日韩第一页浮力,欧美a在线,中文字幕无码乱码人妻系列蜜桃 ,国产成人精品三级麻豆,国产男女爽爽爽免费视频,中文字幕国产精品av,两个人日本www免费版,国产v精品成人免费视频71pao
      網(wǎng)易首頁 > 網(wǎng)易號 > 正文 申請入駐

      UE5多線程|ThreadPool

      0
      分享至


      【USparkle專欄】如果你深懷絕技,愛“搞點(diǎn)研究”,樂于分享也博采眾長,我們期待你的加入,讓智慧的火花碰撞交織,讓知識的傳遞生生不息!

      這是侑虎科技第1917篇文章,感謝作者南京周潤發(fā)供稿。歡迎轉(zhuǎn)發(fā)分享,未經(jīng)作者授權(quán)請勿轉(zhuǎn)載。如果您有任何獨(dú)到的見解或者發(fā)現(xiàn)也歡迎聯(lián)系我們,一起探討。(QQ群:793972859)

      作者主頁:

      https://www.zhihu.com/people/xu-chen-71-65

      當(dāng)有持續(xù)時間短,又比較雜的異步任務(wù)時,可以使用ThreadPool,用固定數(shù)量的工作線程執(zhí)行任務(wù),不每次都創(chuàng)建新線程。UE4和UE5的線程池有很大區(qū)別,UE4線程池會真的創(chuàng)建很多線程,而UE5主要線程池底層復(fù)用了TaskGraph的線程,線程池只是邏輯上的概念。

      一、創(chuàng)建線程池

      線程池在FEngineLoop::PreInitPreStartupScreen函數(shù)中創(chuàng)建。

      • GThreadPool

      類型為FQueuedLowLevelThreadPool,是UE5中的新實(shí)現(xiàn),線程數(shù)量由FPlatformMisc::NumberOfWorkerThreadsToSpawn()確定。

      • GIOThreadPool

      類型為FQueuedThreadPool,線程數(shù)量由FPlatformMisc::NumberOfIOWorkerThreadsToSpawn()確定,Client為4,Server為2。

      • GBackgroundPriorityThreadPool

      類型為FQueuedThreadPool,Client為2,Server為1。

      • GLargeThreadPool

      類型為FQueuedLowLevelThreadPool,數(shù)量由FPlatformMisc::NumberOfCoresIncludingHyperthreads()確定。

      二、使用線程池

      雖然線程池實(shí)現(xiàn)比Runnable復(fù)雜,但使用方式也比較簡單。

      1. Async函數(shù)

      最常見用法,Async函數(shù)可設(shè)置EAsyncExecution::ThreadPool參數(shù),指定任務(wù)在ThreadPool里執(zhí)行。


      函數(shù)內(nèi)部會創(chuàng)建TAsyncQueuedWork封裝Function和Promise,然后使用AddQueuedWork接口把任務(wù)加到GThreadPool中。

      AddQueuedWork是線程池最重要的接口。


      2. AsyncPool函數(shù)

      與Async類似,但可以指定線程池和Work優(yōu)先級。


      3.手動調(diào)用AddQueuedWork

      AddQueuedWork函數(shù)只需要接受IQueuedWork作為參數(shù),TAsyncQueuedWork只是一個子類,我們可以創(chuàng)建子類,做自定義操作,這樣也能指定使用哪個線程池。

      比如引擎中Encode LightMap的操作,就使用了FAsyncEncode類:


      三、線程池實(shí)現(xiàn)

      1.類型定義

      類型定義可分為線程池,線程池線程,任務(wù)。

      1. 線程池

      FQueuedThreadPool:線程池基類,定義了線程池的接口。

      Allocate:創(chuàng)建線程池,類型為FQueuedThreadPoolBase。

      Create:創(chuàng)建若干工作線程。

      AddQueuedWork:向線程池添加任務(wù)。

      RetractQueuedWork:撤回任務(wù)。

      AddQueuedWork和RetractQueuedWork是線程池提供給外部調(diào)用的主要接口,注意會在多線程中被調(diào)用。

      FQueuedThreadPool有多種實(shí)現(xiàn):

      • FQueuedThreadPoolBase

      最常用,線程池的基礎(chǔ)實(shí)現(xiàn),GIOThreadPool和GBackgroundPriorityThreadPool都會使用。

      成員:

      FThreadPoolPriorityQueue QueuedWork:待處理任務(wù)的隊(duì)列。

      TArray QueuedThreads:等待接收任務(wù)的空閑線程。

      TArray AllThreads:所有工作線程。

      FCriticalSection* SynchQueue:保護(hù)任務(wù)隊(duì)列的CriticalSection,因?yàn)槿蝿?wù)隊(duì)列會被多線程修改。

      • FQueuedLowLevelThreadPool

      底層線程使用TaskGraph的ThreadPool,UE5中GThreadPool的默認(rèn)實(shí)現(xiàn)。

      • FQueuedThreadPoolWrapper

      • FQueuedThreadPoolDynamicWrapper

      • FQueuedThreadPoolTaskGraphWrapper

      2. 線程池線程

      FQueuedThread:繼承自FRunnable,表示線程池中的工作線程。可以想象,它大部分時間都處于idle狀態(tài),當(dāng)有任務(wù)來時才工作。

      成員:

      DoWorkEvent:通知線程有任務(wù)要執(zhí)行的Event。

      QueuedWork:當(dāng)前線程正在執(zhí)行的Work。

      Thread:Runnable對應(yīng)的線程。

      函數(shù):

      Run:主函數(shù),可認(rèn)為是一個等待、執(zhí)行任務(wù)的循環(huán)。

      DoWork:由ThreadPool調(diào)用,傳入一個任務(wù)并執(zhí)行。

      3. 任務(wù)

      IQueuedWork:可排隊(duì)任務(wù)的基類接口,供線程池使用。

      接口:

      DoThreadedWork:執(zhí)行任務(wù)。

      IQueuedWork有多種實(shí)現(xiàn):

      • TAsyncQueuedWork

      最常用,Async和AsyncPool函數(shù)中使用。

      DoThreadedWork:通過SetPromise執(zhí)行任務(wù)。

      • FAsyncTaskBase

      可操作內(nèi)容更多。

      DoThreadedWork:通過Task執(zhí)行任務(wù)。

      類圖如下:


      常用部分已高亮顯示

      2. FQueuedThreadPoolBase

      • 線程池創(chuàng)建

      FQueuedThreadPoolBase是默認(rèn)線程池,F(xiàn)QueuedThreadPool::Allocate函數(shù)中構(gòu)造。


      線程池通過Create函數(shù)初始化,主要工作是創(chuàng)建InNumQueuedThreads數(shù)量的工作線程,使用FQueuedThread類封裝,并把創(chuàng)建的線程加入QueuedThreads和AllThreads容器中,QueuedThreads中存儲了當(dāng)前線程池中處于空閑狀態(tài)的線程。還要創(chuàng)建CriticalSection對象SynchQueue,用于保護(hù)對QueuedWork和QueuedThreads的訪問。


      FQueuedThread

      FQueuedThread繼承自FRunnable,是一個可運(yùn)行任務(wù)的抽象,其Create函數(shù)如下。首先創(chuàng)建DoWorkEvent,用于做多線程同步,然后創(chuàng)建一個底層的Thread。線程創(chuàng)建好后進(jìn)入Run方法,初始沒有任務(wù),線程在DoWorkEvent上等待,處于休眠狀態(tài)。


      • 添加任務(wù)

      觀察AddQueuedWork函數(shù),添加任務(wù)時分成了兩種情況。

      如果線程池中尚有空閑線程,即下圖中的情況1,QueuedThreads中有元素,那么把任務(wù)分配給其中一個線程即可,這里還有一個細(xì)節(jié),QueuedThreads采用棧管理,先進(jìn)后出,這可以更好利用CPU Cache,因?yàn)檫@個Thread可能剛運(yùn)行過,同時也可以避免數(shù)組中的元素移動。得到Thread后,調(diào)用DoWork方法添加任務(wù)。

      另一種情況是所有線程都在忙碌,QueuedThreads中沒有元素,這時只能把InQueuedWork暫存到QueuedWork中,等線程執(zhí)行完之前任務(wù)后再做處理。


      FQueuedThread::DoWork方法用于通知一個Thread要執(zhí)行任務(wù)了,首先把InQueuedWork設(shè)置到其QueuedWork屬性上,然后執(zhí)行DoWorkEvent的Trigger方法,喚醒該Thread。注意這里加了一個MemoryBarrier,是為了避免CPU指令亂序優(yōu)化導(dǎo)致1071行在1074行之后執(zhí)行,導(dǎo)致錯誤。


      • 執(zhí)行任務(wù)

      執(zhí)行任務(wù)通過屬性的Run函數(shù)實(shí)現(xiàn)。Thread一開始會在DoWorkEvent上等待,被DoWork函數(shù)喚醒后,會獲取之前被賦值的QueuedWork,執(zhí)行DoThreadedWork函數(shù),這里是真正執(zhí)行任務(wù)。執(zhí)行完成后再調(diào)用ThreadPool的ReturnToPoolOrGetNextJob函數(shù),嘗試獲取暫存的QueuedWork并執(zhí)行,若沒有就把Thread歸還到QueuedThreads中,之后在DoWorkEvent上等待,進(jìn)入休眠狀態(tài)。



      流程圖示:


      3. TAsyncQueuedWork

      線程池中的任務(wù),包裝了一個Function對象,DoThreadWork函數(shù)中使用給Promise SetValue的形式來執(zhí)行Function。


      以上就是UE線程池常用的FQueuedThreadPoolBase,F(xiàn)QueuedThread,TAsyncQueuedWork組合。

      以下內(nèi)容是UE5的改動。

      4. FQueuedLowLevelThreadPool

      在UE5中,非Editor模式下GThreadPool實(shí)現(xiàn)變成了FQueuedLowLevelThreadPool。底層使用了TaskGraph,相關(guān)內(nèi)容放在后面看,這里只分析與線程池相關(guān)的部分。

      UE希望把多線程操作盡量放在TaskGraph里,這樣好管理。CPU物理核心數(shù)量是有限的,如果TaskGraph和ThreadPool都創(chuàng)建了核心數(shù)量的線程,其實(shí)在各自管理,兩邊線程都跑滿就會產(chǎn)生更多的CPU調(diào)度開銷。

      • Create

      其實(shí)不需要Create了,因?yàn)樽约翰粍?chuàng)建線程,初始化在構(gòu)造函數(shù)里完成,主要任務(wù)是獲取LowLevelTasks::FScheduler單例。


      FQueuedThreadPool::Create只是實(shí)現(xiàn)一下純虛函數(shù)。


      LowLevelTasks::Fscheduler管理了TaskGraph中的Workers線程,包括ForegroundWorkers和BackgroundWorkers,向Worker線程分發(fā)任務(wù),細(xì)節(jié)后面再看。

      5. AddQueuedWork


      首先創(chuàng)建FQueuedWorkInternalData對象來存儲QueuedWork相關(guān)數(shù)據(jù),然后設(shè)置到InQueuedWork.InternalData屬性。

      FQueuedWorkInternalData類包裝了一個LowLevelTasks::FTask,F(xiàn)Task用于把QueuedWork包裝成TaskGraph里可執(zhí)行的東西。Retract函數(shù)用于取消任務(wù),但線程池場景下不需要考慮取消。


      Task.Init函數(shù)調(diào)用有點(diǎn)繞,464行先把InQueuedWork包裝成一個Lambda函數(shù),然后在Init實(shí)現(xiàn)里面再把Lambda包裝到另一個TFunction里面。這樣就把InQueuedWork存到Task里面了,往后操作只和TaskGraph有關(guān),與線程池?zé)o關(guān)了。


      FScheduler::TryLaunch把Task添加到任務(wù)隊(duì)列中,等待Worker線程來消費(fèi)。


      6. 執(zhí)行任務(wù)

      TaskGraph中Worker線程的Run函數(shù)會循環(huán)獲取任務(wù)執(zhí)行,細(xì)節(jié)放后面TashGraph里看,這里只看一個調(diào)用棧。

      下圖中1的位置是Worker線程取Task,2的位置是執(zhí)行InQueuedWork->DoThreadedWork(),終于又回到了線程池。


      總體來看,F(xiàn)QueuedLowLevelThreadPool其實(shí)就是TaskGraph,和Async函數(shù)中傳EAsyncExecution::TaskGraph是一個效果。

      7. FQueuedThreadPoolWrapper

      不是真正的線程池,而是另一個線程池的包裝,任務(wù)都會轉(zhuǎn)發(fā)過去。UE5 Editor下GThreadPool就會設(shè)置成這個,包裝了GLargeThreadPool,目的為共用GLargeThreadPool中的線程,類似FQueuedLowLevelThreadPool共用TaskGraph的線程,因?yàn)镋ditor下后臺任務(wù)更多,因此單獨(dú)使用了GLargeThreadPool。這么做的目的還是減少線程創(chuàng)建。


      • 主要成員

      FQueuedThreadPool* WrappedQueuedThreadPool; 包裝的ThreadPool。

      TArray WorkPool; Work集合。

      TMap ScheduledWork; 當(dāng)前正在被執(zhí)行的Work。

      std::atomic MaxConcurrency; 最多允許多少Work在后臺線程池中運(yùn)行。

      std::atomic CurrentConcurrency; 當(dāng)前在后臺線程池中運(yùn)行的Work。

      • FScheduledWork

      成員中出現(xiàn)了FScheduledWork類型,它是一個容器,存儲了真正的IQueuedWork,同時也是IQueuedWork的子類,有DoThreadedWork接口。


      其中128行執(zhí)行了異步任務(wù),131行通知FQueuedThreadPoolWrapper任務(wù)執(zhí)行完,可調(diào)度下個任務(wù),會在下面介紹。

      • 初始化

      構(gòu)造函數(shù)如下,主要接受一個線程池作為后臺線程池,InMaxConcurrency表示最多同時在后臺線程池中執(zhí)行多少個任務(wù)。


      • AddQueuedWork

      AddQueuedWork首先把任務(wù)加到QueuedWork中,然后執(zhí)行Schedule函數(shù),默認(rèn)參數(shù)為空。


      Schedule函數(shù)最重要的是下面幾行。首先從QueuedWork中獲取要執(zhí)行的任務(wù),然后遞增CurrentConcurrency。接著通過AllocateWork獲取一個FScheduledWork對象,并把InnerWork封裝在里面,然后把FScheduledWork交給后臺線程池運(yùn)行。

      WorkPool容器就緩存了已創(chuàng)建的FScheduledWork對象,AllocateWork會首先從中獲取,沒有再創(chuàng)建,避免性能上的浪費(fèi)。


      • 執(zhí)行

      FScheduledWork執(zhí)行完DoThreadedWork后,會調(diào)用Release,繼續(xù)讓線程池執(zhí)行剩余任務(wù),并把自己重置,加入WorkPool中,等待下次使用。


      圖示如下:


      文末,再次感謝南京周潤發(fā) 的分享, 作者主頁:https://www.zhihu.com/people/xu-chen-71-65, 如果您有任何獨(dú)到的見解或者發(fā)現(xiàn)也歡迎聯(lián)系我們,一起探討。(QQ群: 793972859 )。

      近期精彩回顧





      特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺“網(wǎng)易號”用戶上傳并發(fā)布,本平臺僅提供信息存儲服務(wù)。

      Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

      相關(guān)推薦
      熱點(diǎn)推薦
      艾倫:雖然打丟黑球輸給吳宜澤讓我心痛,但這仍有積極的一面!

      艾倫:雖然打丟黑球輸給吳宜澤讓我心痛,但這仍有積極的一面!

      世界體壇觀察家
      2026-05-25 12:00:43
      梅西傷退美職聯(lián)收官戰(zhàn),世界杯前拉響警報(bào)

      梅西傷退美職聯(lián)收官戰(zhàn),世界杯前拉響警報(bào)

      甜份超標(biāo)的我
      2026-05-26 01:17:15
      稀土換芯片,日本在蘇州攤牌了,結(jié)果被現(xiàn)實(shí)狠狠上了一課

      稀土換芯片,日本在蘇州攤牌了,結(jié)果被現(xiàn)實(shí)狠狠上了一課

      涼羽亭
      2026-05-24 18:34:45
      廣西女孩:被好萊塢裁員后,我在美國做出爆款短劇

      廣西女孩:被好萊塢裁員后,我在美國做出爆款短劇

      澎湃新聞
      2026-05-25 17:14:25
      我59歲才頓悟一個道理:如果別人請客不想去,千萬別傻傻地回“有事去不了,下次再約”,高情商的人這樣回應(yīng)

      我59歲才頓悟一個道理:如果別人請客不想去,千萬別傻傻地回“有事去不了,下次再約”,高情商的人這樣回應(yīng)

      心理觀察局
      2026-05-13 09:07:23
      臺灣網(wǎng)紅館長陳之漢開啟川渝之行,無濾鏡直播展現(xiàn)大陸真實(shí)面貌

      臺灣網(wǎng)紅館長陳之漢開啟川渝之行,無濾鏡直播展現(xiàn)大陸真實(shí)面貌

      天空空啊
      2026-05-25 19:23:30
      一月八萬不夠花,李雙江“賴”學(xué)校不退休,兒子改名出國后再作妖

      一月八萬不夠花,李雙江“賴”學(xué)校不退休,兒子改名出國后再作妖

      一盅情懷
      2026-05-16 20:12:47
      最高院:提供 “口交” “肛交”等進(jìn)入式性服務(wù),是否屬賣淫行為?

      最高院:提供 “口交” “肛交”等進(jìn)入式性服務(wù),是否屬賣淫行為?

      周軍律師聊案子
      2026-04-21 09:50:16
      北京師范大學(xué)回應(yīng)“帶隊(duì)老師讓女生先吃飯,男生吃剩飯”傳聞:經(jīng)核查,并非該校師生,也非該校組織實(shí)習(xí)活動

      北京師范大學(xué)回應(yīng)“帶隊(duì)老師讓女生先吃飯,男生吃剩飯”傳聞:經(jīng)核查,并非該校師生,也非該校組織實(shí)習(xí)活動

      三湘都市報(bào)
      2026-05-25 08:36:19
      銅市出現(xiàn)歷史性大提貨

      銅市出現(xiàn)歷史性大提貨

      第一財(cái)經(jīng)資訊
      2026-05-25 19:13:34
      曾兩斤酒起步的相聲大師,如今已得過3次腦梗,隱居北京坐上輪椅

      曾兩斤酒起步的相聲大師,如今已得過3次腦梗,隱居北京坐上輪椅

      米果說識
      2026-05-25 19:49:06
      結(jié)果出爐后,馬辦拒絕接受,蕭旭岑五點(diǎn)回應(yīng),金溥聰承認(rèn)關(guān)鍵事實(shí)

      結(jié)果出爐后,馬辦拒絕接受,蕭旭岑五點(diǎn)回應(yīng),金溥聰承認(rèn)關(guān)鍵事實(shí)

      掉了顆大白兔糖
      2026-05-26 02:59:44
      與女星同居12年,多次求婚被拒,轉(zhuǎn)身娶世界冠軍定居香港兒女雙全

      與女星同居12年,多次求婚被拒,轉(zhuǎn)身娶世界冠軍定居香港兒女雙全

      白面書誏
      2026-05-25 20:34:59
      97年我跑長途捎了一位尼姑,尼姑下車時送我三句話,三年后全應(yīng)驗(yàn)

      97年我跑長途捎了一位尼姑,尼姑下車時送我三句話,三年后全應(yīng)驗(yàn)

      千秋文化
      2026-04-29 19:09:51
      30位情婦、60輛豪車,有錢人的生活能有多奢淫?比賭王過得還瀟灑

      30位情婦、60輛豪車,有錢人的生活能有多奢淫?比賭王過得還瀟灑

      歷史偉人錄
      2026-05-24 20:05:31
      涉嫌嚴(yán)重違紀(jì)違法,朱亞洲被查

      涉嫌嚴(yán)重違紀(jì)違法,朱亞洲被查

      都市快報(bào)橙柿互動
      2026-05-25 22:57:19
      悲哀!孩子都不在了,家長還在念叨他687分的三模成績,哭訴遺憾

      悲哀!孩子都不在了,家長還在念叨他687分的三模成績,哭訴遺憾

      火山詩話
      2026-05-23 07:15:35
      吳婉芳次子大婚!干爹張學(xué)友獻(xiàn)唱,每桌兩瓶茅臺,鄭伊健夫婦也在

      吳婉芳次子大婚!干爹張學(xué)友獻(xiàn)唱,每桌兩瓶茅臺,鄭伊健夫婦也在

      裕豐娛間說
      2026-05-24 07:05:20
      不忍了?鄭麗文啟程去美國找靠山,大陸用兩句話戳破“和平”偽裝

      不忍了?鄭麗文啟程去美國找靠山,大陸用兩句話戳破“和平”偽裝

      鍋鍋愛歷史
      2026-05-25 16:49:19
      不把總統(tǒng)當(dāng) “干部”   美國漫畫家筆下的總統(tǒng)川普

      不把總統(tǒng)當(dāng) “干部” 美國漫畫家筆下的總統(tǒng)川普

      那些看得見的老照片
      2026-04-24 17:00:03
      2026-05-26 05:03:00
      侑虎科技UWA incentive-icons
      侑虎科技UWA
      游戲/VR性能優(yōu)化平臺
      1578文章數(shù) 987關(guān)注度
      往期回顧 全部

      科技要聞

      華為:沒有先進(jìn)光刻機(jī)也能造出高端芯片

      頭條要聞

      伊朗媒體披露最高領(lǐng)袖就醫(yī)情況

      頭條要聞

      伊朗媒體披露最高領(lǐng)袖就醫(yī)情況

      體育要聞

      如果不好好守門,他可能早就繼承家業(yè)了

      娛樂要聞

      李晨鄭愷跑男停宣:12年元老被邊緣化

      財(cái)經(jīng)要聞

      起底煤礦“暗面”:假整改、假數(shù)據(jù)

      汽車要聞

      啟境GT7定檔5月29日預(yù)售 提供三電機(jī)版本

      態(tài)度原創(chuàng)

      游戲
      藝術(shù)
      本地
      教育
      公開課

      《暗黑破壞神4》國服本體免費(fèi)活動延長至8月4日

      藝術(shù)要聞

      于東來計(jì)劃建小區(qū),建筑設(shè)計(jì)用材都公開,地產(chǎn)界震動?

      本地新聞

      用云錦的方式,打開江蘇南京

      教育要聞

      罰抄10遍被投訴,一個電話讓全班沒了作業(yè),孩子就毀這類家長手里

      公開課

      李玫瑾:為什么性格比能力更重要?

      無障礙瀏覽 進(jìn)入關(guān)懷版 主站蜘蛛池模板: 亚洲超碰97无码中文字幕| 国产清品夜色一区二区三区不卡| 黑人粗长大战亚洲女| 7m精品福利视频导航| 在线无码免费的毛片视频| 亚洲熟妇av一区二区三区宅男| 久久中文亚洲| 无码视频伊人| 亚洲AV永久无码精品天堂D1| 午夜成人性爽爽免费视频| 亚洲欧美另类在线| 福利姬秘 入口| 国产剧情福利av一区二区| 天堂资源最新在线| 激情综合色五月丁香六月欧美| 无码国产精品一区二区免费97| 国产美女在线精品免费观看网址| 亚州无码熟女| 亚洲精品亚洲人成在线观看下载 | 精品日韩人妻中文字幕| 91导航| 一区二区久久不射av| 成人日韩在线观看视频| 大肉大捧一进一出好爽动态图| 亚洲无码成人电影| 国产精品久久vr专区| 久久亚洲精品人成综合网| 97夜夜澡人人爽人人| 亚洲精品中文字幕尤物综合| 边摸边吃奶边做爽gif动态图| 成人做爰免费视频免费看| 婷婷色中文字幕综合在线| 国产美女裸身网站免费观看视频| 91最新免费观看在线| 国产精品美女久久久久久麻豆| 中文字幕一区二区三区麻豆| 91热爆| 亚洲无码精品电影| 宕昌县| 人妻中文字幕精品系列| 久久做受www|