2010-12-09 42 views
1

我有POSIX在腦子裏執行,雖然這個問題更多的是關於架構。如何設置和管理持久多線程?

我從一個有幾個主要工作要做的更新循環開始。我可以將這些作業分爲四個或五個具有共同內存訪問要求的主要任務。這是我的想法,將這些工作分解成自己的線程,讓他們完成一個「更新」循環,並休眠到下一幀。

但是如何同步?如果我在每個週期開始時分離四個或五個線程,讓它們運行一次,死掉,然後在每次傳遞中分離另外4-5個線程?這聽起來很貴。

這聽起來更合理一些,創建這些線程,讓他們去睡覺,直到一個同步的調用喚醒它。

這是一個明智的做法嗎?我願意接受來自任何形式實現的想法。

編輯:根據到目前爲止的答案,我想補充:

  • 併發希望
  • 這些工作線程的目的是在非常短的持續時間< 250ms的
  • 工作運行由每個線程完成將始終是相同的
  • 我正在考慮4-5線程,20是一個硬限制。

回答

1

如果您每個週期都有相同的工作,並且您需要等待所有工作在下一個週期開始前完成,那麼您正在考慮正確的解決方案。

您需要一些同步對象:「幀開始信號量」,「幀結束信號量」和「結束幀事件」。如果您有n個獨立的任務每個框架,啓動N個線程,與看起來像這樣的(僞)循環:

while true: 
    wait on "start of frame semaphore" 
    <do work> 
    enter lock 
    decrement "worker count" 
    if "worker count" = 0 then set "end of frame event" 
    release lock 
    wait on "end of frame semaphore" 

然後,您可以有一個控制線程運行:

while true: 
    set "worker count" to n 
    increment "start of frame semaphore" by n 
    wait on "end of frame event" 
    increment "end of frame semaphore" by n 

這將很好地工作爲小n。如果完成每個週期所需的任務數量變得很大,那麼您可能需要使用與任務隊列相結合的線程池,這樣就不會使用線程壓倒系統。但是這種解決方案的複雜性更高,並且線程複雜性是敵人。

1

最好的可能是使用任務隊列。

任務隊列可以看作等待作業提交給他們的線程。如果有多個一次發送,它們按FIFO順序執行。

這樣,您可以維護4-5個線程,並且每個線程都會執行您提供的作業,而無需爲每個作業分離新的線程。

唯一的問題是,我不知道在C中的任務隊列的許多實現。蘋果有大中央調度,就是這樣做; FreeBSD也有一個實現。除了那些,我不知道其他。 (儘管我看起來並不十分努力)。

2

這取決於線程正在執行的任務的粒度。如果他們正在執行長時間的任務(例如第二次或更長時間),那麼創建和銷燬線程的成本與線程所做的工作相比可以忽略不計,所以我建議保持簡單並按需創建線程。相反,如果你有很短的任務(例如少於10-100毫秒左右),你肯定會開始注意到創建和銷燬大量線程的成本。在這種情況下,是的,你應該只創建一次線程,並讓它們休眠直到工作到達。您需要使用某種condition variable(例如pthread_cond_t):線程在條件變量上等待,並且當工作到達時,您發出條件變量的信號。

+0

+1。我會接受你的答案,但約翰提出了一個更接近我的需求的實施。 – bitcruncher 2010-12-10 16:12:28

0

您的想法被稱爲線程池。它們可以在WinAPI,Intel TBB和Visual Studio ConcRT中找到,我對POSIX瞭解不多,因此也無法幫助您,但它們是一個非常出色的結構,具有許多理想的屬性,例如卓越的縮放比例被分裂。

但是,我不會輕視工作所需的時間。如果你有五個任務,並且你有一個性能問題如此絕望以至於多個線程是關鍵,那麼創建線程幾乎肯定是一個可以忽略的問題。

+0

謝謝,我欣賞這個警告。儘管在這種情況下,我並沒有分手任務,因爲它耗時太長。我試圖分割不同的領域是併發的主要候選人。 – bitcruncher 2010-12-09 21:47:22

+0

@bitcruncher:併發只有一個目標:性能。如果您不需要性能,則不需要併發性。 – Puppy 2010-12-09 22:05:51