簡體   English   中英

C++ 並發、協程和作業調度?

[英]C++ Concurrency, Coroutines & Job Scheduling?

我正在嘗試了解 C++ 中的多線程,以提出適合我的通用實現。 每個人都有不同的實現, Awesome CPP列出了 39 個庫。 在我看來,這是一個與任何領域的任何后勤調度問題相同的后勤問題。

在我看來,有兩種明顯的方法可以重復執行abc工作:

  1. abc拆分為 3 個單獨的任務: abc 產生 x 個線程。 排隊。 進來的作業被添加到隊列中。 每個線程從隊列中抓取下一個任務,並在任務結束時將其放回隊列中等待下一個任務。 他們可以直接訪問隊列,或者他們都可以與為他們提供任務的中央“管理器”或“調度器”線程進行通信。

  2. 獨立地在 x 個單獨的線程上按順序執行abc (並行性。)

(1) 存在一個問題,即在保持隊列和處理其上的競爭條件時可能存在大量開銷。 (1)在其他方面是直觀的,對我來說很有意義。 這就是我在現實生活中遇到現實生活中的問題時會做的事情。 從字面上看,這就是公司在現實世界中的運作方式。

(2)存在任何阻塞導致整個線程阻塞,使CPU線程空閑的問題。 並且(2)在較少的用例中的靈活性和適用性要差得多。 從好的方面來說,任務之間沒有開銷。

問題1: (1)不也有同樣的阻塞問題嗎? 如果一個線程從文件中讀取,它必須等待磁盤。 這通常是如何解決的,是否有某種方法可以在它執行諸如從磁盤讀取或寫入之類的操作時暫時返回,或者這通常只是通過運行的線程多於 CPU 線程並希望一次不會有太多塊來解決?

在我看來,(1)顯然是更好的解決方案,除了它將任務限制為中型到大型任務。 用它來做一些簡單的數學並行化(只是一個例子)是沒有意義的,因為處理隊列需要比實際處理任務更長的時間。 因此,任何給定任務的 (1) 值與存儲機制(隊列)的開銷和任務大小之間的差異成反比。 從表面上看,這聽起來不錯,直到您意識到拆分為任務的效率本身與任務的大小成正比。 簡而言之:理論上您希望每個任務都較小以提高整體效率,但實際上您希望每個任務較大以最小化隊列的開銷。

很明顯,需要一些存儲機制因為如果沒有記錄機制,您將無法跟蹤某些內容,它不一定是嚴格的隊列,而是在等待被拾取時在 memory 中記錄任務的任何形式。 隊列的優化(我用的是松散的詞,不是嚴格意義上的隊列類型)這里的#1重要因素。 任務接收其有效載荷的成本越低越好。

這讓我想到了問題 2:這就是 C++20 協程有用的地方嗎? 我花了幾個小時閱讀協程教程,但仍然不清楚它們有什么用處。 我想我明白他們的所作所為 如果我做對了,他們允許特殊類型的 function(協程)在中間暫停,將其處理連同有效負載一起返回給調用者,調用者稍后可以恢復它。 但我為什么要這樣做? 我不能通過將 function 分成兩部分來做到這一點嗎?

問題 3:協程是否意味着任務調度程序線程使用協程以某種方式優化隊列? 還是只是為了讓您線性編寫代碼,然后將這些產量放入其中以將其分解? 在這種情況下,如果我已經按照設計將我的工作分成單獨的任務,它對我沒有用處?

問題4:我想在這里重新發明輪子嗎? 這個問題已經解決了嗎? 如果是這樣,為什么會有這么多不同的實現?

Q1:不,它更可能有不同的阻塞問題。

Q2:協程有很多應用; 嘗試在“這就是 X 的用途嗎?”中替換 X。 X = { 同時,如果,返回,指針,... }。 不要向標准機構(尤其是那個)尋求洞察力; 他們最擅長標點符號和拼寫檢查。

Q3:協程可以用來優化各種結構,但是使用這種形式的真正目的是讓你的程序盡可能自然地表達問題。 Go 的 Go-routines 是如何智能使用協程的更好示例之一。

Q4:可能; 幾乎可以肯定; 因為許多解決方案是不充分的。

Q1+Q4。 沒有單一的阻塞問題,我想到的是:死鎖、活鎖、不必要的順序、不可擴展、慢。 一些結構 {{ 線程、協程、線程 + 協程 } * { 鎖、條件、消息傳遞 }} 有助於解決其中一些問題,但會引發其他問題。 我最喜歡的是 { (threads + coroutines) * (message passing) },它通常對除了慢的一切都有好處。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM