【发布时间】:2014-03-08 07:39:55
【问题描述】:
在我编写的软件的很多地方,都有short 或float 的三维数组,通常有几百万个元素。数据最好从概念上理解为一个三维数组,因为它描述了空间中规则位置的值。
我在这里看到其他地方提到 .NET CLR 在遍历这些数组时并不是非常“高效”,例如,在计算新值和填充第二个大小和维度相同的数组时。如果这是真的,为什么会这样?
出于可读性的原因,我还没有确定使用锯齿状数组的想法,但如果这真的是答案,那么我愿意,但是:
为了解决这个问题,有人建议我将数据格式化为单维数组。例如,如果我的数组具有大小为m、n 和o 的维度,那么我将创建一个float[m*n*o] 而不是float[m,n,o],并编写我自己的索引器以获取正确的数组位置在遍历期间。
具体用例是在并行化遍历中,如:
Parallel.For(0,m)((x) => for(y=0,y<n,y++) { for(z=0,z<o,z++) doSomething(array(x,y,z)); });
在单索引的情况下,会发生Parallel.ForEach(myArray, (position) => doSomething(array(Position))) 之类的事情,而不是嵌套的for 循环。
所以,问题是,真的,这会比依赖内置的 CLR 数组索引更快吗?
编辑:根据一些计时测试,我在下面提供了自己的答案。代码已包含在内。
【问题讨论】:
-
您必须对其进行分析才能确定,但我敢打赌,您的更多时间花在复制数据然后是索引查找上。
-
您说复制 3D 数组很慢的来源是什么?
-
doSomething() 最好是一个实质性的方法,否则内存总线将挫败使用线程加速代码的尝试。在这种情况下,数组索引不再相关。你有几匹马,如果你想看看哪一匹跑得最快,那就跑吧。
-
@Servy:他几乎大喊这是道听途说;他想要确认。
-
请记住 float[m,n,o] 就像 float[mno] 有大于 85k 的风险,最终会出现在大对象堆上,这可能导致到碎片化。如果您的数组大于 85kb 并且您创建/销毁它们很多,那么请考虑使用 float[m][n][o] 代替。
标签: c# algorithm multidimensional-array parallel-processing