Самый быстрый способ установить значение __m256 для всех ОДИН бит
Как я могу установить значение 1 для всех битов в значении __m256? Используете встроенные функции AVX или AVX2?
Чтобы получить все нули, вы можете использовать _mm256_setzero_si256()
,
Чтобы получить все, я в настоящее время использую _mm256_set1_epi64x(-1)
, но я подозреваю, что это медленнее, чем случай с нулем. Есть ли здесь доступ к памяти или переключение Salar/SSE/AVX?
И я не могу найти простую побитовую операцию НЕ в AVX? Если бы это было доступно, я мог бы просто использовать setzero, а затем вектор NOT.
1 ответ
См. Также Установите все биты в регистре ЦПУ на 1, что эффективно для регистров AVX, AVX2 и AVX512 zmm и k (маска).
Вы, очевидно, даже не смотрели на вывод asm, что тривиально сделать:
#include <immintrin.h>
__m256i all_ones(void) { return _mm256_set1_epi64x(-1); }
vpcmpeqd ymm0, ymm0, ymm0
ret
с gcc6.1 и clang3.8.
Первая версия gcc для поддержки avx2 знала достаточно, чтобы выполнить эту оптимизацию. С -mavx -mno-avx2
GCC загружает вектор всех единиц из памяти. Clang делает 128-битные монеты и использует vinsertf128
,
Как описано в разделе векторов руководства по оптимизации сборки Agner Fog, генерация констант на лету - это дешево. Для генерации всех единиц все еще требуется модуль исполнения вектора (в отличие от_mm_setzero
), но это лучше, чем любая возможная последовательность из двух инструкций, и обычно лучше, чем загрузка. Смотрите также x86 tag wiki.
Компиляторы не любят генерировать более сложные константы на лету, даже те, которые могут быть сгенерированы из всех с простым сдвигом. Даже если вы попробуете, написав __m128i float_signbit_mask = _mm_srli_epi32(_mm_set1_epi16(-1), 1)
Компиляторы обычно делают постоянное распространение и помещают вектор в память. Это позволяет им складывать его в операнд памяти при последующем использовании в тех случаях, когда нет цикла, из которого можно вывести константу.
И я не могу найти простую побитовую операцию НЕ в AVX?
Вы делаете это путем XORing со всеми.