Подсчет населения в AVX512

Я пытался использовать _mm256_popcnt_epi64 на машине, поддерживающей AVX512, и в коде, который ранее был оптимизирован для AVX2.

К сожалению, я столкнулся с проблемой, что функция не найдена. Однако соответствующий __m512i эквивалент найден. Функция __m256i устарела?


person Alex    schedule 18.05.2020    source источник


Ответы (1)


_mm512_popcnt_epi64 является частью AVX512-VPOPCNTDQ. 256-битные и 128-битные версии также требуют, чтобы AVX512VL использовал инструкции AVX512 со 128 или 256-битными векторами.

Все основные процессоры AVX512 имеют AVX512-VL. В процессорах Xeon Phi нет AVX512-VL.

Возможно, вы забыли включить необходимые параметры компилятора (например, GCC -march=native, чтобы включить все, что может делать машина, на которой вы компилируете), или вы компилируете для цели, у которой нет обеих функций. Если это так, то у компилятора не будет определения _m256_popcnt_epi64 как внутреннего, поэтому в C он примет свою и необъявленную функцию и вызовет ее. (Что, конечно, не будет найдено во время ссылки.) И / или он предупредит или выдаст ошибку (C или C ++) о том, что прототип не найден.

В настоящее время очень немногие процессоры имеют AVX512-VPOPCNTDQ (wikipedia AVX512 функция по сравнению с матрицей ЦП):

  • Knight's Mill (Xeon Phi последнего поколения): только AVX512-VPOPCNTDQ, без AVX512VL. Таким образом, для gcc -O3 -march=knm доступны только __m512i версии. Вам определенно следует использовать 512-битные векторы на Xeon Phi, если схема данных не работает идеально для 256 и потребует дополнительного перетасовки для 512-бит. Но будьте осторожны, это медленно для некоторых инструкций AVX / AVX2, у которых нет 512-битных версий, например, перемешивание с элементами меньше 32-битных. (Нет AVX512 BW)
  • Ice Lake / Tiger Lake: имеет как AVX512 VPOPCNTDQ, так и AVX512 VL, поэтому при компиляции для этой целевой микроархитектуры поддерживается _mm256_popcnt_epi64, например gcc -O3 -march=icelake-client. (Предполагая, что заголовки вашего компилятора верны).

Выбор между 256 или 512-битными векторами в Ice Lake - это компромисс, как и в Skylake-x: когда 512-битные векторные мопы находятся в полете, векторные ALU на порту 1 не используются. И максимальная тактовая частота турбо может быть снижена. Инструкции SIMD, снижающие частоту ЦП. Поэтому, если вы не получаете большого ускорения от более широких векторов (например, из-за узкого места в памяти или ваши циклы SIMD являются лишь крошечной частью более крупной программы), использование 512-битных векторов в одном цикле может снизить общую производительность.


Другие процессоры вообще не имеют аппаратной поддержки SIMD popcnt, и форма _mm512_popcnt_epi64 недоступна.

Даже если у вас есть только AVX2, а не AVX512 вообще, SIMD popcnt лучше скалярных popcnt над немаленькими массивами на современных процессорах с быстрым vpshufb (_mm256_shuffle_epi8). https://github.com/WojciechMula/sse-popcount/ имеет версии AVX2 и AVX512, которые используют vpternlogd для накопления Harley-Seal, чтобы уменьшить количество запросов SIMD LUT для поп-счета.

Также в разделе «Переполнение стека» Подсчет 1 бита (подсчет населения) для больших данных с использованием AVX-512 или AVX-2 показывает, что некоторый код скопирован из этого репо пару лет назад.

Если вам нужны подсчеты для отдельных элементов по отдельности, просто используйте стандартную распаковку для vpshufb и vpsadbw против нулевого вектора в hsum на 64-битные блоки qword.

Если вам нужно позиционное число (отдельная сумма для каждой битовой позиции), см. https://github.com/mklarqvist/positional-popcount.

person Peter Cordes    schedule 18.05.2020
comment
Отлично, большое спасибо! Я работал над Skylake, и руководство по встроенным функциям заставило меня подумать, что AVX512VL достаточно. - person Alex; 19.05.2020
comment
@Alex: Это не объясняет, что _mm512_popcnt_epi64 работает на вас. Это также должно быть ошибкой компилятора или ошибкой как недопустимой инструкцией, если вы используете параметры компилятора, которые позволяют ему компилироваться. Так что проверьте свои варианты сборки. - person Peter Cordes; 19.05.2020
comment
Мой код является частью более крупного проекта, и при компиляции у меня возникли ошибки приведения, когда я пытался выполнить popcnt на `__m256i '. Вот почему я подумал, что эта функция доступна. Постараюсь подробно проверить. - person Alex; 19.05.2020
comment
@Alex: Это заставило вас подумать, что версия __m512i доступна? Ok. Нет, это недоступно с -march=skylake-avx512. Я просто волновался, что что-то еще было совершенно не так с вашими параметрами сборки или тестовой настройкой, но неправильные предположения прекрасно это объясняют. - person Peter Cordes; 19.05.2020