2014-05-16 50 views
3

首先,D如何創建並行foreach(底層邏輯)?D並行循環

int main(string[] args) 
{ 
    int[] arr; 
    arr.length = 100000000; 
    /* Why it is working?, it's simple foreach which working with 
     reference to int from arr, parallel function return ParallelForeach!R 
     (ParallelForeach!int[]), but I don't know what it is. 
     Parallel function is part od phobos library, not D builtin function, then what 
     kind of magic is used for this? */ 
    foreach (ref e;parallel(arr)) 
    { 
     e = 100; 
    } 
    foreach (ref e;parallel(arr)) 
    { 
     e *= e; 
    } 
    return 0; 
} 

第二,爲什麼它是慢那麼簡單的foreach? 最後,如果我創建自己的taskPool(並且不使用全局taskPool對象),程序永遠不會結束。爲什麼?

回答

5

並行返回一個結構(類型爲ParallelForeach),該結構實現了foreach重載的opApply(int delegate(...))

被調用時,結構會向專用submitAndExecute提交一個並行函數,該函數將相同的任務提交給池中的所有線程。

這個然後作用:

scope(failure) 
{ 
    // If an exception is thrown, all threads should bail. 
    atomicStore(shouldContinue, false); 
} 

while (atomicLoad(shouldContinue)) 
{ 
    immutable myUnitIndex = atomicOp!"+="(workUnitIndex, 1); 
    immutable start = workUnitSize * myUnitIndex; 
    if(start >= len) 
    { 
     atomicStore(shouldContinue, false); 
     break; 
    } 

    immutable end = min(len, start + workUnitSize); 

    foreach(i; start..end) 
    { 
     static if(withIndex) 
     { 
      if(dg(i, range[i])) foreachErr(); 
     } 
     else 
     { 
      if(dg(range[i])) foreachErr(); 
     } 
    } 
} 

其中workUnitIndexshouldContinue被共享變量和dg是在foreach委託

它之所以是較慢的是將函數傳遞給所需的開銷的僅僅是因爲線程在池中並自動訪問共享變量。

您的自定義池不關閉很可能你不finish

+0

感謝一個很好的答案關閉線程池的原因。我有另外一個問題。我如何使用(在我的課上重載)opApply?在文檔中沒有描述oppApply運算符重載。 – Seraph

+0

請參閱http://dlang.org/statement.html#ForeachStatement和http://ddili.org/ders/d.en/foreach_opapply.html –

+0

謝謝,這對我非常有幫助。 – Seraph