索引内存指针数组与ANSI C中的间接整数索引数组

时间:2012-06-04 00:21:32

标签: c pointers gcc indexing

声明

a[i] += a[j] * a[k];

将在循环中执行数千次,可能会执行数千到数百万次。代表i中条目的随机访问权的索引jka可以通过语句设置

i = i_index[l];
j = j_index[l];
k = k_index[l];

其中lfor循环的索引。整数数组i_indexj_indexk_index在程序开头设置,可能偶尔会更改。

内存指针数组是另一种选择。例如

*ap1[l] += *ap2[l] * (*ap3[l]);

其中内存指针数组ap1ap2ap3已预先设置为指向i_index最初标识的位置,{{1} }和j_index数组。它们也可能偶尔改变。

第一种方法看起来比第二种方法更清晰,但除非有某种方法可以为编译器提供额外的信息,否则它看起来会更慢。似乎XCode中的GCC编译器无法提前发现k_indexi_indexj_indexk_indexap1和{ {1}}大部分时间都是不变的。有什么方法可以让gcc编译器提高性能?

1 个答案:

答案 0 :(得分:2)

您不太可能找到一个选项,让编译器有效地将指针值缓存在您明确计算的代码的第一个版本中并保存在代码的第二个版本中。这是因为编译器需要发出代码来生成并保存一个非常大的数据结构来缓存这些值,这不是典型的编译器行为。

但是,根据您所针对的架构,这可能无关紧要。许多体系结构具有“间接基础+索引”寻址模式,这将用于aa[i] += a[j] * a[k];的访问,而在现代核心上,这些模式对平原没有任何性能损失。 “间接”寻址模式(即 - 一条指令将按i的大小多a[0],将其添加到a的基址并取消引用结果)。关于目标架构的配置文件,请参阅。

可能使用任一版本改善事物的一件事是使用struct的数组而不是三个单独的数组,以便每个值所需的三个值l在记忆中保持连续:

i = index[l].i;
j = index[l].j;
k = index[l].k;

*ap[l].i += *ap[l].j * *ap[l].k;

这意味着您的代码通过indexap数组进行一次线性遍历,而不是三次同时进行线性遍历,这有助于预取程序识别您正在执行的操作。< / p>