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 に答える