В моем предыдущий пост Я объясняю, что я начинаю с AVX, чтобы ускорить мой код (обратите внимание, что, хотя есть общие части, этот пост относится к AVX512, а предыдущий — к AVX2, которые, насколько я знаю, немного отличаются и нуждаются в разных флагах компиляции) , После экспериментов с AVX2 я решил попробовать AVX512 и изменил свою функцию AVX2:
void getDataAVX2(u_char* data, size_t cols, std::vector<double>& info)
{
__m256d dividend = _mm256_set_pd(1 / 64.0, 1 / 64.0, 1 / 64.0, 1 / 64.0);
info.resize(cols);
__m256d result;
for (size_t i = 0; i < cols / 4; i++)
{
__m256d divisor = _mm256_set_pd((double(data[4 * i + 3 + cols] << 8) + double(data[4 * i + 2 * cols + 3])),
(double(data[4 * i + 2 + cols] << 8) + double(data[4 * i + 2 * cols + 2])),
(double(data[4 * i + 1 + cols] << 8) + double(data[4 * i + 2 * cols + 1])),
(double(data[4 * i + cols] << 8) + double(data[4 * i + 2 * cols])));
result = _mm256_sqrt_pd(_mm256_mul_pd(divisor, dividend));
info[size_t(4 * i)] = result[0];
info[size_t(4 * i + 1)] = result[1];
info[size_t(4 * i + 2)] = result[2];
info[size_t(4 * i + 3)] = result[3];
}
}
для того, что я думаю, должно быть его эквивалентом:
void getDataAVX512(u_char* data, size_t cols, std::vector<double>& info)
{
__m512d dividend = _mm512_set_pd(1 / 64.0, 1 / 64.0, 1 / 64.0, 1 / 64.0, 1 / 64.0, 1 / 64.0, 1 / 64.0, 1 / 64.0);
info.resize(cols);
__m512d result;
for (size_t i = 0; i < cols / 8; i++)
{
__m512d divisor = _mm512_set_pd((double(data[4 * i + 7 + cols] << 8) + double(data[4 * i + 2 * cols + 7])),
(double(data[4 * i + 6 + cols] << 8) + double(data[4 * i + 2 * cols + 6])),
(double(data[4 * i + 5 + cols] << 8) + double(data[4 * i + 2 * cols + 5])),
(double(data[4 * i + 4 + cols] << 8) + double(data[4 * i + 2 * cols + 4])),
(double(data[4 * i + 3 + cols] << 8) + double(data[4 * i + 2 * cols + 3])),
(double(data[4 * i + 2 + cols] << 8) + double(data[4 * i + 2 * cols + 2])),
(double(data[4 * i + 1 + cols] << 8) + double(data[4 * i + 2 * cols + 1])),
(double(data[4 * i + cols] << 8) + double(data[4 * i + 2 * cols])));
result = _mm512_sqrt_pd(_mm512_mul_pd(divisor, dividend));
info[size_t(4 * i)] = result[0];
info[size_t(4 * i + 1)] = result[1];
info[size_t(4 * i + 2)] = result[2];
info[size_t(4 * i + 3)] = result[3];
info[size_t(4 * i + 4)] = result[4];
info[size_t(4 * i + 5)] = result[5];
info[size_t(4 * i + 6)] = result[6];
info[size_t(4 * i + 7)] = result[7];
}
}
который в не AVX форме:
void getData(u_char* data, size_t cols, std::vector<double>& info)
{
info.resize(cols);
for (size_t i = 0; i < cols; i++)
{
info[i] = sqrt((double(data[cols + i] << 8) + double(data[2 * cols + i])) / 64.0);
;
}
}
После компиляции кода я получаю следующую ошибку:
Illegal instruction (core dumped)
К моему удивлению, эта ошибка возникает в вызове sqrt
в getData
функция. Если я удалю sqrt
вызовите, то ошибка появляется еще дальше, в __m512d divisor = _mm512_set_pd((d....
, Есть идеи о том, что происходит?
Вот это полный пример.
Большое спасибо.
Я собираю с c++
(7.3.0) со следующими параметрами -std=c++17 -Wall -Wextra -O3 -fno-tree-vectorize -mavx512f
, Я проверил как объяснил Вот и мой процессор (Intel® Core® TM i7-4710HQ CPU @ 2,50 ГГц) поддерживает AVX2. Должен ли в списке быть AVX-512 для поддержки этого?
Я не думаю, что инструкции AVX-512 поддерживаются в вашей системе (CPU). Принимая официальная документация во внимание; в нем упоминается только AVX-2. более новый процессор будет указывать AVX-512 совершенно нормально. Оба могут быть найдены в разделе «Расширения набора инструкций».
Других решений пока нет …