1

我对 SSE 舍入有一个小问题。该代码是不言自明的,我试图在 293.05694580 中获得 0.0001 的计数,包括一些舍入(例如,5.21 中有 52 个 0.1)...

#include <xmmintrin.h> 
#include <emmintrin.h> 

int main(void)
{
    float val       = (float) 293.05694580;
    float tickSize  = (float)   0.0001;

    __m128 _val     = _mm_set_ps1( val );
    __m128 _shift   = _mm_set_ps1( 1 / tickSize );

    /* 293.0569480 * 10000 should be 2930569.480 */
    __m128 _mul     = _mm_mul_ps(_val, _shift);

    /* Rounding 2930569.480 should get 2930569, but returns 2930570 instead. Why? */
    __m128i _ticks  = _mm_cvtps_epi32( _mul );
}

最后,如何恢复 _ticks 中结果的顺序?非常感谢,丹尼尔

4

3 回答 3

1

检查中间结果,不要假设它

检查/设置 sse 舍入模式

计数使用整数

于 2012-10-14T09:03:00.323 回答
1

如果有人关心,最终的代码是

inline void QTickCalcer::tickCountsFromDoubleArray(
        const double * src, int * dest, const unsigned int elemCount) const 
{
/*  src and dest need to be align_malloced              */
__m128i * r  = (__m128i*)dest;

__m128i r1;
__m128i r2;
__m128i rTot;

__m128d * d1 = (__m128d*) & src[0];
__m128d * d2 = (__m128d*) & src[2];

__m128d tmp1;
__m128d tmp2;

for ( register unsigned int i = 0; i < elemCount/4; i++ )
{
    tmp1    = _mm_mul_pd( *d1,  this->_dshiftor);           
    tmp2    = _mm_mul_pd( *d2,  this->_dshiftor);           

    /*  Interleave - http://msdn.microsoft.com/en-us/library/c8c5hx3b(v=vs.71).aspx                 */      
    r1  = _mm_cvtpd_epi32 ( tmp1 );
    r2  = _mm_cvtpd_epi32 ( tmp2 );
    rTot = _mm_unpacklo_epi32 ( r1, r2 );

    /*  Shuffle to match the ordering in src - http://software.intel.com/en-us/forums/topic/309988  */
    *r = _mm_shuffle_epi32( rTot, _MM_SHUFFLE(3,1,2,0));

    d1 += 2;
    d2 += 2;
    r++;
}
};

感谢所有的评论。

于 2012-10-14T18:38:03.843 回答
0

对于性能和精度,也许您可​​以:

  • 仅在精度异常处理程序中使用双精度(取消屏蔽精度异常)
  • 如果要求是“需要 X 位数的美分”,您可以将大笔资金放入双数组,将小笔资金放入浮点数组。在此之前从 X 计算你拆分它的数字
于 2012-10-14T13:43:35.470 回答