Объединить битовые последовательности a и b в соответствии с маской

Согласно немного тредлинг хаки сайт, операция

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 по маске. Я размышлял:

  1. Имеет ли эта операция конкретное / обычное имя?
  2. Существовала ли конкретная инструкция по сборке для этой операции в некотором наборе команд?

2

Решение

В программировании 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 будет интересно поиграть, когда он в конечном итоге появится в обычных процессорах для настольных ПК / ноутбуков, но это, вероятно, еще через пару лет.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]