C# 为什么.NET中的矩阵乘法这么慢?

C# 为什么.NET中的矩阵乘法这么慢?,c#,.net,performance,xna,matrix-multiplication,C#,.net,Performance,Xna,Matrix Multiplication,我不太明白是什么让C#/.NET(甚至Java)中的矩阵乘法如此缓慢 看看这个基准():尝试查找更新的基准 C的整数和双性能与用MSVC++编译的C++接近。double的速度为87%,32位整数的速度为99%。我得说,相当不错。然后看看矩阵乘法。差距扩大到约19%的C#。这是一个巨大的差异,我不明白。矩阵乘法只是一堆简单的数学。怎么会变得这么慢?它的速度不应该大致相当于简单的浮点或整数运算的数量吗 这在游戏和XNA中尤为重要,因为矩阵和向量的性能对于物理引擎等方面至关重要。不久前,Mono

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

看看这个基准():尝试查找更新的基准

C的整数和双性能与用MSVC++编译的C++接近。double的速度为87%,32位整数的速度为99%。我得说,相当不错。然后看看矩阵乘法。差距扩大到约19%的C#。这是一个巨大的差异,我不明白。矩阵乘法只是一堆简单的数学。怎么会变得这么慢?它的速度不应该大致相当于简单的浮点或整数运算的数量吗

这在游戏和XNA中尤为重要,因为矩阵和向量的性能对于物理引擎等方面至关重要。不久前,Mono通过一些漂亮的向量和矩阵类增加了对SIMD指令的支持。它关闭了间隙,使单声道比手写C++更快,虽然没有SIMD的C++快。()

这是怎么回事


编辑:仔细看,我看错了第二张图。C#看起来很接近。第一个基准只是做错了什么吗?抱歉,我错过了第一个基准上的版本号。我把它作为我经常听到的“C#线性代数很慢”的一个方便的参考。我将尝试找到另一个。

对于这样的大型矩阵,CPU缓存成为限制因素。最重要的是矩阵的存储方式。基准代码正在比较苹果和橙子。C++代码使用锯齿数组,C代码使用二维数组。
重写C#代码以使用交错数组,速度也提高了一倍。重写矩阵乘法代码以避免数组索引边界检查似乎毫无意义,没有人会将这样的代码用于实际问题。

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

有关多维数组比锯齿数组慢的原因的更深入分析,请参见本文


有关数组边界检查的更多信息,请参见此。这篇文章特别警告不要使用多维数组进行矩阵乘法。

这里有一个处理矩阵乘法的更新基准(以及一些使用新任务并行库的基准):

本文介绍了不同的方法,并解释了为什么多维数组是一个糟糕的选择:

做矩阵的最简单方法 乘法是用.NET实现的 具有i,j,k的多维数组 在循环中排序。问题 这是双重的。首先是i,j.k排序 以忙碌的方式访问内存 导致不同位置的数据被删除 停车。第二,它使用的是 多维数组。是的.NET 多维数组很方便, 但是它非常慢


为了解释XNA矩阵运算速度慢这一想法的起源:

首先是初学者的问题:XNA
矩阵
类的
操作符*
将复制多个副本。这比您期望的等效C++代码慢。

(当然,如果使用
Matrix.Multiply()
,则可以通过引用传递。)

第二个原因是XNA在Xbox 360上使用的.Net紧凑框架不能访问VC++硬件(SIMD),这是本地、C++游戏可用的。


这就是为什么你总是听说它很慢,至少是这样。正如您在发布的基准测试中所看到的,当您将苹果与苹果进行比较时,它并不真的那么“慢”。

C#版本+选项:.Net Framework 1.1.4322 Uh。。。难道没有更新的版本吗?坐着等着看JonSkeet对此有何评论:-)测试是用VS2003完成的。(也请注意C++版本)因此,古老版本的.NET.@ GalaCjjelo是的,但即使如此,为什么它比整数/浮点运算慢得多?我会看看是否能找到更多的基准测试。@Matt Olenick:那是.NET的第一个(嗯…第二个)版本。此外,XNA甚至不会在.NET1.1上运行,它是.NET2.0 Compact Edition的一个实现。信不信由你,在早期版本之后,语言有了改进。谢谢,这就把事情弄清楚了。那么,为什么我总是听到(除其他原因外)“XNA很慢,因为C#中的矩阵乘法很慢”?这不是真的吗?我不知道,从我的立场来看,这是一个无法证实的说法。XNA程序员经常编写自己的矩阵乘法代码吗?C/C++代码在速度方面是不妥协的,当它爆炸时,你只能从耳朵里掏出弹片。如果C#中的某个特定算法存在速度问题,那么您总是可以依赖C/C++。不,他们使用XNA提供的库。这是有道理的。也许一些误解来自于使用操作符。