8

我目前的任务是优化蒙特卡洛模拟,该模拟按地区计算一组债务人的资本充足率数据。

它的运行速度要慢约 10 倍,这对于需要在生产中运行以及需要运行次数或每日运行的地方来说太慢了。此外,在某个阶段,结果数据的粒度可能需要改进到桌面级别,我得到的代码基本上是一个原型,业务部门在半生产能力中使用它。

该应用程序当前是单线程的,因此我需要将其设为多线程,可能会查看Microsoft Parallel ExtensionsSystem.Threading.ThreadPool库,但我受限于该银行服务器上的 .NET 2,因此我可能不得不考虑这个人的端口,http://www.codeproject.com/KB/cs/aforge_parallel.aspx

我正在尽我最大的努力让他们升级到 .NET 3.5 SP1,但对于这种规模的组织来说,这是一项重大的工作,在我的合同期限内可能是不可能的。

我已经使用dotTrace ( http://www.jetbrains.com/profiler )的试用版分析了应用程序。还有哪些其他好的分析器?免费的?

大量执行时间用于生成均匀随机数,然后将其转换为正态分布的随机数。他们正在使用 C# Mersenne twister实现。我不确定他们从哪里得到它,或者它是否是最好的方法(或最好的实现)来生成统一的随机数。然后将其转换为用于计算的正态分布版本(我还没有深入研究翻译代码)。

另外使用以下内容是什么体验?

你知道的任何替代方案?我是 C# 开发人员,所以更喜欢 C#,但是C++ 的包装器应该不是问题,不是吗?

利用 C++ 实现可能更快。我认为其中一些库将具有直接生成正态分布随机数的最快方法,而无需转换步骤。他们也可能有一些其他的功能,这将有助于后续的计算。

此外,这台计算机是四核 Opteron 275、8 GB 内存,但 Windows Server 2003 Enterprise 32 位。我应该建议他们升级到64 位操作系统吗?任何支持此决定的文章链接都将不胜感激。

无论如何,非常感谢您提供的任何建议和帮助。

4

4 回答 4

4

我发现 Mersenne Twister 很快。问题可能在于将均匀分布转换为高斯分布的算法(Box-Muller)。标准算法如下所示:

y1 = sqrt( - 2 ln(x1) ) cos( 2 pi x2 )
y2 = sqrt( - 2 ln(x1) ) sin( 2 pi x2 )

其中 x1 和 x2 是均匀随机数,y1 和 y2 是高斯分布输出。

平方根很慢,但三角函数更差,接近 0 时不稳定。Taygeta关于该主题的页面给出了更快的结果(伪代码):

         float x1, x2, w, y1, y2;

     do {
             x1 = 2.0 * ranf() - 1.0;
             x2 = 2.0 * ranf() - 1.0;
             w = x1 * x1 + x2 * x2;
     } while ( w >= 1.0 );

     w = sqrt( (-2.0 * ln( w ) ) / w );
     y1 = x1 * w;
     y2 = x2 * w;

如果他们不使用这样的东西,您可以通过避免使用三角函数甚至预先生成随机数来加快速度。

于 2009-07-06T17:57:53.467 回答
1

您是否考虑过将分析器指向您的代码?我见过一些简单的修复得到非常显着改进的案例。就像将几个属性切换到字段一样。

于 2009-07-06T17:23:09.527 回答
0

首先受限于使用 .Net 进行大规模模拟会在前期花费你相当多的性能......但是这就是说......

如果您正在运行 Mersenne Twister 的纯 C# 实现,您可能很难调整所有性能。如果您查看 Mersenne Twister参考实现,您会发现他们有一个针对支持 SSE 的处理器进行了高度优化的 C 版本 - 这非常快。我不相信在 C# 中(或者至少,我不知道如何)以这种优化级别强制使用 SSE 指令是可能的。我建议围绕 Mersenne Twister 库编写一个 C++/CLI 包装器(或 P/Invoke 包装器),看看它如何影响您的性能。但是,您必须小心影响您的性能的托管-非托管编组,因为我在这里看到了关于该问题的其他帖子(尽管我可以'

我这样说可能会引起一些争议,但如果性能是您的应用程序中的一个重要问题,那么编写良好的 C 或 C++ 几乎总是比任何托管或解释语言更可取。

于 2009-07-06T17:43:09.017 回答
0

我的经验是,C# 与 C++ 的相对性能很大程度上取决于您在做什么。这里有一个很好的讨论:

C++ 性能与 Java/C#

对于进行数学运算(比如矢量物理计算)的紧密循环,c++ 比 C# 快 2-3 倍,尽管性能可能受 Sqrt() 等底层函数的支配。

我采用了混合语言方法,使用托管 C++/CLI 包装器(重新)实现 C++/OpenMP 中最慢的代码。这允许您只“为您使用的东西付费”。

这里有一个关于如何用 C++/CLI 封装原生 C/C++ 的总结:

http://msdn.microsoft.com/en-us/library/ms235281.aspx

一旦你掌握了 C++/CLI 的窍门,就很容易让事情运行起来。

于 2009-07-08T21:34:19.143 回答