为什么.NET中的矩阵乘法如此之慢?

Mat*_*nik 15 .net c# performance xna matrix-multiplication

我不太明白是什么使C#/ .NET(甚至Java)中的矩阵乘法变得如此之慢.

看一下这个基准测试(来源):试图找到更新的基准测试.

Java vs C#vs C++细分http://img411.imageshack.us/img411/9324/perf.gif

C#的整数和双重性能非常接近用MSVC++编译的C++.双精度为87%,32位整数为99%.非常好,我会说.但接下来看矩阵乘法.差距扩大到C#的速度约为19%.这是一个非常大的差异,我不明白.矩阵乘法只是一堆简单的数学运算.怎么这么慢?它不应该与等量的简单浮点或整数运算一样快吗?

这尤其是游戏和XNA的关注点,其中矩阵和矢量性能对物理引擎等事物至关重要.前一段时间,Mono通过一些漂亮的矢量和矩阵类增加了对SIMD指令的支持.它缩小了差距,使Mono比手写的C++更快,尽管没有C++与SIMD一样快.(来源)

矩阵乘法比较http://img237.imageshack.us/img237/2788/resultse.png

这里发生了什么?

编辑:仔细观察,我误读了第二张图.C#看起来非常接近.第一个基准测试只是做了可怕的错误吗?对不起,我错过了第一个基准测试的版本号.我抓住它作为我总是听到的"C#线性代数很慢"的方便参考.我会试着找另一个.

Han*_*ant 13

对于像这样的大型矩阵,CPU缓存成为限制因素.什么是非常重要的是矩阵的存储方式.基准代码是比较苹果和橙子.C++代码使用锯齿状数组,C#代码使用二维数组.

重写C#代码以使用锯齿状数组,并使其速度加倍.重写矩阵乘法代码以避免数组索引边界检查似乎毫无意义,没有人会使用这样的代码来解决实际问题.


And*_*ell 10

为了解释XNA矩阵运算缓慢的想法的起源:

首先是初学者级别的问题:XNA Matrix课程operator*将制作几个副本.这比您对等效C++代码的期望要慢.

(当然,如果你使用Matrix.Multiply(),那么你可以通过引用传递.)

第二个原因是XNA在Xbox 360上使用的.NET Compact Framework无法访问本机C++游戏可用的VMX硬件(SIMD).

这就是为什么你一直听说它很慢,至少.从你发布的基准测试中可以看出 - 当你比较苹果和苹果时,它并不是那么"慢".


Bri*_*eon 7

很明显,基准作者并不了解C#中的锯齿状和多维数组之间的区别.比较真的不是一个苹果对苹果.当我改变代码以使用锯齿状数组而不是多维数组以便它以类似于Java的方式运行时,C#代码最终运行速度提高了两倍......使它比Java快(尽管只是勉强可能统计上无关紧要的).在C#中,多维数组的速度较慢,因为在查找数组插槽时需要额外的工作,因为无法为它们消除数组边界检查...

请参阅此问题,以更深入地分析为什么多维数组比锯齿状数组慢.

有关数组边界检查的更多信息,请参阅此博客.本文特别警告不要使用多维数组进行矩阵乘法.