2014-01-09 46 views
6

我有一些需要並行處理的某些項目的不斷流,所以我正在使用TPL Dataflow。值得注意的是共享相同鍵(與詞典類似)的項目應該按照先進先出的順序進行處理,而不是彼此平行(它們可以與具有不同值的其他項目平行)。散列/分片動作塊

正在開展的工作是非常CPU以最小的異步鎖的束縛,所以我的解決方案是創建ActionBlock<T> S的Environment.ProcessorCount沒有並行大小的數組,並張貼到他們根據按鍵的GetHashCode值。

創作:

_actionBlocks = new ActionBlock<Item>[Environment.ProcessorCount]; 
for (int i = 0; i < _actionBlocks.Length; i++) 
{ 
    _actionBlocks[i] = new ActionBlock<Item>(_ => ProcessItemAsync(_)); 
} 

用法:

bool ProcessItem(Key key, Item item) 
{ 
    var actionBlock = _actionBlocks[(uint)key.GetHashCode() % _actionBlocks.Length]; 
    return actionBlock.Post(item); 
} 

所以,我的問題是,這是我的問題的最佳解決方案?我傷害了性能/可伸縮性嗎?我錯過了什麼嗎?

+1

我喜歡它。我想不出另一種不需要存儲的方法。我認爲只要你確定你的散列碼是正確分佈的,這應該沒問題。 – spender

+0

依賴於'GetHashCode'的值聽起來對我來說很奇怪,你爲什麼擁有它?實際需求是否「應該按先進先出順序處理相同的項目」? – svick

+0

@svick更像是具有相同密鑰的項目應該按照先進先出順序進行處理,這與您使用字典的方式類似(並不一定是相同的項目類型)。我會更新這個問題,使其更清楚。 – i3arnon

回答

3

我認爲你的方法是合理的,假設你知道哈希碼將被很好地分配。

如果您想要針對不良分佈提供更好的保護,可以使用更大數量的ActionBlock,同時通過使用所有塊共享的單個定製TaskScheduler來限制其總併發級別。你可以找到這樣的調度程序in ParallelExtensionsExtrason MSDN

+0

這將如何解決不良分佈?如果我有一個「特殊」哈希得到比其他人更多的使用,那麼如何讓許多ActionBlocks阻止彼此不同比使用'%_actionBlocks.Length'?在你的情況下,「特殊」散列會使其隊列更大,相對於其他隊列... – i3arnon

+1

是的,它仍然會比其他的大,但它可能會比小塊數少,因爲這個特殊的散列會有更少的衝突。例如,如果所有散列的一半是0,其餘的分佈是均勻的,那麼有2個塊,所有項的3/4將進入塊0.但是有4個塊,只有5/8並且有無塊區塊,將是1/2。 – svick

+0

但你仍然只有2個線程。一個會處理5/8塊和1/8塊(6/8 = 3/4),另一個線程會處理剩下的2 1/8塊(2/8 = 1/4)。我錯過了什麼嗎? 我這樣做,當你也增加線程數,但這個代碼是非常CPU佔用,我建議每個核心AFAIK單線程。 – i3arnon