根据我的经验,.NET 比本机代码慢 2 到 3 倍。(我实现了 L-BFGS 进行多变量优化)。

我在 stackoverflow 上追踪到了广告http://www.centerspace.net/products/

速度确实惊人,接近原生代码的速度。他们怎么能这么做呢?他们说:

问。NMath 是“纯粹的”.NET 吗?

A。答案在某种程度上取决于您对“纯.NET”的定义。NMath 是用 C# 编写的,加上一个小的托管 C++ 层。然而,为了提高基本线性代数运算的性能,NMath 确实依赖于本机英特尔数学内核库(包含在 NMath 中)。但没有 COM 组件,没有 DLL,只有 .NET 程序集。此外,在托管 C++ 层中分配并由本机代码使用的所有内存都是从托管堆中分配的。

有人可以向我解释更多吗?

有帮助吗?

解决方案

关于用C++/CLI是正确的。为了全面说明情况,只是另外两个有趣的要点:

  • .净存管理(垃圾)显然不是这里的问题,因为NMath仍然取决于它

  • 性能优点是实际提供通过英特尔MKL,它提供实现极为优化对于许多Cpu。从我的角度看,这是关键点。使用直线前进,naiv C/C++的代码一定不会给你的卓越表现C#/.净,有时甚至更糟。然而C++/CLI允许利用的所有"脏"优化选择。

其他提示

他们怎么能这么做呢?

与大多数 .NET 数值库一样,NMath 只不过是嵌入在 .NET 程序集中的 Intel MKL 的包装器,可能通过与 C++/CLI 链接来创建 混合装配. 。您可能只是对那些实际上不是用 .NET 编写的部分进行了基准测试。

F#.NET 期刊文章 数值库:特殊函数、插值和随机数 (2008 年 3 月 16 日)和 数值库:线性代数和谱方法 (2008 年 4 月 16 日)测试了相当多的功能,NMath 实际上是所有商业库中最慢的。他们的 PRNG 比其他所有库都慢,比免费的 Math.NET 库慢 50%,缺少一些基本功能(例如计算能力 Gamma(-0.5))和其他基本功能(他们确实提供的与 Gamma 相关的功能)被破坏了。Extreme Optimization 和 Bluebit 在特征求解器基准测试中都击败了 NMath。NMath 当时甚至没有提供傅立叶变换。

更令人惊讶的是,有时性能差异很大。我们测试的最昂贵的商业数值库 (IMSL) 在 FFT 基准测试中比免费的 FFTW 库慢 500 倍以上,并且 没有任何 的库当时使用了多核。

事实上,正是这些图书馆的质量差才鼓励我们将自己的图书馆商业化 F# 用于数字 库(100% 纯 F# 代码)。

我的一个导致开发商 ILNumerics.所以我有偏见,明显),但我们更多的公开对我们的内部,那么,我将给出一些见解 我们 速度'秘密'。

这一切取决于如何系统利用资源!如果你是纯粹的速度和需要处理大型阵列,则将确保(订购的重要性,最重要的第一)

  1. 管理你的记忆适当!'天真'存管理将导致糟糕的表现,因为它强调的GC严重,导致记忆的碎片,并降低了存储地点(因此缓性能)。在一个垃圾收集环境等。净,这归结为阻止从经常存拨款。在ILNumerics,我们实施了一个高性能存池,以便达到的目标这一目标(及确定性的处理的临时阵列,以获得不错,舒适的语法不笨拙的功能语).

  2. 利用并行!这个目标:线水平的并行性和数据等级的并行性。多核心是利用线计算密集的部分计算的。在X86/64Cpu单指令/多媒体扩展,如SSE。XX和营允许一个小型但有效矢量化。他们都不直接地址的电流。净的语言。这是唯一的原因,为什么MKL可能仍然是速度快于'纯'.净码。(但解决办法已经上升。)

  3. 达到的目标的 速度的高度优化的语言 像FORTRAN和C++、同一优化必须得到应用你的代码这样做。C#提供的选择不这样做。

