[英]How to parallelize for-cycle using PLINQ?
我的任务是使用PLINQ并行化迭代。 为此,我有一个基于循环的功能:
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做到这一点?
您可以这样尝试:
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对象,则对返回随机数的方法的调用将返回0。
通过首先生成所有XY对,可以解决此问题。
在范围上使用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
不是线程安全的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.