Оптимизировать извлечение 64-битного значения из регистра AVX2
Я пытаюсь извлечь 64 бит из регистра __m256i. Пример моей текущей функции извлечения:
byte 31 16 15 0
byte_result_vec 000D 000C 000B 000A 000H 000G 000F 000E
_mm256_packs_epi32 -> 0D0C 0B0A 0D0C 0B0A 0H0G 0F0E 0H0G 0F0E
_mm256_packus_epi16 -> DCBA DCBA DCBA DCBA HGFE HGFE HGFE HGFE
^^^^ ^^^^
_mm256_castsi256_si128 -> HGFE HGFE HGFE HGFE
_mm256_extracti128_si256 -> DCBA DCBA DCBA DCBA
_mm_cvtsi128_si32(byte_result_vec1) -> ABCD
_mm_cvtsi128_si32(byte_result_vec2) -> EFGH
Следующий код сдвигает 4x8 битов в позицию регистра 0-3 и затем извлекает 32 бита.
byte_result_vec = _mm256_packs_epi32(byte_result_vec, byte_result_vec);
byte_result_vec = _mm256_packus_epi16(byte_result_vec, byte_result_vec);
__m128i byte_result_vec1 = _mm256_castsi256_si128(byte_result_vec);
__m128i byte_result_vec2 = _mm256_extracti128_si256(byte_result_vec,1);
const int res1 = _mm_cvtsi128_si32(byte_result_vec1);
const int res2 = _mm_cvtsi128_si32(byte_result_vec2);
result_array[j] = res1;
result_array[j+1] = res2;
Код работает правильно, но медленно. Похоже, что копирование res1 и res2 в result_array занимает больше всего времени. Есть ли способ оптимизировать его?
1 ответ
Решение
Вероятно, этот вариант будет быстрее
/* byte_result_vec 000H 000G 000F 000E 000D 000C 000B 000A */
const __m256i shuffle_mask = _mm256_setr_epi8(0, 4, 8, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 4, 8, 12, -1, -1, -1, -1, -1, -1, -1, -1);
/* abcdefgh 0000 0000 HGFE 0000 0000 0000 0000 DCBA */
const __m256i abcdefgh = _mm256_shuffle_epi8(byte_result_vec, shuffle_mask);
/* abcd 0000 0000 0000 DCBA */
const __m128i abcd = _mm256_castsi256_si128(abcdefgh);
/* efgh 0000 0000 HGFE 0000 */
const __m128i efgh = _mm256_extracti128_si256(abcdefgh, 1);
_mm_storel_epi64((__m128i*)&result_array[j], _mm_or_si128(abcd, efgh));