Обновить

Комментарии 7

В avx512 есть отдельная инструкция VPOPCNTDQ. Для 128 бит сумма двух popcnt r/m64 может достаточно быстро работать.

Сам AVX-512 сейчас не везде есть, но вообще это в большей степени для демонстрации концепта, я специально в качестве первичного примера брал операцию, которая итак есть.

Помимо полной поддержки AVX512 есть ещё поддержка на логическом уровне — формально инструкция поддерживается, но реально процессор выполняет её как две 256-битных. Я столкнулся с этим на своём CPU пока писал управление светодиодными лентами. CPU по документации вроде AVX512 поддерживает, но скорость от AVX2 по факту не отличается. Сначала я думал, что виноват C#, и по‑нормальному надо для таких задач использовать C++. Однако, раскопав документацию процессора поглубже, я понял, что регистры AVX512 вроде как есть, а вот обработчиков нет — вместо этого срабатывают AVX2 в два этапа. Полноценный AVX512 — это к ксеонам/тредрипперам/эпикам.

А ещё у AVX512 гораздо более удобный shuffle, который может переносить любые байты в любое место. У AVX256 насколько мне известно две половинки по 128 бит, которые между собой перемешивать не получится. Но могу ошибаться.

А ещё у AVX512 гораздо более удобный shuffle, который может переносить любые байты в любое место

Сколько не искал так и ни нашел ни одну инструкцию, которая умеет перемещать данные между двумя 64-битными компонентами, не то что 128. Например чтобы посчитать маску (1 << L) - 1 с L>64 пришлось

Вот так выкручиваться
  __m512i a = _mm512_maskz_set1_epi64((1ull << ((count >> 6))) - 1,
                                      std::numeric_limits<uint64_t>::max());
  __m512i b = _mm512_maskz_set1_epi64((1ull << ((count >> 6) + 1)) - 1,
                                      std::numeric_limits<uint64_t>::max());
  __m512i mask = _mm512_shldv_epi64(a, b, _mm512_set1_epi64(count % 64));

PSLLDQ (_mm_slli_si128) перемешает, но должно быть кратно 8

Да, это я что-то затупил, тот же шафл перемешивает внутри 128-битного блока. Но в целом проблема с примером, который я привёл, остается -- сделать сдвиг кратно 8 бит можно одной инструкцией, но произвольный почему-то нет, приходится извращаться.

Касательно исходного вопроса по произвольному перекладыванию: судя по всему в AVX-512 shuffle тоже не умеет перекладывать между 128-битными блоками, но это умеет делать семейство инструкций permute -- ожидаемо они работают чуть медленее.

У AVX256 насколько мне известно две половинки по 128 бит, которые между собой перемешивать не получится.

Я, когда перекладывал Game of Life на avx, столкнулся с этим. Инструкции битового сдвига не переносят биты между 128-битными блоками

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации