我试图通过在C中错误对齐数组而导致性能下降。我的机器有64字节高速缓存,因此我在程序中使用了64字节的步长,从未对齐的地址开始。但结果与使用正确对齐的访问时保持一致。使用多个数组也没有改变任何东西。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 10000000
#define DATATYPE long
#define ALIGNMENT __alignof__(DATATYPE)
#define CACHE_SIZE 64
#define STEP_SIZE (CACHE_SIZE / sizeof(DATATYPE))
#define NR_ARRAYS 20
#define ALIGNMENT_OFFSET 1
DATATYPE arr[N];
DATATYPE sum(DATATYPE **ptr, int size) {
DATATYPE sum = 0;
int i, j;
for (i = 0; i < size; i += STEP_SIZE) {
for (j = 0; j < NR_ARRAYS; j++) {
sum += ptr[j][i];
}
}
return sum;
}
int main() {
DATATYPE *arrs[20];
int i;
for (i = 0; i < NR_ARRAYS; i++) {
arrs[i] = (DATATYPE*)((long) malloc(N * sizeof(DATATYPE)) + ALIGNMENT_OFFSET);
}
long result = 0;
clock_t tic = clock();
for (i = 0; i < 100; i++) {
result += sum(arrs, N-1);
}
clock_t toc = clock();
printf("result: %ld ", result);
printf("elapsed: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC);
}
我有以下问题:
答案 0 :(得分:5)
根据perf(参见https://perf.wiki.kernel.org/index.php/Main_Page),代码中的大部分时间都是由与以下内容相关的循环指令(比较+跳转)获取的:
for (i = 0; i < size; i += STEP_SIZE)
│ DATATYPE sum(DATATYPE **ptr, int size) { ▒
│ DATATYPE sum = 0; ▒
│ int i, j; ▒
│ for (i = 0; i < size; i += STEP_SIZE) { ▒
│ for (j = 0; j < NR_ARRAYS; j++) { ▒
│ sum += ptr[j][i]; ▒
2.83 │60: mov (%rdx),%rdi ▒
4.37 │ add $0x8,%rdx ▒
5.50 │ add (%rdi,%r8,1),%rcx ▒
│ ▒
│ DATATYPE sum(DATATYPE **ptr, int size) { ▒
│ DATATYPE sum = 0; ▒
│ int i, j; ▒
│ for (i = 0; i < size; i += STEP_SIZE) { ▒
│ for (j = 0; j < NR_ARRAYS; j++) { ▒
86.29 │ cmp %r12,%rdx ▒
│ ↑ jne 60 ▒
0.10 │ add $0x40,%r8 ▒
因此,您没有看到不良对齐的影响。
答案 1 :(得分:1)
程序中的数组访问是否真的未对齐?
是的,如果sizeof(DATATYPE)
大于1,则为。
我是否考虑过可能影响该计划绩效的主要因素?
不,你没有。例如,100次迭代就没有了。写一个包含1亿次迭代的循环,你会得到更真实的结果。没关系,我误读了代码。到目前为止,基准看起来“很好”(除了UB),但仍有其他因素需要考虑。
是否可能,
的性能相同ALIGNMENT_OFFSET
0和1
一切皆有可能,因为你的程序会调用未定义的行为。