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

Posted

技术标签:

【中文标题】如何使用 avx 指令将 float 向量转换为 short int?【英文标题】:How can I convert a vector of float to short int using avx instructions? 【发布时间】:2016-12-19 17:42:54 【问题描述】:

基本上,我怎样才能用 AVX2 内在函数编写等效的内容?我们在这里假设result_in_float 的类型为__m256,而result 的类型为short 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 的内在函数,但我不确定这是否能解决问题,因为我找不到它的用法示例。

【问题讨论】:

我同时使用 C 和 C++。这些内在函数可以从它们中的任何一个中调用。所以,这就是原因。 将 vpshufb 与适当的字节选择一起使用,然后将值从高 128 位通道降低到低位的任何 shuffle。 如果它们饱和而不是在溢出时换行是否可以(从 int 到 short,即不是在 float 到 int 步骤中)? 在我的程序中,我认为这些浮点值总是在短值的范围内。所以,是的,这不是问题。 你是用gcc还是g++编译的? 【参考方案1】:

_mm256_cvtps_epi32 是很好的第一步,转换为 short 的打包向量有点烦人,需要跨切片 shuffle(所以它不在依赖链中很好)。

由于可以假定值在正确的范围内(根据注释),我们可以使用 _mm256_packs_epi32 而不是 _mm256_shuffle_epi8 进行转换,无论哪种方式它都是端口 5 上的 1 周期指令,但使用_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

【讨论】:

你先生,真是个天才:)!我测试了你的代码,它成功了!一次更正。应该是 _m256i 和 _m128i,而不是 __mm256i 或 __mm128i。我使用的确切代码如下。 __m256i tmp = _mm256_cvtps_epi32(result_in_float); tmp = _mm256_packs_epi32(tmp, _mm256_setzero_si256()); tmp = _mm256_permute4x64_epi64(tmp, 0xD8); 对,单m那里,我改一下 @pythonic 和 harold:对于单个向量,您不需要归零临时(并且只需要 AVX1):_mm256_cvtps_epi32,然后是 _mm256_extractf128_si256 和作为输入到 128 位 _mm_packs_epi32 的转换. (我不确定 256b VCVTPS2DQ ymm 是否在 AVX1 中,但确实如此。)

以上是关于如何使用 avx 指令将 float 向量转换为 short int?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 AVX2 中将 32 位无符号整数转换为 16 位无符号整数?

使用 AVX2 高效计算 std::complex<float> 向量的绝对值

AVX指令集是什么?(Advanced Vector Extensions 高级向量扩展)

AVX指令集是什么?(Advanced Vector Extensions 高级向量扩展)

AVX/SSE 将浮点符号掩码转换为 __m128i

最快的步幅 2 聚集