[英]AMD64 misalignment of array in C: why no performance degradation?
我試圖通過在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);
}
我有以下問題:
根據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 ▒
因此,您沒有看到不良對齊的影響。
程序中的數組訪問是否真的未對齊?
是的,如果sizeof(DATATYPE)
大於1,則它們是。
我是否考慮過可能影響該計划績效的主要因素?
不,你沒有。 例如,100次迭代就沒有了。 編寫一個包含1億次迭代的循環,您將獲得更逼真的結果。 沒關系,我誤讀了代碼。 到目前為止,基准看起來“很好”(除了UB),但仍有其他因素需要考慮。
是否有可能
ALIGNMENT_OFFSET
為0和1的性能相同
一切皆有可能,因為您的程序會調用未定義的行為。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.