C# 蒙特卡洛增量风险计算优化、随机数、并行执行

发布于 2024-07-26 01:13:20 字数 2000 浏览 3 评论 0原文

我当前的任务是优化计算资本充足率的蒙特卡洛模拟一组债务人按地区划分的数字。

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

该应用程序当前是单线程,因此我需要将其设为多线程,可以查看System.Threading.ThreadPool或< strong>Microsoft 并行扩展 库,但我仅限于 .NET 2服务器在这家银行,所以我可能不得不考虑这个人的端口, http://www.codeproject .com/KB/cs/aforge_parallel.aspx

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

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

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

另外使用以下的体验如何?

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

利用 C++ 实现可能会更快。 我认为其中一些库将拥有最快的方法来直接生成正态分布的随机数,而无需翻译步骤。 它们还可能具有一些其他功能,这对后续计算很有帮助。

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

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

My current task is to optimise a Monte Carlo Simulation that calculates Capital Adequacy figures by region for a set of Obligors.

It is running about 10 x too slow for where it will need to be in production and number or daily runs required. Additionally the granularity of the result figures will need to be improved down to desk possibly book level at some stage, the code I've been given is basically a prototype which is used by business units in a semi production capacity.

The application is currently single threaded so I'll need to make it multi-threaded, may look at System.Threading.ThreadPool or the Microsoft Parallel Extensions library but I'm constrained to .NET 2 on the server at this bank so I may have to consider this guy's port, http://www.codeproject.com/KB/cs/aforge_parallel.aspx.

I am trying my best to get them to upgrade to .NET 3.5 SP1 but it's a major exercise in an organisation of this size and might not be possible in my contract time frames.

I've profiled the application using the trial of dotTrace (http://www.jetbrains.com/profiler). What other good profilers exist? Free ones?

A lot of the execution time is spent generating uniform random numbers and then translating this to a normally distributed random number. They are using a C# Mersenne twister implementation. I am not sure where they got it or if it's the best way to go about this (or best implementation) to generate the uniform random numbers. Then this is translated to a normally distributed version for use in the calculation (I haven't delved into the translation code yet).

Also what is the experience using the following?

Any alternatives you know of? I'm a C# developer so would prefer C#, but a wrapper to C++ shouldn't be a problem, should it?

Maybe even faster leveraging the C++ implementations. I am thinking some of these libraries will have the fastest method to directly generate normally distributed random numbers, without the translation step. Also they may have some other functions that will be helpful in the subsequent calculations.

Also the computer this is on is a quad core Opteron 275, 8 GB memory but Windows Server 2003 Enterprise 32 bit. Should I advise them to upgrade to a 64 bit OS? Any links to articles supporting this decision would really be appreciated.

Anyway, any advice and help you may have is really appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

浪荡不羁 2024-08-02 01:13:20

我发现 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;

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

I have found the Mersenne Twister to be quick. The problem may be in the algorithm (Box-Muller) to transform the uniform distrubution to Gaussian distribution. The standard algorithm looks like:

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

Where x1 and x2 are uniform random numbers and y1 and y2 are the gaussian distribution outputs.

The square roots are slow, but the trig is worse, and it is unstable close to 0. Taygeta's page on the subject gives a faster one (in pseudocode):

         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;

If they're not using something like this, you may be able to speed things up quite a bit by avoiding the trig functions or even pre-generating the random numbers.

远昼 2024-08-02 01:13:20

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

Have you considered pointing a profiler at your code? I've seen cases where there are simple fixes get very significant improvements. Like switching a couple of properties over to fields.

北凤男飞 2024-08-02 01:13:20

首先受限于使用 .Net 进行大规模模拟将会使您预先损失相当多的性能...但是也就是说...

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

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

Being constrained to use .Net in the first place for a large-scale simulation is going to cost you quite a bit of performance right up front...but that said...

If you're running a pure C# implementation of the Mersenne Twister, it's likely that you'll have a hard time tweaking all the performance you can out of it. If you check out the Mersenne Twister reference implementation you'll see they have a C version that is heavily optimized for SSE-capable processors - this is very fast. I don't believe it's possible in C# (or at least, I'm not aware how) to force the usage of SSE instructions with that level of optimization. I'd suggest writing a C++/CLI wrapper (or a P/Invoke wrapper) around the Mersenne Twister libraries, and seeing how that affects your performance. However, you'll have to be careful with managed-unmanaged marhsalling affecting your performance, as I have seen other posts here on SO about that issue (though I can't seem to find them right now...).

I may generate some flame for saying this, but if performance is a significant concern in your application, well-written C or C++ is almost always going to be preferable to any managed or interpreted language.

凡尘雨 2024-08-02 01:13:20

我的经验是,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 的窍门,运行起来就非常容易了。

My experience is that the relative performance of C# vs. C++ is largely dependent on what you're doing. A great discussion of that here:

C++ performance vs. Java/C#

For tight loops doing math (say vector physics calculations) c++ is a 2-3 times faster than C# although the perf may be dominated by the underlying functions like Sqrt().

I've taken a mixed language approach, (re)implementing the slowest code in C++/OpenMP with a managed C++/CLI wrapper. This allows you to only "pay for what you use".

There's a summary of how to wrap native C/C++ with C++/CLI here:

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

Once you get the hang of C++/CLI it's pretty easy to get things running.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文