1

そのため、SSE2 を使用してベクトルをフロアする関数を作成しましたが、特定の目的でのみ機能するように見えます。たとえば、バイリニア フィルタリング アルゴリズムでは正常に機能しますが、モジュロを実行するために使用すると、値がわずかにずれます。この関数は、切り捨てを使用して整数ベクトルへの変換を実行し、それを浮動小数点に戻すことによって機能します。フロア コードとモジュロ コードの両方を以下に示します。

inline __m128 floor_SIMD(const __m128 & a)
{
    __m128i int_val = _mm_cvttps_epi32(a);
    return _mm_cvtepi32_ps(int_val); 
}

inline __m128 mod_SIMD(const __m128 & x, const __m128 & y)
{
    return _mm_sub_ps(x, _mm_mul_ps(y, floor_SIMD(_mm_div_ps(x, y))));
}

モジュロからわずかに奇妙な値が得られる理由について、誰か説明があるでしょうか?

編集:たとえば、 mod_SIMD(_mm_set1_ps(63.6f), _mm_set1_ps(32.0f)) を使用すると、誤った回答が生成されますが、 mod_SIMD(_mm_set1_ps(23.6f), _mm_set1_ps(32.0f)) は正しい回答を生成します。フロア関数を効率の悪いコンポーネントごとのバージョンに置き換えると、正常に機能します。

4

1 に答える 1

3

私は自分の問題を解決しました。ここにいるすべての人のために、結果のコードを示します。切り捨ての問題を補正する元の値より大きい場合は、値から 1 を減算します。

inline __m128 floor_SIMD(const __m128 & a)
{
    static const __m128 one = _mm_set1_ps(1.0f);

    __m128 fval = _mm_cvtepi32_ps(_mm_cvttps_epi32(a));

    return _mm_sub_ps(fval, _mm_and_ps(_mm_cmplt_ps(a, fval), one));
}
于 2013-05-10T18:48:10.167 に答える