Я пытаюсь переписать функцию с использованием AVX2 и сталкиваюсь с проблемами

Оригинальная скалярная функция

static inline uint32 abc(uint32 bytes, int shift)
{
uint32 kMul= 0x1e35a7bd;
return (bytes * kMul) >> shift;

}

Эквивалентная функция AVX

 static inline uint32 abc(uint32 bytes, int shift)
{
uint32 kMul= 0x1e35a7bd;
__m256i a,b,c,resShift,shift_256i;
a=_mm256_set1_epi32(bytes);
b=_mm256_set1_epi32(kMul);
shift_256i=_mm256_set1_epi32(shift);
c=_mm256_mul_epi32(a,b);
resShift=_mm256_srlv_epi64(c,shift_256i);
// I am not sure what function to use to convert m256i variable into integer
}

Я не уверен, как конвертировать переменную m256i в целое число на последнем шаге. ResShift имеет значение m256i правого смещения, но мне нужно преобразовать его в целочисленную форму и вернуть из этой функции. Любая помощь?

2

Решение

Вы можете проконсультироваться Intel Intrinsics Guide. Вам явно нужны некоторые экстракт внутренне, но я не могу найти ни одного, чтобы сделать это за один шаг. Вот как это сделать в двух инструкциях:

__m128i lower = _mm256_extracti128_si256(resShift, 0);
return _mm_extract_epi32(lower, 0);

Обратите внимание, что в том, что вы делаете, нет никакого смысла. Вместо того, чтобы вычислять один результат для одного входа, вы дублируете этот вход восемь раз и решаете восемь одинаковых задач, чтобы получить восемь равных ответов. Таким образом, вы выполняете в восемь раз больше работы без необходимости. Также само дублирование (set1_ intrinsics) займет дополнительное время. Ваша подпрограмма AVX не будет работать быстрее, чем скалярная.

Постскриптум Кстати, вы должны использовать _mm256_srlv_epi32 вместо _mm256_srlv_epi64 для сдвига, потому что вы упаковали 32-битные данные в свои регистры.

2

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


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector