.NET在数值计算中的速度

Yin*_*Zhu 18 .net c# managed-c++ managed-code nmath

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

我已经在stackoverflow上跟踪广告到 http://www.centerspace.net/products/

速度真的很惊人,速度接近原生代码.他们怎么能这样做?他们说:

问:NMath是"纯粹的".NET吗?

答:答案在某种程度上取决于您对"纯.NET"的定义.NMath是用C#编写的,加上一个小的Managed C++层.但是,为了更好地执行基本线性代数运算,NMath确实依赖于本机Intel Math Kernel Library(包含在NMath中).但是没有COM组件,没有DLL - 只是.NET程序集.此外,在托管C++层中分配并由本机代码使用的所有内存都从托管堆中分配.

有人可以向我解释一下吗?

Jon*_*rop 11

他们怎么能这样做?

与.NET的大多数数字库一样,NMath只不过是.NET程序集中嵌入的英特尔MKL的包装器,可能通过与C++/CLI链接来创建混合程序集.您可能只是对那些实际上没有用.NET编写的位进行基准测试.

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

更令人惊讶的是,性能差异有时是巨大的.我们测试的最昂贵的商业数值库(IMSL)比FFT基准测试中的免费FFTW库慢500多倍,并且当时没有一个库使用多个内核.

事实上,正是这些库的质量差,鼓励我们将我们自己的F#商业化为Numerics库(这是100%纯F#代码).


Hay*_*ach 10

我是ILNumerics的主要开发人员之一.所以我很有偏见,显然;)但是我们对内幕的内容更加透露,所以我会对我们的速度'秘密' 给出一些见解.

这一切都取决于系统资源的利用方式!如果你是关于纯粹的速度并且需要处理大型数组,你将确保(按重要性排序,最重要的是首先)

  1. 妥善管理你的记忆!"天真"的内存管理会导致糟糕的性能,因为它严重地强调GC,导致内存碎片并降低内存局部性(因此缓存性能).在像.NET这样的垃圾收集环境中,这归结为防止频繁的内存分配.在ILNumerics中,我们实现了一个高性能内存池,以实现这一目标(并确定性地处理临时数组,以获得一个漂亮,舒适的语法,而不会出现笨拙的函数语义).

  2. 利用并行性!这针对两者:线程级并行和数据级并行.通过线程计算的密集部分来利用多个核.在X86/X64 CPU上,SIMD /多媒体扩展(如SSE.XX和AVX)允许小而有效的矢量化.它们不能被当前的.NET语言直接寻址.这是唯一的原因,为什么MKL仍然比'纯'.NET代码更快.(但解决方案已在上升.)

  3. 为了实现高度优化的语言(如FORTRAN和C++)的速度,必须将相同的优化应用于您的代码.C#提供了这样做的选项.

注意,这些注意事项应该按顺序进行!如果瓶颈是内存带宽并且处理器花费大部分时间等待新数据,那么关心SSE扩展甚至绑定检查删除是没有意义的.此外,对于许多简单的操作而言,投入巨大的努力来实现最后的小规模达到峰值性能甚至都不值得付出代价!考虑LAPACK函数DAXPY的常见示例.它将向量X的元素添加到另一个向量Y的相应元素.如果这是第一次完成,则必须从主存储器获取X和Y的所有内存.你无能为力.而记忆是瓶颈!所以不管最后的添加是否以C#中的天真方式完成

for (int i = 0; i < C.Length; i++) {
    C[i] = X[i] + Y[i]; 
}
Run Code Online (Sandbox Code Playgroud)

或者通过使用矢量化策略完成 - 它将不得不等待内存!

我知道,这个答案确实以某种方式"回答"了这个问题,因为目前大多数这些策略都没有从上述产品中使用(但是?).通过遵循这些要点,您最终将获得比"本机"语言中的每个天真实现更好的性能.

如果您有兴趣,可以透露您对L-BFGS的实施情况?我很乐意将其转换为ILNumerics并发布比较结果,我相信,此处列出的其他库将遵循.(?)


rea*_*idt 8

关于C++/CLI的观点是正确的.要完成图片,只需另外两点:

  • .NET内存管理(垃圾收集器)显然不是问题,因为NMath仍然依赖于它

  • 性能优势实际上是由英特尔MKL提供的,它提供了针对许多CPU极其优化的实现.从我的观点来看,这是关键点.使用直接的,naiv C/C++代码不一定会比C#/ .NET提供更好的性能,有时甚至更糟.但是,C++/CLI允许您利用所有"脏"优化选项.


Pau*_*aul 5

我发布了一篇解决这个问题的博客文章.