2010-05-31 91 views
2

我有兩種方法的程序。第一種方法需要兩個數組作爲參數,並執行,其中來自一個陣列被有條件地寫入到其它,像這樣值的運算:關於多線程,鎖和多核處理器的多部分問題(multi^3)

void Blend(int[] dest, int[] src, int offset) 
{ 
    for (int i = 0; i < src.Length; i++) 
    { 
     int rdr = dest[i + offset]; 
     dest[i + offset] = src[i] > rdr? src[i] : rdr; 
    } 
} 

第二種方法通過他們創建int陣列和迭代的兩套獨立的這樣一組的每個陣列是Blend版與另一組的每個陣列,像這樣:

void CrossBlend() 
{ 
    int[][] set1 = new int[150][75000]; // we'll pretend this actually compiles 
    int[][] set2 = new int[25][10000]; // we'll pretend this actually compiles 
    for (int i1 = 0; i1 < set1.Length; i1++) 
    { 
     for (int i2 = 0; i2 < set2.Length; i2++) 
     { 
      Blend(set1[i1], set2[i2], 0); // or any offset, doesn't matter 
     } 
    } 
} 

第一個問題:由於此之路探尋是並行的明顯的候選人,是它的本質是線程安全的?這似乎是否定的,因爲我可以設想一個場景(不太可能,我認爲)一個線程的更改由於不同的線程〜同時操作而丟失。

如果沒有,就這樣:

void Blend(int[] dest, int[] src, int offset) 
{ 
    lock (dest) 
    { 
     for (int i = 0; i < src.Length; i++) 
     { 
      int rdr = dest[i + offset]; 
      dest[i + offset] = src[i] > rdr? src[i] : rdr; 
     } 
    } 
} 

是一個有效的解決?

第二個問題:如果是這樣,使用這種鎖的可能性能成本是多少?我認爲,如果某個線程嘗試鎖定當前被另一個線程鎖定的目標數組,則第一個線程會阻塞,直到鎖被釋放,而不是繼續處理某些內容。

另外,它需要多少時間才能獲得鎖定?納秒級別還是比這還差?這會成爲像這樣的主要問題嗎?

第三個問題:我將如何最好的辦法這個問題,將充分利用多核處理器的(這是基於潛在的錯誤的假設,一個多線程的解決辦法不是速度多線程方式在單個核心處理器上執行此操作)?我猜想我希望每個核心都有一個線程運行,但我不知道這是否正確。

+0

您將在<100ns內獲得無爭議的鎖定。 – Rusty 2010-06-05 22:18:58

+0

看看PLINQ。 [瞭解PLINQ中的加速](http://msdn.microsoft.com/en-us/library/dd997399%28v=VS.100%29.aspx) – Rusty 2010-06-05 22:26:43

回答

3

與CrossBlend的潛在爭用是set1 - 混合的目的地。與使用鎖相比,與您正在進行的工作量相比,這將比較昂貴,而不是安排每個線程在它自己的目的地上工作。這是一個給定的目標(set1中某個索引處的數組)由給定任務擁有。這是可能的,因爲結果獨立於CrossBlend處理陣列的順序。

然後每個任務應該只運行CrossBlend中的內部循環,並且該任務使用dest數組(index1)的索引參數化爲使用(或指數範圍)

您也可以並行化Blend方法,因爲每個索引都是獨立於其他索引計算的,因此在那裏沒有爭用。但是在今天的機器上,使用< 40個內核,您只需通過CrossBlend方法即可獲得足夠的並行性。

要爲N個核多核您可以

  1. 有效地運行,劃分問題分爲N個部分。鑑於set1相對於核心數量相當大,您可以將set1劃分爲N個範圍,並將每個索引範圍傳遞給運行內部CrossBlend循環的N個線程。這會給你相當好的並行性,但它不是最優的。(有些線程會更快完成,最終無需做任何工作。)
  2. 更復雜的方案是使CrossBlend內部循環的每次迭代都成爲一個單獨的任務。有N個隊列(對於N個核心),並將這些任務分配到隊列中。啓動N個線程,每個線程從隊列中讀取任務。如果一個線程隊列變爲空,它將從其他線程的隊列中獲取一個任務。

第二種方法是最適合於尺寸不規則的任務,或者被用於其他任務的系統,所以一些核心可能是時間的其他進程之間進行切換,所以你不能指望在等量工作完成大致相同的時間在不同的內核上。

第一種方法編碼簡單得多,並且可以提供很好的並行性。

+0

我忘了我的問題的另一部分:在C#中,我怎麼能確定核心數量? – MusiGenesis 2010-05-31 11:42:04