簡體   English   中英

如何使用pthread和條件變量改善多線程應用程序中的實時行為?

[英]How can I improve my real-time behavior in multi-threaded app using pthreads and condition variables?

我有一個使用pthreads的多線程應用程序。 我有一個互斥鎖()和條件變量()。 有兩個線程,一個線程正在為第二個線程生成數據,一個工人正在嘗試以實時方式處理生成的數據,以使一個卡盤的處理盡可能接近固定時間段的流逝。

這很好用,但是,有時當生產者線程釋放工作者正在等待的條件時,在工作者線程獲得控制並再次執行之前,可以看到將近一整秒的延遲。

我知道這是因為,在生產者釋放工人正在等待的條件之前,如果是時候處理另一個卡盤,它將為工人做一個處理,然后在工人線程中收到條件后立即執行如果是時候加工另一個卡盤了。

在后一種情況下,我看到我要多次處理卡盤。 我想消除這種效率損失,並盡我所能使卡盤在盡可能接近所需頻率的位置滴答作響。

我有什么辦法可以減少從生產者釋放條件到檢測到該條件被釋放以便工人恢復處理之間的延遲? 例如,這有助於生產者調用某些東西來迫使自己被上下文切換嗎?

最重要的是,工人每次要求生產者自行創建工作時都必須等待,以便生產者可以在告知工人准備好再次並行運行之前對工人的數據結構進行處理。 生產者的獨占訪問時間很短,但是在此期間,我還要檢查生產者具有獨占訪問權時生產者代表工人進行的實時工作。 不知何故,我退回並行運行有時會導致嚴重的延遲,這是我想避免的。 請提出如何最好地做到這一點。

我可以建議以下模式。 通常,可以使用相同的技術,例如在某些實時渲染器中對幀進行預緩沖或類似的操作時。

首先,很明顯,您在消息中描述的方法僅在兩個線程始終被均等(或幾乎均等)加載時才有效 如果沒有,多線程實際上將使您受益。

現在,讓我們考慮一個最適合您的問題的線程模式。 假設我們有一個yieldingprocessing線程。 首先,它們准備要處理的數據塊,其次進行處理並將處理結果存儲在某個地方(實際上並不重要)。

使這些線程協同工作的有效方法是適當的屈服機制。 您的yielding線程應該只將數據添加到某個共享緩沖區中,而實際上並不關心該數據會發生什么。 而且,您的緩沖區可以實現為簡單的FIFO隊列。 這意味着您的yielding線程應該准備要處理的數據並對隊列進行PUSH調用:

X = PREPARE_DATA()
BUFFER.LOCK()
BUFFER.PUSH(X)
BUFFER.UNLOCK()

現在, processing線程。 應該以這種方式描述它的行為(您可能應該在對EMPTY調用之間添加一些人為的延遲,例如SLEEP(X)

IF !EMPTY(BUFFER) PROCESS(BUFFER.TOP)

這里的重要時刻是您的處理線程應如何處理已處理的數據。 一種明顯的方法意味着在處理完數據后進行POP調用,但是您可能想提出一些更好的主意。 無論如何,在我的變體中,這看起來像

// After data is processed
BUFFER.LOCK()
BUFFER.POP()
BUFFER.UNLOCK()

請注意, yieldingprocessing線程中的鎖定操作實際上不會影響您的性能,因為每個數據塊僅調用一次。


現在,有趣的部分。 正如我在開始時所寫的那樣,這種方法僅在線程在CPU /資源使用方面的行為相同時才有效。 有一種方法可以使這些線程解決方案有效,即使這種情況並非總是如此,並且在某些其他運行時條件上也很重要。

這種方式意味着創建另一個線程,稱為controller線程。 該線程將僅比較每個線程用於處理一個數據塊並相應地平衡線程優先級的時間。 實際上,我們不必“比較時間”controller線程可以像這樣簡單地工作:

IF BUFFER.SIZE() > T
   DECREASE_PRIORITY(YIELDING_THREAD)
   INCREASE_PRIORITY(PROCESSING_THREAD)

當然,您可以在此處實現一些更好的啟發式方法,但是使用controller線程的方法應該很清楚。

暫無
暫無

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

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