AMD64阵列中的AMD64未对准:为什么没有性能下降?

时间:2014-02-03 08:31:32

标签: c arrays alignment x86-64

我试图通过在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);
}

我有以下问题:

  1. 程序中的数组访问是否真的未对齐?
  2. 我是否考虑过可能影响该计划表现的主要因素?
  3. 是否有可能ALIGNMENT_OFFSET为0和1的性能相同,因为我的CPU执行了一些“魔法”?

2 个答案:

答案 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

的性能相同

一切皆有可能,因为你的程序会调用未定义的行为。