如何使用 avx 指令将 float 向量转换为 short int?

How can I convert a vector of float to short int using avx instructions?

基本上,我如何使用 AVX2 内在函数编写与此等效的内容?我们这里假设 result_in_float__m256 类型,而 resultshort int*short int[8] 类型。

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

我知道可以使用 __m256i _mm256_cvtps_epi32(__m256 m1) 内部函数将浮点数转换为 32 位整数,但不知道如何将这些 32 位整数进一步转换为 16 位整数。我不仅想要那个,还想要将这些值(以 16 位整数的形式)存储到内存中,我想使用矢量指令来完成所有这些操作。

在互联网上搜索后,我发现了一个名为 _mm256_mask_storeu_epi16 的内在函数,但我不确定这是否能解决问题,因为我找不到它的用法示例。

_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