繁体   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