2016-12-19 23 views
3

В принципе, как я могу записать эквивалент этого с помощью встроенных AVX2? Мы предполагаем, что result_in_float имеет тип __m256, а result имеет тип short int* или short int[8].Как преобразовать вектор float в short int с помощью команд avx?

for(i = 0; i < 8; i++) 
    result[i] = (short int)result_in_float[i]; 

Я знаю, что поплавки могут быть преобразованы в 32-битных целых чисел, используя __m256i _mm256_cvtps_epi32(__m256 m1) внутренней, но не имеют ни малейшего представления о том, как преобразовать эти 32 битные целые дальше 16-битных целых чисел. И я не хочу этого, но также хранить эти значения (в виде 16-битных целых чисел) в памяти, и я хочу сделать это с помощью векторных инструкций.

Поиск по интернету, я нашел внутреннее имя _mm256_mask_storeu_epi16, но я не уверен, что это будет трюк, поскольку я не мог найти пример его использования.

+0

Я использую как C и C++. И эти внутренности могут быть вызваны из любого из них. Вот почему. – pythonic

+0

Используйте vpshufb с соответствующими байтовыми выделениями, затем любая тасовка, которая приносит значение вниз от верхней 128-битной полосы до нижней. –

+0

Все в порядке, если они насыщаются вместо обертывания при переполнении (от int до короткого, а не от float до int step)? – harold

ответ

4

_mm256_cvtps_epi32 - хороший первый шаг, преобразование в упакованный вектор шорт немного раздражает, требуя перетаскивания в поперечном разрезе (так что хорошо, что он не находится в цепочке зависимостей здесь).

Поскольку значения можно считать в нужном диапазоне (в соответствии с комментарием), мы можем использовать _mm256_packs_epi32 вместо _mm256_shuffle_epi8, чтобы выполнить преобразование, так или иначе, это инструкция 1-цикл на порте 5, но с использованием _mm256_packs_epi32 Избегает из-за чего нужно достать маску для тасования.

Итак, чтобы положить его вместе (не тестировалось)

__m256i tmp = _mm256_cvtps_epi32(result_in_float); 
tmp = _mm256_packs_epi32(tmp, _mm256_setzero_si256()); 
tmp = _mm256_permute4x64_epi64(tmp, 0xD8); 
__m128i res = _mm256_castsi256_si128(tmp); 
// _mm_store_si128 that 

Последний шаг (литая) свободен, он просто меняет тип.

Если у вас есть два вектора поплавков для преобразования, вы можете повторно использовать большинство инструкций, например: (не тестировалось либо)

__m256i tmp1 = _mm256_cvtps_epi32(result_in_float1); 
__m256i tmp2 = _mm256_cvtps_epi32(result_in_float2); 
tmp1 = _mm256_packs_epi32(tmp1, tmp2); 
tmp1 = _mm256_permute4x64_epi64(tmp1, 0xD8); 
// _mm256_store_si256 this 
+0

Ты, сэр, гениальный :)! Я проверил ваш код, и он сработал! Тем не менее. Вместо __mm256i или __mm128i это должно быть _m256i и _m128i. Точный код, который я использовал, следующий. __m256i tmp = _mm256_cvtps_epi32 (result_in_float); \t tmp = _mm256_packs_epi32 (tmp, _mm256_setzero_si256()); \t tmp = _mm256_permute4x64_epi64 (tmp, 0xD8); – pythonic

+0

Правильно, один 'm' там, я изменю его – harold

+3

@pythonic и harold: для одного вектора вам не нужен обнуленный временный (и нужен только AVX1):' _mm256_cvtps_epi32', затем '_mm256_extractf128_si256' и в качестве входных данных в128 бит '_mm_packs_epi32'. (Я не был уверен, что 256b [VCVTPS2DQ ymm] (http://www.felixcloutier.com/x86/CVTPS2DQ.html) был в AVX1, но это так.) –