C#中的大数组算术

Posted

技术标签:

【中文标题】C#中的大数组算术【英文标题】:Large array arithmetics in C# 【发布时间】:2010-09-11 18:44:00 【问题描述】:

在 c# 中存储二维数组的最佳方法是在对数组中的元素执行大量算术运算时优化性能?

我们有大型(大约 1.5G)数组,例如,我们希望将它们逐个元素地相乘。性能至关重要。执行此操作的上下文在 c# 中。有什么聪明的方法来存储数组并迭代它们吗?我们可以用非托管 C++ 编写这些部分吗?这真的会提高性能吗?数组需要可供 c# 程序的其余部分访问。

目前(在 c 中)该数组存储为单个长向量。我们对数组中的每个元素执行计算并覆盖旧值。对于向量中的每个元素,计算通常是唯一的。

时序实验表明,在 C# 中将数据作为数组存储和迭代比将数据存储为二维数组要慢。我想知道是否有更好的数据处理方式。执行的具体算术与问题无关。

【问题讨论】:

我不确定您所说的计时实验是什么意思。你的意思是 C# 2D 数组比 C 2D 数组慢? c# 2d 数组比 1d c# 数组快 【参考方案1】:

安娜,

这是一个很棒的页面,讨论了传统科学编程语言(fortran、C++)和 c# 之间的性能差异。

http://msdn.microsoft.com/en-us/magazine/cc163995.aspx

根据文章 C#,在使用矩形数组 (2d) 时可以表现非常出色。这是一张图表,显示了锯齿状数组(数组的数组)和矩形数组(多维)数组之间的性能差异。

alt text http://i.msdn.microsoft.com/cc163995.fig08.gif

我建议自己进行试验,并使用 VS 2008 中的性能分析进行比较。

如果使用 C#“足够快”,那么您的应用程序将更容易维护。

祝你好运!

【讨论】:

该图中显示的结果来自 .Net 1.1。锯齿状数组实际上比 .Net 3 和 4 中的多维数组更快,如下所示:codeproject.com/KB/cross-platform/BenchmarkCppVsDotNet.aspx @AndrewS - 当我在 2008 年回答这个问题时,.Net 4 尚未发布。【参考方案2】:

为获得最佳数组性能,请确保您使用的是较低索引为 0 的一维数组。

要尽可能快地访问数组的元素,可以使用不安全的指针,如下所示:

int[] array = Enumerable.Range(0, 1000).ToArray();

int count = 0;
unsafe 
    fixed (int* pArray = array) 
        for (int i = 0; i < array.Length; i++) 
            count += *(pArray + i);
        
    

编辑该死!没注意到你说的是二维数组。这个技巧不适用于多维数组,所以我不确定它会有多大帮助。尽管您可以通过对数组索引进行一些算术来将任何数组转换为一维数组。仅取决于您是否关心索引数组或迭代数组时的性能损失。

【讨论】:

@Cameron MacFarland:实际上它可以用于 2D 数组,您只需要执行 *(pArray + (ii * cols) + jj) 之类的操作。 六个字母变量:很高兴知道。虽然这只适用于矩形数组 [,] 而不是锯齿状数组 [][] 除非您使用当前数组的列数,这会使事情变慢。 我建议测量,测量和......至少测量!即使指针算法确实在早期版本的 JIT 中带来了很多性能提升,但优化确实进步了很多。现在(.NET 4.0)的优势似乎几乎可以忽略不计。【参考方案3】:

如果您下载 F#,并引用其中一个运行时库(我认为是 FSharp.PowerPack),并使用 Microsoft.FSharp.Maths.Matrix。它会根据您使用的是密集矩阵还是稀疏矩阵进行自我优化。

【讨论】:

【参考方案4】:

您是按行还是按列或两者都对矩阵进行迭代?你总是访问附近的元素还是随机访问矩阵。

如果您的访问中有一些局部性,但您没有按顺序访问它(例如在矩阵乘法中很常见),那么您可以通过将矩阵存储在更多缓存中来获得 巨大 的性能差异- 友好的方式。

一个非常简单的方法是编写一个小的访问函数来将你的行/列索引转换为一个索引并处理一个一维矩阵,缓存友好的方式。

该函数应将附近的坐标分组到附近的索引中。如果您使用两种尺寸的幂,则可以使用 morton-order。对于非幂大小,您通常可以仅将最低 4 位带入 morton 顺序,并对高位使用普通索引算术。即使坐标到索引的转换看起来成本很高,您仍然会获得显着的加速。

http://en.wikipedia.org/wiki/Z-order_(curve)

顺便说一句,10 倍以上的加速是现实的。不过,这取决于您在矩阵上运行的算法。

【讨论】:

以上是关于C#中的大数组算术的主要内容,如果未能解决你的问题,请参考以下文章

算术运算导致不安全 C# 中的溢出

linq中的算术运算使用实体框架mvc C#

C# 使用列中的算术运算符通过字符串查询 DataTable

对数组中的元素执行算术运算 - android/java

算术运算中的上溢或下溢

MATLAB-算术运算