Я пытаюсь визуализировать ускорение включения AVX2 и AVX512
#include <stdio.h>
#include <stdlib.h>
#include <immintrin.h>
#include <omp.h>
#include <time.h>
int main()
{
long i, N = 160000000;
int * A = (int *)aligned_alloc(sizeof(__m256), sizeof(int) * N);
int * B = (int *)aligned_alloc(sizeof(__m256), sizeof(int) * N);
int * C = (int *)aligned_alloc(sizeof(__m256), sizeof(int) * N);
int * E = (int *)aligned_alloc(sizeof(__m512), sizeof(int) * N);
int * F = (int *)aligned_alloc(sizeof(__m512), sizeof(int) * N);
int * G = (int *)aligned_alloc(sizeof(__m512), sizeof(int) * N);
srand(time(0));
for(i=0;i<N;i++)
{
A[i] = rand();
B[i] = rand();
E[i] = rand();
F[i] = rand();
}
double time = omp_get_wtime();
for(i=0;i<N;i++)
{
C[i] = A[i] + B[i];
}
time = omp_get_wtime() - time;
printf("General Time taken %lf\n", time);
__m256i A_256_VEC, B_256_VEC, C_256_VEC;
time = omp_get_wtime();
for(i=0;i<N;i+=8)
{
A_256_VEC = _mm256_load_si256((__m256i *)&A[i]);
B_256_VEC = _mm256_load_si256((__m256i *)&B[i]);
C_256_VEC = _mm256_add_epi32(A_256_VEC, B_256_VEC);
_mm256_store_si256((__m256i *)&C[i],C_256_VEC);
}
time = omp_get_wtime() - time;
printf("AVX2 Time taken %lf\n", time);
free(A);
free(B);
free(C);
__m512i A_512_VEC, B_512_VEC, C_512_VEC;
time = omp_get_wtime();
for(i=0;i<N;i+=16)
{
A_512_VEC = _mm512_load_si512((__m512i *)&E[i]);
B_512_VEC = _mm512_load_si512((__m512i *)&F[i]);
C_512_VEC = _mm512_add_epi32(A_512_VEC, B_512_VEC);
_mm512_store_si512((__m512i *)&G[i],C_512_VEC);
}
time = omp_get_wtime() - time;
printf("AVX512 Time taken %lf\n", time);
for(i=0;i<N;i++)
{
if(G[i] != E[i] + F[i])
{
printf("Not Matched !!!\n");
break;
}
}
free(E);
free(F);
free(G);
return 1;
}
Итак, код распределяется в три этапа. Три массива присутствуют. Это просто добавление массива. Сначала мы выполняем это с использованием общего l oop, затем с помощью AVX2, а затем с помощью AVX 512. Я использую процессор Intel Xeon 6130.
Код скомпилирован с помощью команды
gcc -o test.o test.c -mavx512f -fopenmp -mavx2
Вывод:
General Time taken 0.532550
AVX2 Time taken 0.175549
AVX512 Time taken 0.264475
Теперь ускорение видно в случае общих реализаций l oop и intrinsi c. Но время увеличивается с AVX2 до AVX512, что не должно быть теоретически.
Я проверил отдельные операции загрузки, добавления, сохранения. Операция сохранения AVX512 требует максимального времени.
Просто для того, чтобы проверить, удаляю ли я операцию сохранения из обоих сегментов кода, результирующие моменты времени:
General Time taken 0.530248
AVX2 Time taken 0.115234
AVX512 Time taken 0.107062
Может Кто-нибудь пролил некоторый свет на такое поведение или это ожидается?
********* ОБНОВЛЕНИЕ 1 *********
После компиляции с -O3 -march = собственные расширения, новые тайминги:
General Time taken 0.014887
AVX2 Time taken 0.008072
AVX512 Time taken 0.014630
Это со всеми инструкциями загрузки, добавления, сохранения.
********* ОБНОВЛЕНИЕ 2 ** *******
Тест 1:
Общие l oop был изменен следующим образом,
for(i=0;i<N;i++)
{
//C[i] = A[i] + B[i];
//G[i] = E[i] + F[i];
}
Выход есть,
General Time taken 0.000003
AVX2 Time taken 0.014877
AVX512 Time taken 0.014334
Поэтому в обоих случаях происходит сбой страницы
Тест 2:
Общие l oop был изменен
for(i=0;i<N;i++)
{
C[i] = A[i] + B[i];
G[i] = E[i] + F[i];
}
Итак, кэширование выполняется в обоих случаях.
Вывод:
General Time taken 0.029703
AVX2 Time taken 0.008500
AVX512 Time taken 0.008560
Тест 3:
Пустой внешний l oop добавлен во все сценарии ios и из N уменьшен до 160000 .
for(j=0;j<N;j++)
{
for(i=0;i<N;i+= /* 1 or 8 or 16 */)
{
// Code
}
}
Теперь вывод равен
General Time taken 6.969532
AVX2 Time taken 0.871133
AVX512 Time taken 0.447317