SSE内在函数导致正常的float操作返回-1。#INV

时间:2012-01-29 10:42:29

标签: c++ sse intrinsics

我正在编写一个执行音频处理的SSE方法的问题。我在这里基于英特尔的论文实现了SSE随机函数:

http://software.intel.com/en-us/articles/fast-random-number-generator-on-the-intel-pentiumr-4-processor/

我还有一个使用SSE执行从Float到S16的转换的方法,转换操作非常简单如下:

unsigned int Float_S16LE(float *data, const unsigned int samples, uint8_t *dest)
{
  int16_t *dst = (int16_t*)dest;
  const __m128 mul = _mm_set_ps1((float)INT16_MAX);
   __m128 rand;
  const uint32_t even = count & ~0x3;
  for(uint32_t i = 0; i < even; i += 4, data += 4, dst += 4)
  {
    /* random round to dither */
    FloatRand4(-0.5f, 0.5f, NULL, &rand);

    __m128 rmul = _mm_add_ps(mul, rand);
    __m128 in = _mm_mul_ps(_mm_load_ps(data),rmul);
    __m64 con = _mm_cvtps_pi16(in);

    memcpy(dst, &con, sizeof(int16_t) * 4);
  }
}

FloatRand4的定义如下:

static inline void FloatRand4(const float min, const float max, float result[4], __m128 *sseresult = NULL)
{
  const float delta  = (max - min) / 2.0f;
  const float factor = delta / (float)INT32_MAX;
  ...
}

如果sseresult != NULL返回__m128结果且未使用result。 这在第一个循环上表现完美,但在下一个循环delta变为-1.#INF而不是1.0。如果我注释掉__m64 con = _mm_cvtps_pi16(in);行,问题就会消失。

我认为FPU正处于未知状态或其他状态。

2 个答案:

答案 0 :(得分:9)

混合SSE整数算术和(常规)浮点数学。可以产生奇怪的结果,因为它们都在相同的寄存器上运行。如果您使用:

_mm_empty()

FPU重置为正确状态。 Microsoft有Guidelines for When to Use EMMS

答案 1 :(得分:1)

  • _mm_load_ps不保证执行对齐加载。 float * data可以对齐到4个字节而不是16 _ =&gt; _mm_loadu_ps
  • memcpy可能会破坏使用SSE实现的优势,你应该使用__m64的存储命令,但在这里再次处理对齐。 如果不可能做一个未对齐的流或__m64的存储,我要么将它保存在_m128i中并使用_mm_maskmoveu_si128进行掩码写入,要么手工存储这8个字节。

http://msdn.microsoft.com/en-us/library/bytwczae.aspx