Я реализовал скалярное ядро с добавлением матрицы.В чем преимущества использования vaddss вместо addss в добавлении скалярной матрицы?
#include <stdio.h>
#include <time.h>
//#include <x86intrin.h>
//loops and iterations:
#define N 128
#define M N
#define NUM_LOOP 1000000
float __attribute__((aligned(32))) A[N][M],
__attribute__((aligned(32))) B[N][M],
__attribute__((aligned(32))) C[N][M];
int main()
{
int w=0, i, j;
struct timespec tStart, tEnd;//used to record the processiing time
double tTotal , tBest=10000;//minimum of toltal time will asign to the best time
do{
clock_gettime(CLOCK_MONOTONIC,&tStart);
for(i=0;i<N;i++){
for(j=0;j<M;j++){
C[i][j]= A[i][j] + B[i][j];
}
}
clock_gettime(CLOCK_MONOTONIC,&tEnd);
tTotal = (tEnd.tv_sec - tStart.tv_sec);
tTotal += (tEnd.tv_nsec - tStart.tv_nsec)/1000000000.0;
if(tTotal<tBest)
tBest=tTotal;
} while(w++ < NUM_LOOP);
printf(" The best time: %lf sec in %d repetition for %dX%d matrix\n",tBest,w, N, M);
return 0;
}
В этом случае, я составил программу с другим флагом компилятора и выходом сборки внутреннего цикла выглядит следующим образом:
: Лучшее время: 0,000024 сек в 406490 повторении для 128x128 матрица
movss xmm1, DWORD PTR A[rcx+rax]
addss xmm1, DWORD PTR B[rcx+rax]
movss DWORD PTR C[rcx+rax], xmm1
gcc -O2 -mavx
: лучшее время: 0,000009 сек в 1000001 повторения для 128x128 матрицы
vmovss xmm1, DWORD PTR A[rcx+rax]
vaddss xmm1, xmm1, DWORD PTR B[rcx+rax]
vmovss DWORD PTR C[rcx+rax], xmm1
AVX версия gcc -O2 -mavx
:
__m256 vec256;
for(i=0;i<N;i++){
for(j=0;j<M;j+=8){
vec256 = _mm256_add_ps(_mm256_load_ps(&A[i+1][j]) , _mm256_load_ps(&B[i+1][j]));
_mm256_store_ps(&C[i+1][j], vec256);
}
}
SSE версия gcc -O2 -sse4.2
::
__m128 vec128;
for(i=0;i<N;i++){
for(j=0;j<M;j+=4){
vec128= _mm_add_ps(_mm_load_ps(&A[i][j]) , _mm_load_ps(&B[i][j]));
_mm_store_ps(&C[i][j], vec128);
}
}
В скалярной программе убыстрение -mavx
над msse4.2
является 2.7x. Я знаю, что avx
улучшил ISA эффективно, и, возможно, из-за этих улучшений. Но когда я реализовал программу в intrinsics для AVX
и SSE
, ускорение является фактором 3x. Вопрос в том, что сканер AVX в 2,7 раза быстрее, чем SSE, когда я векторизовал его, скорость выше 3x (размер матрицы составляет 128x128 для этого вопроса). Имеет ли смысл при использовании AVX и SSE в режиме скалярного режима, ускорение 2.7x. но векторный метод должен быть лучше, потому что я обрабатываю восемь элементов в AVX по сравнению с четырьмя элементами в SSE. Все программы имеют менее 4,5% промахов в кэше, как сообщалось perf stat
.
использованием gcc -O2
, linux mint
, skylake
UPDATE: Вкратце, Скалярное-AVX является 2.7x быстрее, чем Скалярное-SSE, но AVX-256 только 3 раза быстрее, чем SSE-128, пока она векторизации. Я думаю, это может быть из-за конвейерной обработки. в скалярном я имею 3 vec-ALU
, который может не использоваться в векторизованном режиме. Я мог бы сравнивать яблоки с апельсинами вместо яблок с яблоками, и это может означать, что я не могу понять причину.
Чтобы ответить на вопрос заголовка (я не могу полностью проанализировать последнюю часть тела): [GCC делает то, что вы сказали, только при компиляции на -O1] (https://godbolt.org/g/T4xnCU). Когда системы таргетинга с AVX [всегда рекомендуют использовать версии VEX устаревших инструкций SSE] (https://software.intel.com/sites/default/files/m/d/4/1/d/8 /11MC12_Avoiding_2BAVX-SSE_2BTransition_2BPenalties_2Brh_2Bfinal.pdf). –
@MargaretBloom, no 'gcc -O2' Я добавил к вопросу. таргетинг в порядке, но я сравниваю чистые 'AVX' и' SSE', а не AVX-256 с AVX-128. – Martin
@MargaretBloom, векторизация разрешена параметром '-ftree-loop-vectorize', который активируется' -O3', но не '-O2'. Это будет даже векторизовано с помощью '-O1 -ftree-loop-vectorize' –