Я пытаюсь сравнить производительность между скалярным кодом и кодом Intel AVX (SIMD), компилируемым с флагом -O3.
После запуска программ я вижу огромную разницу в производительности между ними.
Я использую 4 функции:
* Сумма
* Подсчет
* Мин
* Макс
Для всех скалярных выполнений время, которое я получаю, составляет 0,000001 с (среднее значение, 11 выполнений в каждом случае), в отличие от 0,043958 с для AVXSum, AVXMin, AVXMax (регистр подсчета дает одинаковый быстрый результат для обоих исполнений).
Я попытался глубже взглянуть на ассемблерный код скалярных функций. К своему удивлению я обнаружил, что gcc генерирует один и тот же код сборки для ScalarSum, ScalarCount, ScalarMin, ScalarMax.
Поскольку возникает зависимость RAW, я ожидал некоторой задержки во времени выполнения. При более внимательном рассмотрении числа пропусков в филиалах они довольно близки (т.е. 772 548 846 промахов в ветвях и среднее значение 0,044221сек для AVXMin, 772 656 995 промахов в среднем 0,000000 сек для ScalarMin).
Входные данные (отношение) - это массив из 1024
1024 элементов (rel_size).
В основной функции я инициализирую и рандомизирую входной массив (rand () - пользовательский и реализован алгоритм Фишера Йейтса). Я считаю, что вычисление времени компиляции не происходит, но я не могу объяснить такую большую разницу в производительности.
Ниже, я прикрепляю сгенерированный ассемблерный код для скалярного случая (то же самое для всех случаев, как я уже упоминал). Кроме того, я прилагаю коды AVXMin и ScalarMin C.
.file "scalarMin.c"
.section .text.unlikely,"ax",@progbits
.LCOLDB1:
.text
.LHOTB1:
.p2align 4,,15
.globl scalar_min
.type scalar_min, @function
scalar_min:
.LFB38:
.cfi_startproc
pushq %rbx
.cfi_def_cfa_offset 16
.cfi_offset 3, -16
call clock
movq %rax, %rbx
call clock
pxor %xmm0, %xmm0
subq %rbx, %rax
popq %rbx
.cfi_def_cfa_offset 8
cvtsi2sdq %rax, %xmm0
divsd .LC0(%rip), %xmm0
ret
.cfi_endproc
.LFE38:
.size scalar_min, .-scalar_min
.section .text.unlikely
.LCOLDE1:
.text
.LHOTE1:
.section .rodata.cst8,"aM",@progbits,8
.align 8
.LC0:
.long 0
.long 1093567616
.ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609"
.section .note.GNU-stack,"",@progbits
Функция Intel AVX Min:
double avx_min(int32_t** relation, int32_t rel_size){
clock_t t;
__m256i input_buffer;
__m256i min = _mm256_set_epi32(INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX);
t = clock();
for(int i = 0 ; i < rel_size ; i += 8){
input_buffer = _mm256_stream_load_si256((__m256i*)&(*relation)[i]);
min = _mm256_min_epi32(min, input_buffer);
}
t = clock() - t;
return ((double) t) /CLOCKS_PER_SEC;
}
Функция Scalar Min:
double scalar_min(int32_t** relation, int32_t rel_size){
clock_t t;
int32_t min = INT32_MAX;
t = clock();
for(int i = 0 ; i < rel_size ; i++){
if( (*relation)[i] < min ){
min = (*relation)[i];
}
}
t = clock() - t;
return ((double) t) /CLOCKS_PER_SEC;
}
*1024* Заранее спасибо за помощь:)