Согласно немного тредлинг хаки сайт, операция
unsigned int a; // value to merge in non-masked bits
unsigned int b; // value to merge in masked bits
unsigned int mask; // 1 where bits from b should be selected; 0 where from a.
unsigned int r; // result of (a & ~mask) | (b & mask) goes here
r = a ^ ((a ^ b) & mask);
позволяет объединять две битовые последовательности a
а также b
по маске. Я размышлял:
В программировании SSE / AVX выборочное копирование из одного вектора в другой на основе маски называется смесь. SSE4.1 добавил инструкции, такие как PBLENDVB xmm1, xmm2/m128, <XMM0>
, где неявный операнд XMM0 управляет тем, какие байты src перезаписывают соответствующие байты в dst. (Без SSE4.1 вы обычно и И НЕ маска на два вектора и ИЛИ, что вместе; трюк xor имеет меньший параллелизм на уровне команд и, вероятно, требует как минимум столько же инструкций MOV для копирования регистров.)
Есть также инструкция немедленного смешивания, pblendw
, где маска является 8-битной немедленной вместо регистра. И есть 32-битные и 64-битные немедленные смеси (blendps
, blendpd
, vpblendd
) и переменные смеси (blendvps
, blendvpd
).
IDK, если другие наборы инструкций SIMD (NEON, AltiVec, независимо от того, что MIPS называет их и т. Д.) Также называют их «смешивания» или нет.
SSE / AVX (или целочисленные инструкции x86) не предоставляют ничего лучше, чем обычный побитовый XOR / AND для выполнения побитовое (вместо поэлементного) смешивается до AVX512F.
AVX512F может сделать побитовую версию этого (или любую другую побитовую троичную функцию) с одним vpternlogd
или же vpternlogq
инструкция. (Единственное различие между размерами элементов d и q заключается в том, что вы используете регистр маски для маскирования слиянием или нулевой маскировки места назначения, но это не помешало Intel создавать отдельные встроенные функции даже для случая без маски:
__m512i _mm512_ternarylogic_epi32 (__m512i a, __m512i b, __m512i c, int imm8)
и эквивалентная версия … _ epi64.
imm8
Непосредственный байт — это таблица истинности. Каждый бит адресата определяется независимо от соответствующих битов a, b и c, используя их в качестве 3-битного индекса в таблице истинности. то есть как imm8[a:b:c]
,
С AVX512 будет интересно поиграть, когда он в конечном итоге появится в обычных процессорах для настольных ПК / ноутбуков, но это, вероятно, еще через пару лет.
Других решений пока нет …