Mat*_*ero 20 .net c# random parallel-processing
考虑以下程序:
public class Program
{
private static Random _rnd = new Random();
private static readonly int ITERATIONS = 5000000;
private static readonly int RANDOM_MAX = 101;
public static void Main(string[] args)
{
ConcurrentDictionary<int,int> dic = new ConcurrentDictionary<int,int>();
Parallel.For(0, ITERATIONS, _ => dic.AddOrUpdate(_rnd.Next(1, RANDOM_MAX), 1, (k, v) => v + 1));
foreach(var kv in dic)
Console.WriteLine("{0} -> {1:0.00}%", kv.Key, ((double)kv.Value / ITERATIONS) * 100);
}
}
Run Code Online (Sandbox Code Playgroud)
这将打印以下输出:
(注意每次执行时输出会有所不同)
> 1 -> 97,38%
> 2 -> 0,03%
> 3 -> 0,03%
> 4 -> 0,03%
...
> 99 -> 0,03%
> 100 -> 0,03%
Run Code Online (Sandbox Code Playgroud)
为什么数字1以这样的频率生成?
Bat*_*eba 21
Random是不是线程安全的.
Next 没有什么特别的,以确保线程安全.
不要这样使用Random.并且不要考虑使用线程本地存储持续时间,否则你将搞乱生成器的统计属性:你必须只使用一个Random实例.一种方法是lock(_global)在该锁定区域中使用和绘制数字.
我认为这里发生的事情是,到达生成器的第一个线程获得正确生成的随机数,并且所有后续线程都为每个绘图接收0.使用32个线程的"并行化"线程池,您在上面引用的比率大致得以实现; 假设31个线程的结果放在第一个桶中.
从线程本地存储解决方案更进一步,并试图避免统计问题,我建议使用从RNGCryptoServiceProvider以下生成的随机种子:
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
private static readonly int ITERATIONS = 5000000;
private static readonly int RANDOM_MAX = 101;
private static int GetCriptoRandom()
{
using (var rng = new System.Security.Cryptography.RNGCryptoServiceProvider())
{
byte[] bytes = new byte[4];
rng.GetBytes(bytes);
return BitConverter.ToInt32(bytes, 0);
}
}
private static ThreadLocal<Random> m_rnd = new ThreadLocal<Random>(() => new Random(GetCryptoRandom()));
private static Random _rnd
{
get
{
return m_rnd.Value;
}
}
static void Main(string[] args)
{
ConcurrentDictionary<int, int> dic = new ConcurrentDictionary<int, int>();
Parallel.For(1, ITERATIONS, _ => dic.AddOrUpdate(_rnd.Next(1, RANDOM_MAX), 1, (k, v) => v + 1));
foreach (var kv in dic)
Console.WriteLine("{0} -> {1:0.00}%", kv.Key, ((double)kv.Value / ITERATIONS) * 100);
}
}
}
Run Code Online (Sandbox Code Playgroud)
在统计学上看似正确,结果范围从0.99%到1.01%.
| 归档时间: |
|
| 查看次数: |
1554 次 |
| 最近记录: |