首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >存储4个具有SSE本质的16位整数

存储4个具有SSE本质的16位整数
EN

Stack Overflow用户
提问于 2014-02-26 12:51:50
回答 3查看 3.5K关注 0票数 2

我乘和轮四个32位浮点数,然后把它转换成四个带有SSE本质的16位整数。我想将四个整数结果存储到一个数组中。使用浮标很容易:_mm_store_ps(float_ptr, m128value)。但是,我还没有找到任何使用16位(__m64)整数来完成这一操作的指令。

代码语言:javascript
复制
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
}

任何帮助都将不胜感激。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-02-26 15:53:24

就我个人而言,我会避免使用MMX。此外,我将使用显式存储而不是隐式存储,后者通常只在某些编译器上工作。下面的代码可以在MSVC2012和SSE4.1中找到。

请注意,fptr需要16字节对齐。这不是一个问题,如果您在64位模式编译,但在32位模式,您应该确保它是对齐的。

代码语言:javascript
复制
#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版本的程序集输出

代码语言:javascript
复制
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版本的程序集输出

代码语言:javascript
复制
mulps   (%rdi), %xmm0
cvttps2dq   %xmm0, %xmm0
packssdw    %xmm0, %xmm0
movq    %xmm0, (%rsi)
ret
票数 3
EN

Stack Overflow用户

发布于 2014-02-26 13:24:03

对于__m64类型,只需适当地转换目标指针:

代码语言:javascript
复制
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一样;因此,您不需要执行存储的本质。

票数 2
EN

Stack Overflow用户

发布于 2014-02-26 14:28:21

我认为将其转移到普通64位寄存器(long long将对Linux LLP64和LP64都适用)并自己复制它是安全的。

从我在xmmintrin.h上读到的资料来看,gcc将很好地处理从__m64long long的演员阵容。当然,您可以使用_mm_cvtsi64_si64x

代码语言:javascript
复制
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与一个联合,以使它看起来更好,但我想,这将是在未定义的行为。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22041999

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档