I have a task to parallelize iterations using PLINQ. For it I have a function based on 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++;
}
}
}
How can I do it using PLINQ?
You could try like this:
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));
As noted by Roman Dvoskin in the comment under the other answer, Random
objects are not thread safe:
However, Random objects are not thread safe. If your app calls Random methods from multiple threads, you must use a synchronization object to ensure that only one thread can access the random number generator at a time. If you don't ensure that the Random object is accessed in a thread-safe way, calls to methods that return random numbers return 0.
This problem can be worked around by generating all XY pairs first.
Use Parallel.ForEach
method on a range :
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);
}
});
Note the use of Interlocked.Increment
instead of N_0++
to avoid concurrency issues. The use of randLock
serves the same purpose: according to the documentation, System.Random
is not thread-safe.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.