簡體   English   中英

parallel.foreach有效,但是為什么呢?

[英]parallel.foreach works, but why?

誰能解釋,為什么該程序返回sqrt_min的正確值?

int n = 1000000;

double[] myArr = new double[n];
for(int i = n-1 ; i>= 0; i--){ myArr[i] = (double)i;}

// sqrt_min contains minimal sqrt-value
double sqrt_min = double.MaxValue;

Parallel.ForEach(myArr, num =>
{
double sqrt = Math.Sqrt(num); // some time consuming calculation that should be parallized
if(sqrt < sqrt_min){ sqrt_min = sqrt;}
});
Console.WriteLine("minimum: "+sqrt_min);

運氣很好。 有時,當您運行它時,您很幸運 ,對double的非原子讀取和寫入不會導致“ torn”值。 有時,您很幸運 ,當比賽發生時,非原子測試和設置恰好設置了正確的值。 不能保證該程序會產生任何特定的結果。

您的代碼不安全; 它只是偶然地起作用。

如果兩個線程同時運行if ,則最小值之一將被覆蓋:

  • sqrt_min = 6
  • 線程A: sqrt = 5
  • 線程B: sqrt = 4
  • 線程A進入if
  • 線程B進入if
  • 線程B分配sqrt_min = 4
  • 線程A分配sqrt_min = 5

在32位系統上,您還容易受到讀/寫撕裂的攻擊。

可以在循環中使用Interlocked.CompareExchange使其安全。

至於為什么您的原始代碼被破壞,請檢查其他答案,我不再贅述。

當沒有對共享狀態的寫訪問權時,多線程是最容易的。 幸運的是,您的代碼可以用這種方式編寫。 在這種情況下,並行linq可能會很好,但是有時開銷太大。

您可以將代碼重寫為:

double sqrt_min = myArr.AsParallel().Select(x=>Math.Sqrt(x)).Min();

在您的特定問題中,交換MinSqrt操作更快,這是可能的,因為Sqrt單調增加。

double sqrt_min = Math.Sqrt(myArr.AsParallel().Min())

您的代碼並沒有真正起作用:我在一個循環中運行了100,000次,並且在我的8核計算機上一次失敗,產生了以下輸出:

minimum: 1

我縮短了運行時間,以使錯誤顯示更快。

這是我的修改:

static void Run() {
    int n = 10;

    double[] myArr = new double[n];
    for (int i = n - 1; i >= 0; i--) { myArr[i] = (double)i*i; }

    // sqrt_min contains minimal sqrt-value
    double sqrt_min = double.MaxValue;

    Parallel.ForEach(myArr, num => {
        double sqrt = Math.Sqrt(num); // some time consuming calculation that should be parallized
        if (sqrt < sqrt_min) { sqrt_min = sqrt; }
    });
    if (sqrt_min > 0) {
        Console.WriteLine("minimum: " + sqrt_min);
    }
}


static void Main() {
    for (int i = 0; i != 100000; i++ ) {
        Run();
    }
}

考慮到共享變量讀寫之間缺乏同步,這不是巧合。

正如其他人所說,這僅基於運氣。 不過,OP和其他張貼者在創建比賽條件時都遇到了麻煩。 這很容易解釋。 該代碼生成了很多競爭條件,但是其中絕大多數(精確到99.9999%)都是無關緊要的。 最重要的是,最終結果應為0。 如果您的代碼認為根5大於根6,或者根234大於根235,它仍然不會中斷。 特別需要有一個競爭條件,該迭代會生成0。其中一個迭代具有另一個競爭條件的可能性非常非常高。 處理最后一項的迭代具有競爭條件的幾率確實非常低。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM