【问题标题】:How to parallelize for-cycle using PLINQ?如何使用 PLINQ 并行化 for-cycle?
【发布时间】:2014-08-24 12:47:25
【问题描述】:

我的任务是使用 PLINQ 并行化迭代。为此,我有一个基于 for-cycle 的函数:

public void PointGenerator(int n, Random rnd)
{
    for (int i = 1; i <= n; i++)
    {
        x = rnd.NextDouble(); 
        y = rnd.NextDouble(); // 
        if (((x - 0.5) * (x - 0.5) + (y - 0.5) * (y - 0.5)) < 0.25)
        {
            N_0++;
        }
    }
}

我如何使用 PLINQ 来做到这一点?

【问题讨论】:

    标签: c# plinq


    【解决方案1】:

    你可以这样尝试:

    public bool Check(double x, double y)
    {
        return ((x - 0.5) * (x - 0.5) + (y - 0.5) * (y - 0.5)) < 0.25;    
    }
    
    // ...
    
    N_0 = Enumerable
        .Range(0, n)
        .Select(i => new { X = rnd.NextDouble(), Y = rnd.NextDouble() })
        .AsParallel()
        .Count(p => Check(p.X, p.Y));
    

    正如Roman Dvoskin 在另一个答案下的评论中所指出的,Random 对象不是线程安全的:

    但是,随机对象不是线程安全的。如果您的应用程序从多个线程调用 Random 方法,则必须使用同步对象来确保一次只有一个线程可以访问随机数生成器。如果您不确保以线程安全的方式访问 Random 对象,则对返回随机数的方法的调用将返回 0。

    这个问题可以通过首先生成所有 XY 对来解决。

    【讨论】:

      【解决方案2】:

      range 上使用Parallel.ForEach 方法:

      var randLock = new object();
      Parallel.ForEach(
          Enumerable.Range(1, n)
      ,   () => { // if you needed the index, you could use i instead of ()
              lock (randLock) {
                  x = rnd.NextDouble(); 
                  y = rnd.NextDouble();
              }
              if (((x - 0.5) * (x - 0.5) + (y - 0.5) * (y - 0.5)) < 0.25) {
                  Interlocked.Increment(ref N_0);
              }
          });
      

      注意使用Interlocked.Increment 而不是N_0++ 以避免并发问题。 randLock 的使用具有相同的目的:根据文档,System.Random 不是线程安全的。

      【讨论】:

      • 根据 MSDN msdn.microsoft.com/en-us/library/System.Random(v=vs.110).aspx,随机不是线程安全的
      • 使用锁时并行的意义何在? Random 不可并行化,并且没有其他工作正在完成。 @BartoszKP 有更正确的答案。虽然两者都不完全正确,因为 Random 使用了多个线程。
      • @RomanDvoskin lock 之外的部分不是免费的,但我同意,rnd.NextDouble() 调用可能会占主导地位。
      • 只有未执行的代码是免费的。锁,线程有更大的成本。无功能、有副作用的风格最大。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多