My program performs many simulations, each of which calls for many random numbers to be generated. The serial method is straightforward and works. However, in my pursuit of parallelizing the work I believe I found a more straightforward method than what I could find. The other methods are somewhat dated.
Am I missing something that will make my method susceptible to any of the myriad of multithreading problems? I ask this because my software is not benefiting from my addition and I am wondering if I missed a problem. My method uses the ability of a Parallel.For
to instantiate a variable for individual thread use. In this case each thread gets its own Random
.
Timing:
My method: 4s
Stephen: 14s
Jon: 16s
Clearly I don't know as much as Stephen or Jon so I'm concerned I missed something.
My method:
Random rnd = new Random();
int trials = 1_000_000;
ParallelOptions po = new ParallelOptions();
po.MaxDegreeOfParallelism = 4;
await Task.Run(() =>
{
Parallel.For<Random>(0, trials, po, () => new Random(rnd.Next()), (i, loop, local) =>
{
for (int work = 0; work < 1000; work++)
{
local.Next();
}
return local;
},
(x) => { }
);
});
This next method is by Stephen Toub on the MSDN Blog:
public static class RandomGen2
{
private static Random _global = new Random();
[ThreadStatic]
private static Random _local;
public static int Next()
{
Random inst = _local;
if (inst == null)
{
int seed;
lock (_global) seed = _global.Next();
_local = inst = new Random(seed);
}
return inst.Next();
}
}
await Task.Run(() =>
{
Parallel.For(0, trials, i =>
{
for (int work = 0; work < 1000; work++)
{
RandomGen2.Next();
}
});
});
This next method is by Jon Skeet on his blog:
public static class ThreadLocalRandom
{
private static readonly Random globalRandom = new Random();
private static readonly object globalLock = new object();
private static readonly ThreadLocal<Random> threadRandom = new ThreadLocal<Random>(NewRandom);
public static Random NewRandom()
{
lock (globalLock)
{
return new Random(globalRandom.Next());
}
}
public static Random Instance { get { return threadRandom.Value; } }
public static int Next()
{
return Instance.Next();
}
}
await Task.Run(() =>
{
Parallel.For(0, trials, i =>
{
for (int work = 0; work < 1000; work++)
{
ThreadLocalRandom.Instance.Next();
}
});
});
Aucun commentaire:
Enregistrer un commentaire