我乘和轮四个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
}任何帮助都将不胜感激。
发布于 2014-02-26 15:53:24
就我个人而言,我会避免使用MMX。此外,我将使用显式存储而不是隐式存储,后者通常只在某些编译器上工作。下面的代码可以在MSVC2012和SSE4.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发布于 2014-02-26 13:24:03
对于__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一样;因此,您不需要执行存储的本质。
发布于 2014-02-26 14:28:21
我认为将其转移到普通64位寄存器(long long将对Linux LLP64和LP64都适用)并自己复制它是安全的。
从我在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;您可以键入pune与一个联合,以使它看起来更好,但我想,这将是在未定义的行为。
https://stackoverflow.com/questions/22041999
复制相似问题