注意,这些措施应该随后在这了!它不会感到关注SSE扩展或者甚至绑检查拆除,如果瓶颈存储器的带宽,并处理器(s)花费最多时间等待新的数据。此外,许多简单的操作,它甚至不支付的投资巨大的努力达到的目标的最微小的规模达到峰值。考虑共同的例的功能特点是可扩展性。DAXPY.它增加了的要素的矢量的X相应元件的另一个矢量Y。如果这是第一次,所有的存储器,用X和Y将得到获取的主存储器。很少有什么可以做的。并存的瓶颈!所以无论如何,如果外在结束是天真的方式在C#

for (int i = 0; i < C.Length; i++) {
    C[i] = X[i] + Y[i]; 
}

或者通过使用矢量化的策略,它将必须等待!

我知道,这个答案并以某种方式'超过答案'的问题,因为这些战略的大部分目前都没有被利用从所提及的产品(?).通过下放入系统的观点,你将最终结束了更好的业绩超过每天真执行中的'当地'的语言。

如果你有兴趣,你可能会泄露你的执行情况的L-BFGS?我会很乐意把它ILNumerics和后期比较的结果并且我是肯定的,其他图书馆在这里列出的想要遵循。(?)

我已经发布了一个博客 解决这个问题,文章

的关键是 C ++ / CLI 。它允许编译的C ++代码到托管.NET组件。

今天,它的行业标准来使混合。Net/土库,以便采取优势的两个平台,用于业绩的最优化。不仅NMath,许多商业和免费的图书馆。网接口工作这样的。例如:Math.NET 数字, dnAnalytics, 极端的优化, FinMath 和其他许多人。融合与MKL是非常受欢迎的。净数字图书馆,其中大多数只利用管理C++会作为一个中级水平。但这种解决方法有若干缺点:

  1. 英特尔MKL是一个专有软件和它有点贵。但是,一些图书馆等dnAnalytics提供了一个免费更换MKL的功能与纯粹的。净码。当然,这是要慢得多,但它是自由的和完全的功能。

  2. 它降低了你的兼容性,就需要有重型管理C++核dll为32位和64位模式。

  3. 管理地调需要执行封送它慢下来表现的快速经常被称为操作,例如伽或NormalCDF.

最后两个问题的解决在RTMath FinMath图书馆。我真的不知道他们是怎么做到,但他们提供单纯的。净dll其编为任何CPU平台和支持的32位和64位.我也没有看到任何性能退化对MKL的时候,我需要叫NormalCDF数十亿倍。

由于(本机)的英特尔MKL是做数学题,你实际上没有做托管代码中的数学。你只是使用从.NET中的存储器管理器,所以结果是由Net代码容易地使用。

我学到了更多的形式@Darin季米特洛夫的意见,以他的回答和@Trevor Misfeldt对@评论达林的评论。因此张贴作为一个答案,为未来的读者。

NMath使用的P / Invoke或C ++ / CLI调用英特尔数学核心库本地函数是最密集的地方计算完成和这就是为什么它是如此之快。

时间以内英特尔MKL 的的分解的方法所用即可。的数据的任何复制是必需的下,无论是。因此,它不是CLI是否快或不是一个问题。的这是关于在执行发生即可。

此外@保罗的博客也是一个很好看的。这里的摘要。

<强> C#是快速,存储器分配不是重用变量作为ref或out参数上,而不是从方法返回新的变量。分配一个新的变量消耗内存和减慢执行。 @Haymo Kutschbach已经很好地解释这一点。

如果精度没有必要的,在从双切换到单精度的性能增益是相当大的(更不用说存储器保存用于数据存储)。

有关许多短的计算,来调用从C#中的C ++ / CLI例程,钉扎所有的指针,以在被管理的空间分配的数据,然后调用英特尔库通常比使用P-更好/ Invoke来直接从C#调用库,由于编组的数据的费用。 然而,如在注释中提到的由@Haymo Kutschbach,对于Blittable型,C ++ / CLI和C#之间没有差别。 Blittable型和仅包含blittable成员的类的数组,而不是固定的编组过程中复制。请参阅 https://msdn.microsoft.com/en -us /库/ 75dwhxf7(v = vs.110)的.aspx 以blittable和非blittable型的列表。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top