我測試這個簡單的函數AVX標量運算速度更快
void mul(double *a, double *b) {
for (int i = 0; i<N; i++) a[i] *= b[i];
}
具有非常大的陣列,這樣勢必內存帶寬。我使用的測試代碼如下。當我編譯-O2
需要1.7秒。當我用-O2 -mavx
進行編譯時,它只需要1.0秒。非vex編碼的標量操作速度要慢70%! 這是爲什麼?
系統:[email protected](SKYLAKE微架構)32 GB MEM的,Ubuntu 16.10,GCC 6.3
測試代碼
//gcc -O2 -fopenmp test.c
//or
//gcc -O2 -mavx -fopenmp test.c
#include <string.h>
#include <stdio.h>
#include <x86intrin.h>
#include <omp.h>
#define N 1000000
#define R 1000
void mul(double *a, double *b) {
for (int i = 0; i<N; i++) a[i] *= b[i];
}
int main() {
double *a = (double*)_mm_malloc(sizeof *a * N, 32);
double *b = (double*)_mm_malloc(sizeof *b * N, 32);
//b must be initialized to get the correct bandwidth!!!
memset(a, 1, sizeof *a * N);
memset(b, 1, sizeof *b * N);
double dtime;
const double mem = 3*sizeof(double)*N*R/1024/1024/1024;
const double maxbw = 34.1;
dtime = -omp_get_wtime();
for(int i=0; i<R; i++) mul(a,b);
dtime += omp_get_wtime();
printf("time %.2f s, %.1f GB/s, efficency %.1f%%\n", dtime, mem/dtime, 100*mem/dtime/maxbw);
_mm_free(a), _mm_free(b);
}
FWIW在低2.6 GHz移動Haswell CPU上,我用0.8秒左右的時間獲得了約0.8秒的編譯時間。 –
@PaulR,感謝您的檢查。我可以稍後在我的Haswell系統上進行測試。我在Skylake系統上得到了奇怪的結果,我沒有在Haswell上得到,所以我不會感到驚訝。 –
@PaulR,我只是想出了它!'__asm__ __volatile__(「vzeroupper」:::);'在調用'omp_get_wtime()'後修正它。 –