如何优化指针间接层

时间:2009-09-10 12:18:47

标签: c++ c performance optimization gcc

我正在尝试在繁重的计算应用程序中优化这类内容:

说我有一个

 double d[500][500][500][500];

并且至少从编译器角度来看,以下内容非常昂贵

double d[x][y][j][k]

我想告诉编译器它是连续的内存,以便于计算偏移量。

在我的例子中,

我有这样的事情:

double n=0;
for (int i=0; i < someNumber; i++)
{
    n+=d[x][i][j][k] /*(some other math calculations)*/;
}

所以我尝试通过将其放在一个单独的函数中来优化它

void func( double*** const restrict dMatrix )
{
  /* and do some calculations herel*/

}

没有多大帮助:(

有关优化它的任何建议吗?

}

修改

我无法重写代码以使数组成为一维的。我必须使用这个多维野兽:(

7 个答案:

答案 0 :(得分:14)

我怀疑问题不是偏移计算,而是实际访问内存。当你声明一个4维数组并访问具有相邻索引的任何级别的元素时,除了最后一个之外,内存地址实际上相距很远,这会导致大量缓存未命中和显着减速。

答案 1 :(得分:5)

请注意,这是很多(大约466 GB,如果我的数学是正确的)数据,并且要注意交换和缓存访问问题。如果你实际上没有使用500 ^ 4个元素,你需要对你的应用程序进行概要分析,看它确实是“间接”,这会让你在性能方面付出代价。

答案 2 :(得分:5)

C编译器当然知道内存何时连续。你不必告诉它。

答案 3 :(得分:4)

正如其他地方所提到的,无论如何内存是连续的,缓慢来自缓存未命中。要减少这种情况,您需要确保(如果可能)您在相邻元素上进行迭代以获得最大的缓存一致性,而不是在内存中进行大量跳转。在C中我相信这意味着你最常用的迭代值应该是数组的最后一个维度,最不常见的迭代应该是第一个维度:参见the Wikipedia article

答案 4 :(得分:3)

C中没有多维数组。所有数组都是1维的,编译器只计算正确的偏移量。这意味着您无法通过自己计算偏移量来加快速度。这是C语言的限制。

您可以通过减少缓存未命中量来加快速度。 a[0][?][?][?]可能远离a[1][?][?][?]

答案 5 :(得分:1)

您以前能够做的事情就是使用增量指针来加速访问阵列。

所以使用一个简单的数组。

char aString[500];
for (int i=0; i<500; i++)
    aString[i] = 0;     // Array access is really a multiply!

变为

char aString[500];
char *aStringPtr;
for (aStringPtr= &aString[0] ; aStringPtr<&aString[0]+500; aStringPtr++)
    *aStringPtr = 0;

这比第一个例子快两倍。

答案 6 :(得分:1)

作为unwind said,你的数组大约是半TB。你需要一个足够大的磁盘和一个足够大的页面文件。然后,您可能还需要一个非常大的RAM。最后,您的缓存大小也很重要,因此您访问元素的顺序将产生巨大的差异。地址计算将在噪声中。

如果这实际上是一个稀疏数组,你应该这样对待它。实际上,使用指针数组组织它可能是一种很好的方法。

实际上,只需将数据加载到该数组中,如果以最快的方式完成,可能需要数小时。

顺便说一句,我希望你在64位机器上。 32位地址只能访问大约4 GB。