- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我的任务是采用现有的单线程蒙特卡洛模拟并优化它。这是一个 c# 控制台应用程序,没有数据库访问,它从 csv 文件加载一次数据并在最后写出,所以它几乎只是 CPU 限制,也只使用大约 50mb 的内存。
我已经通过 Jetbrains dotTrace 分析器运行它。在总执行时间中,大约 30% 用于生成均匀随机数,24% 用于将均匀随机数转换为正态分布随机数。
基本的算法是一大堆嵌套的for循环,中间是随机数调用和矩阵乘法,每次迭代返回一个double,它被添加到一个结果列表中,这个列表是周期性的对某些收敛标准进行排序和测试(在检查点,每 5% 的总迭代次数)如果可接受,程序将跳出循环并写入结果,否则它会继续到最后。
我希望开发人员能够权衡:
上面的一些教程链接将是最受欢迎的,因为我从未编写过任何并行或多线程代码。
当前应用需要 2 小时完成 500,000 次迭代,业务需要将其扩展到 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));
}
收件人:
Parallel.For(0, CHECKPOINTS, i =>
{
results.AddRange(Oblist.Simulate(rnd, dist, n));
});
在模拟中有很多对 rnd.nextUniform() 的调用,我想我得到很多相同的值,这是否可能发生,因为现在是并行的?
也可能是 List AddRange 调用不是线程安全的问题?我看到了这个
System.Threading.Collections.BlockingCollection 可能值得使用,但它只有一个没有 AddRange 的 Add 方法,所以我必须查看那里的结果并以线程安全的方式添加。来自使用过 Parallel.For 的人的任何见解,非常感谢。我暂时切换到 System.Random 进行调用,因为在使用我的 Mersenne Twister 实现调用 nextUniform 时出现异常,可能它不是线程安全的某个数组得到一个索引越界....
最佳答案
首先,您需要了解为什么您认为使用多线程是一种优化——但实际上并非如此。如果您有多个处理器,那么使用多线程将使您的工作负载完成得更快只有,并且最多比您有可用的 CPU 快很多倍(这称为加速).在传统意义上,工作并未“优化”(即工作量并未减少 - 事实上,对于多线程,由于线程开销,工作总量通常会增加)。
因此,在设计您的应用程序时,您必须找到可以并行或重叠方式完成的部分工作。可以并行生成随机数(通过在不同的 CPU 上运行多个 RNG),但这也会改变结果,因为您会得到不同的随机数。另一种选择是在一个 CPU 上生成随机数,而在不同的 CPU 上生成其他所有内容。这可为您提供最大 3 倍的加速,因为 RNG 仍将按顺序运行,并且仍会占用 30% 的负载。
因此,如果您进行这种并行化,最终会得到 3 个线程:线程 1 运行 RNG,线程 2 生成正态分布,线程 3 执行其余的模拟。
对于这个架构,一个producer-consumer architecture是最合适的。每个线程将从队列中读取其输入,并将其输出生成到另一个队列中。每个队列都应该是阻塞的,因此如果 RNG 线程落后,归一化线程将自动阻塞,直到有新的随机数可用。为了提高效率,我会跨线程传递 100(或更大)数组中的随机数,以避免对每个随机数进行同步。
对于这种方法,您不需要任何高级线程。只使用常规线程类,没有池,没有库。您唯一需要的(不幸的是)不在标准库中的是阻塞队列类(System.Collections 中的队列类不好)。 Codeproject提供一个看起来合理的实现;可能还有其他人。
关于c# - 将单线程应用程序迁移到多线程、并行执行、蒙特卡洛模拟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1116604/
此代码似乎在启用优化的广泛使用的编译器上中断,尽管它在 Visual Studio 中运行良好。 struct foo { foo(int a) { s[0] = '0'+a%10;s[1]
我想要一个图表,其中有一个单线箭头,如下所示: 1 2 3 4 5 或者像这样(其中/假设是一个箭头:)): \/ -----------------
我正在为 Java 编写自定义规则。有两个 Tree.KIND 实例(STRING_LITERAL 和 ASSIGNMENT)需要捕获。有一个特定的行,字符串文字和赋值的逻辑都会引发问题。但 Sona
Rosettacode.org 在 Ruby 中有这个出色的单行 FizzBuzz 解决方案。 1.upto(100){|n|puts'FizzBuzz '[i=n**4%-15,i+13]||n
很多时候我使用了这个命令,它在当前目录打开了一个临时的 HTTP 服务器: python3 -m http.server 现在我需要接收文件,有没有打开ftp服务器的一行命令? 我只是在寻找一个命令行
相关主题 std::unique_ptr, deleters and the Win32 API 要将 Win32 句柄用作 RAII,我可以使用以下行 std::unique_ptr::type,
我认为必须有一个单行 Guava 解决方案来将一个不可变列表转换为另一个不可变列表,但我找不到它。假设我们有以下对象: ImmutableList input = ImmutableList.of("
我有以下 Highcharts ( http://www.highcharts.com ) 散点图。请注意,轴从 -10 开始,到 10 停止,中间为 0。我希望每条 0 线的宽度或颜色都与其他线不同
我有一个项目需要将一个视频文件与另一个音频文件合并。预期的输出是一个视频文件,其中包含来自实际视频的音频和合并后的音频文件。输出视频文件的长度将与实际视频文件的大小相同。 是否有单行 FFMPEG 命
我在 python3 类中有 2 个列表: self.keys = ["a","b","c","d"] self.values = [1,2,3,4] len(self.keys) == len(se
我有一个不同长度的数组列表,我想将它们组合成一个最大维度的矩阵,并在末尾填充零。例如(伪代码): combine( [1,2,3], [4,5]) [[1,2,3],[4,5,0]] 这是我目前的解决
例如,给定 i=5 和 n=8,我想生成 [0;0;0;0;1;0; 0;0]。具体来说,我想生成向量 v 以便: v = zeros(n,1); v(i) = 1; 有没有一种(合理的)方法可以在一
我是一名优秀的程序员,十分优秀!