Intel AVX работает медленнее, чем скалярный код - PullRequest
0 голосов
/ 03 сентября 2018

Я пытаюсь сравнить производительность между скалярным кодом и кодом 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* Заранее спасибо за помощь:)
...