2013-01-08 34 views
0

我正嘗試使用多線程實現新的調度技術。每個線程都有自己的專用本地隊列。這個想法是,每次從程序線程創建任務時,它應該搜索隊列中的最小隊列大小(任務數較少的隊列)並排入其中。 線程之間的負載平衡方式,其中較少繁忙的隊列排隊更多。查找線程中的最小隊列大小

能否請您建議一些邏輯(或)想法如何在編程的角度動態地在給定隊列中找到最小大小的隊列。

我正在使用visual studio 2008,C++編程語言在我們自己的多線程庫中實現多速率同步數據流範例。

+0

是否有理由不能在所有線程中使用* single *隊列?那麼平衡隊列大小的問題就不會出現。 – NPE

+0

@NPE:擁有多個隊列,您可以使用單個寫入器/閱讀器模式高效地實現它們。使用線程本地隊列將有效地實現單寫入/讀取器模式 – duedl0r

+0

@NPEyes和當另一個線程變爲空閒時,可能會發生錯誤的排隊決策,導致作業在隊列中停留在繁忙的線程中。我不相信這是一個很好的設計,但我沒有嘗試過任何類似的東西,所以不確定。 – aram

回答

0

如果你真的想試試這個,每個隊列不能只保留一個公共的'int count'成員,當任務被壓入/彈出時用atomic inc/dec進行更新?

無論這樣的設計是否值得管理開銷,以及當任務排隊等待恰好運行特別冗長的工作的線程時,另一個線程正準備離隊一個非常短的工作時,偶爾會出現「錯誤」另一個問題。

+0

這就像爲每個隊列創建一個私有int計數,在任務被推入時增加它的計數,在彈出時減少它的計數,並且任務被分派到隊列中看到這個計數。 – aram

+0

是 - 迭代隊列並將任務分派到最低(或找到第一個零)的隊列中。 –

+0

正如您所說,並非完全同步,但可能是最簡單和最高效的解決方案。 – duedl0r

0

爲什麼線程不從「主」工作隊列中獲取工作?

如果您確實想要將工作項目從主源派發到一組工作者,那麼您就可以像您說的那樣進行負載平衡。在那種情況下,你真的在​​談論調度,除非你簡單地進行循環式的平衡。計劃是計算中非常深刻的主題,您可以輕鬆地花費數週或數月時間來了解計算。

+1

我猜的OP要使用無鎖隊列和希望,鎖開銷的消除將開銷大於隊列迭代每個線程 –

0

您可以在線程中同步計數器。但我想這不是你想要的。

由於您想要使用數據流來實現所有功能,所有內容都應該是隊列。

您的第一個選擇是查詢隊列中的作業數量。我認爲這並不容易,如果你想要一個單一的讀寫器模式,因爲你可能不得不使用鎖來進行這個操作,這不是你想要的。注意:我只是猜測,你不能在這裏使用無鎖隊列;要麼有計數器,要麼取兩個指針的差值,無論哪種方式你都有鎖。

第二個選項(可以使用無鎖代碼完成)是將命令發送回調度程序線程,告訴他工作線程x已經完成了一項任務。使用這種方法,您有更多的隊列,每個隊列都從一個工作線程到調度程序線程。

+0

你的第二個選項,你說'你有更多的隊列,每個從一個工作線程到調度線程'。我不清楚它。能否請你解釋清楚一點 – aram

+0

@rahul:目前你每個線程有一個隊列,對吧?您可以爲每個線程添加另一個隊列,以便每個線程有兩個隊列。一個用於向線程發送作業,另一個用於告知調度程序線程從隊列中消耗一個作業。 – duedl0r

1

正如你所看到的,試圖找到加載較少的隊列很麻煩,而且可能是一種效率低下的方法,因爲只需要一項繁重的任務就可以將更多工作添加到隊列中,而具有小型任務的隊列將不會有更多的工作並快速失效。

你最好使用工作竊取啓發式:當一個線程完成它自己的工作時,它會查看其他線程隊列並「竊取」一些工作,而不是保持空閒或被終止。

然後系統將自動平衡,每個線程都處於活動狀態,直到沒有足夠的工作給每個人。

你不應該有空閒的線程和工作等待處理的情況。

+0

+1,這是更好的,但更復雜的實現與無鎖隊列 - 隊列有多個消費者。我知道存在盜竊工作池,但不知道他們是如何在內部工作的。 –