Сдвиги AVX2 (16 бит)

Существуют ли встроенные инструкции для выполнения операций сдвига вправо и влево для (16-разрядных) целочисленных элементов в AVX2?

Как следующие примеры:

[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] --> [16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

а также

[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] --> [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]

где _mm_srli_si128(H,14) а также _mm_slli_si128(H,2) хорошо работают на 16-битных элементах SSE3. Я спрашиваю, потому что производительность (время работы) имеет решающее значение для меня.

1 ответ

К сожалению, в AVX2 таких инструкций нет. Все инструкции AVX2 расширены до 256 бит SSE2 с учетом совместимости при использовании в 128 бит SSE2.

Если вам известно число 16-разрядных целых чисел, которые нужно сдвинуть во время компиляции, вы можете использовать комбинацию перестановок и сдвигов. Например, вы можете логически разбить значение на 64-битные порции, выполнить перестановку и сдвиги этих блоков, а затем объединить их.

Вот как я делаю это в моем коде

static __m256i m256_srl16_1(__m256i i) {
    // suppose i is [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

    //[4, 3, 2, 1,      16, 15, 14, 13,   12, 11, 10, 9,   8, 7, 6, 5]
    __m256i srl64_q = _mm256_permute4x64_epi64(i, _MM_SHUFFLE(0,3,2,1));

    //[ 1, 0, 0, 0      13, 0, 0, 0       9, 0, 0, 0       5, 0, 0, 0]
    __m256i srl64_m = _mm256_slli_epi64(srl64_q, 3*16);
    //[ 0, 16, 15, 14,  0, 12, 11, 10,    0, 8, 7, 6,      0, 4, 3, 2]
    __m256i srl16_z = _mm256_srli_epi64(i, 1*16);

    __m256i srl64 = _mm256_and_si256(srl64_m, _mm256_set_epi64x(0, ~0, ~0, ~0));
    __m256i r = _mm256_or_si256(srl64, srl16_z);

    return r;
}

Если вам нужно перейти на более чем 64 бита, вам нужна дополнительная перестановка исходного значения и маскировка ненужных битов

Другие вопросы по тегам