我已经通过Jetbrains dotTrace分析器运行了它。总执行时间中,大约30%是生成均匀随机数,24%是将均匀随机数转换为正态分布随机数。
基本算法是大量嵌套的for循环,其中心是随机数调用和矩阵乘法,每次迭代返回一个double,该值添加到结果列表中,该列表定期排序并测试一些收敛标准(在总迭代次数的每5%处检查点),如果可接受,则程序跳出循环并写入结果,否则继续进行直到结尾。
我希望开发人员能参与以下讨论:
- 我应该使用新线程vs线程池吗?
- 我应该查看Microsoft Parallels Extension library吗?
- 我应该查看AForge.Net Parallel.For,http://code.google.com/p/aforge/ 还有其他的库吗?
关于上述问题的一些教程链接将会很受欢迎,因为我从未编写过任何并行或多线程代码。
- 生成大量正态分布随机数的最佳策略,以及如何消耗这些随机数。应用程序在此状态下从不使用均匀分布的随机数,它们总是被转换成正态分布然后被消耗。
- 用于随机数生成的好的快速库(并行?)
- 内存考虑因素:当我进行并行处理时,我需要多少额外的内存。
当前应用程序对500,000次迭代需要2小时,业务需求要将其扩展到3,000,000次迭代,并且每天调用多次,因此需要进行大量优化。
特别想听听使用了Microsoft Parallels Extension或AForge.Net Parallel的人的意见。这需要尽快投入生产,因此即使我知道它具有并发库,.net 4 beta也已经过时了,我们可以考虑在发布后随后迁移到.net 4。目前服务器为.net 2,我已提交申请审查升级到我的开发机上有的.net 3.5 SP1。
谢谢
更新
我刚试过Parallel.For实现,但结果有些奇怪。 单线程:
IRandomGenerator rnd = new MersenneTwister();
IDistribution dist = new DiscreteNormalDistribution(discreteNormalDistributionSize);
List<double> results = new List<double>();
for (int i = 0; i < CHECKPOINTS; i++)
{
results.AddRange(Oblist.Simulate(rnd, dist, n));
}
To:
Parallel.For(0, CHECKPOINTS, i =>
{
results.AddRange(Oblist.Simulate(rnd, dist, n));
});
在模拟中有许多对rnd.nextUniform()的调用,我认为我得到了许多相同的值,这可能是因为现在是并行的吗?
另外,List AddRange调用可能不是线程安全的吗?我看到System.Threading.Collections.BlockingCollection可能值得使用,但它只有一个Add方法,没有AddRange,所以我必须以线程安全的方式查看那里的结果并添加。任何使用Parallel.For的人的见解都将不胜感激。我暂时切换到System.Random进行调用,因为我在使用Mersenne Twister实现时调用nextUniform时出现异常,也许它不是线程安全的,某个数组正在获得索引超出范围的异常。