[英]Store four 16bit integers with SSE intrinsics
我将四个32位浮点数相乘并四舍五入,然后使用SSE内在函数将其转换为四个16位整数。 我想将四个整数结果存储到数组中。 使用浮点数很容易: _mm_store_ps(float_ptr, m128value)
。 但是我还没有找到使用16位(__m64)整数来执行此操作的指令。
void process(float *fptr, int16_t *sptr, __m128 factor)
{
__m128 a = _mm_load_ps(fptr);
__m128 b = _mm_mul_ps(a, factor);
__m128 c = _mm_round_ps(b, _MM_FROUND_TO_NEAREST_INT);
__m64 s =_mm_cvtps_pi16(c);
// now store the values to sptr
}
任何帮助,将不胜感激。
我个人将避免使用MMX。 另外,我将使用显式存储而不是隐式存储,后者通常仅在某些编译器上有效。 以下代码可在MSVC2012和SSE 4.1中找到。
请注意, fptr
必须为16字节对齐。 如果在64位模式下进行编译,这不是问题,但是在32位模式下,则应确保其对齐。
#include <stdio.h>
#include <stdint.h>
#include <smmintrin.h>
void process(float *fptr, int16_t *sptr, __m128 factor)
{
__m128 a = _mm_load_ps(fptr);
__m128 b = _mm_mul_ps(a, factor);
__m128i c = _mm_cvttps_epi32(b);
__m128i d = _mm_packs_epi32(c,c);
_mm_storel_epi64((__m128i*)sptr, d);
}
int main() {
float x[] = {1.0, 2.0, 3.0, 4.0};
int16_t y[4];
__m128 factor = _mm_set1_ps(3.14159f);
process(x, y, factor);
printf("%d %d %d %d\n", y[0], y[1], y[2], y[3]);
}
请注意, _mm_cvtps_pi16
不是简单的内在指令,《英特尔内在指令》说:“此内在指令会创建两个或更多指令的序列,并且可能比本机指令执行得差。请考虑此内在指令对性能的影响。”
这是使用MMX版本的程序集输出
mulps (%rdi), %xmm0
roundps $0, %xmm0, %xmm0
movaps %xmm0, %xmm1
cvtps2pi %xmm0, %mm0
movhlps %xmm0, %xmm1
cvtps2pi %xmm1, %mm1
packssdw %mm1, %mm0
movq %mm0, (%rsi)
ret
这是使用仅SSE版本的程序集输出
mulps (%rdi), %xmm0
cvttps2dq %xmm0, %xmm0
packssdw %xmm0, %xmm0
movq %xmm0, (%rsi)
ret
使用__m64
类型,您可以适当地__m64
目标指针:
void process(float *fptr, int16_t *sptr, __m128 factor)
{
__m128 a = _mm_load_ps(fptr);
__m128 b = _mm_mul_ps(a, factor);
__m128 c = _mm_round_ps(b, _MM_FROUND_TO_NEAREST_INT);
__m64 s =_mm_cvtps_pi16(c);
*((__m64 *) sptr) = s;
}
使用MMX指令的对齐存储和不对齐存储没有区别,就像SSE / AVX一样。 因此,您不需要内部函数即可执行存储。
我认为您可以安全地将其移至通用的64位寄存器( long long
对Linux LLP64和Windows LP64均适用)并自行复制。
从我在xmmintrin.h
阅读的内容xmmintrin.h
,gcc可以很好地处理从__m64
到很long long
。 可以肯定的是,您可以使用_mm_cvtsi64_si64x
。
short* f;
long long b = _mm_cvtsi64_si64x(s);
f[0] = b >> 48;
f[1] = b >> 32 & 0x0000FFFFLL;
f[2] = b >> 16 & 0x000000000FFFFLL;
f[3] = b & 0x000000000000FFFFLL;
您可以使用union键入pune以使其看起来更好,但我想这会属于未定义的行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.