0

このエラーは実際にはすべてのマシンで表示されるわけではありませんが、私の場合は以下のコードを実行して出力を得ました (値に注意して-1.#IND00ください)?

values int:: 4 2
shifts:: 4 2
result: : 64 32
input 1 HADDPD:: 10.000000 -1.#IND00
input 2 HADDPD:: 13.000000 10.000000
result of HADDPD:: -1.#IND00 23.000000

コメントアウトしたら

__m64 PSLLDm64_IN = _mm_set_pi32(2,4);
    __m64 PSLLDm64_C = _mm_set_pi32(2,4);//could this be the culprit?
    __m64 PSLLDm64_r  =  PSLLD(PSLLDm64_IN, PSLLDm64_C);

    print_2_32_bit_int("values int:" , PSLLDm64_IN);
    print_2_32_bit_int("shifts:", PSLLDm64_C);
    print_2_32_bit_int("result: ", PSLLDm64_r);

私は...

input 1 HADDPD:: 10.000000 100.000000
input 2 HADDPD:: 13.000000 10.000000
result of HADDPD:: 110.000000 23.000000

32行目のどこ__m64 PSLLDm64_C = _mm_set_pi32(2,4);が台無しになるのでしょうか?

完全なコードを次に示します ( -msse3 -mmmxg++ を使用して実行されます)。ただし、すべてのヘッダーが実際に必要なわけではありません。

#include <xmmintrin.h>
#include <emmintrin.h>
#include <pmmintrin.h>
#include <stdio.h>
#include <stdint.h>
#include <iostream>

void print_2_64_bit_doubles(const char * label, __m128d m64_r)
{
    double *val = (double *) &m64_r;
    printf("%s: %f %f\n",
       label, val[0], val[1]);
}
void print_2_32_bit_int(const char * label, __m64 m32_r)
{
    int *val = (int *) &m32_r;
    printf("%s: %d %d\n",
       label, val[0], val[1]);
}
__m128d HADDPD(__m128d __X, __m128d __Y)
{
    return _mm_hadd_pd ( __X, __Y);
}
__m64 PSLLD(__m64 __m, __m64 __count)
{
    return _mm_sll_pi32 ( __m,  __count);
}
int main()
{
    //PSLLD-------------------------------------------------------------------
    __m64 PSLLDm64_IN = _mm_set_pi32(2,4);
    __m64 PSLLDm64_C = _mm_set_pi32(2,4);
    __m64 PSLLDm64_r  =  PSLLD(PSLLDm64_IN, PSLLDm64_C);

    print_2_32_bit_int("values int:" , PSLLDm64_IN);
    print_2_32_bit_int("shifts:", PSLLDm64_C);
    print_2_32_bit_int("result: ", PSLLDm64_r);
    //HADDPD------------------------------------------------------------------
    double C1 = 10;
    double D = C1*C1;
    double x = 10;
    double y = 13;

    __m128d HADDPDm64_1 = _mm_set_pd(D,C1);
    __m128d HADDPDm64_2 = _mm_set_pd(x,y);
    __m128d HADDPDm64_r = HADDPD( HADDPDm64_1, HADDPDm64_2);

    print_2_64_bit_doubles("input 1 HADDPD:", HADDPDm64_1);
    print_2_64_bit_doubles("input 2 HADDPD:", HADDPDm64_2);
    print_2_64_bit_doubles("result of HADDPD:", HADDPDm64_r);

    return 0;
}

EDIT : これは、g++ 4.4.1 でコンパイルされた新しいシフト命令で更新されたコードです。-msse -msse2 -msse3 -msse4

#include <xmmintrin.h>
#include <emmintrin.h>
#include <pmmintrin.h>
#include <mmintrin.h>
#include <stdio.h>
#include <stdint.h>


void print_2_64_bit_doubles(const char * label, __m128d m64_r)
{
    double *val = (double *) &m64_r;
    printf("%s: %f %f\n",
       label, val[0], val[1]);
}
void print_2_32_bit_int(const char * label, __m64 m32_r)
{
    int *val = (int *) &m32_r;
    printf("%s: %d %d\n",
       label, val[0], val[1]);
}
void print_1_32_bit_int(const char * label, __m64 m32_r)
{
    int *val = (int *) &m32_r;
    printf("%s: %d \n",
       label, val[0]);
}
__m128d HADDPD(__m128d __X, __m128d __Y)
{
    return _mm_hadd_pd ( __X, __Y);
}
__m64 PSLLD(__m64 __m, __m64 __count)
{
    return _mm_sll_pi32 ( __m,  __count);
}
int main()
{
    //PSLLD-------------------------------------------------------------------
    __m64 PSLLDm64_IN = _mm_set_pi32(2,4);
    long long __i = 2;
    __m64 PSLLDm64_C = (__m64)(__i);
    __m64 PSLLDm64_r  =  PSLLD(PSLLDm64_IN, PSLLDm64_C);
    _mm_empty();

    print_2_32_bit_int("values int:" , PSLLDm64_IN);
    print_1_32_bit_int("shifts:", PSLLDm64_C);
    print_2_32_bit_int("result: ", PSLLDm64_r);
    //HADDPD------------------------------------------------------------------
    double C1 = 10;
    double D = C1*C1;
    double x = 10;
    double y = 13;

    __m128d HADDPDm64_1 = _mm_set_pd(D,C1);
    __m128d HADDPDm64_2 = _mm_set_pd(x,y);
    __m128d HADDPDm64_r = HADDPD( HADDPDm64_1, HADDPDm64_2);

    print_2_64_bit_doubles("input 1 HADDPD:", HADDPDm64_1);
    print_2_64_bit_doubles("input 2 HADDPD:", HADDPDm64_2);
    print_2_64_bit_doubles("result of HADDPD:", HADDPDm64_r);

    return 0;
}

そして出力

values int:: 4 2
shifts:: 2
result: : 16 8
input 1 HADDPD:: 10.000000 -1.#IND00
input 2 HADDPD:: 13.000000 10.000000
result of HADDPD:: -1.#IND00 23.000000
4

1 に答える 1

1

http://www.drangon.org/mingw/の gcc および g++ 4.8.1 の Windows x64 ポートでテストすると、両方とも期待どおりの結果が得られます。アーカイブを解凍し、パスを mingw64\bin に設定するだけです。-msse4 などのコンパイラ オプションを使用して、ハードウェアがこれらの命令をサポートしていることをコンパイラに伝えます。

2013/07/05: 最初のコメントが不完全で申し訳ありません。また、上記の回答はコメントであり、回答ではありません。

Microsoft VS2010 では、cygwin から報告されたのと同じ誤った結果が得られます。その原因は、Microsoft デバッガーで簡単に見つけることができます。実際、コンパイル警告も問題を指摘しています。

warning C4730: 'main' : mixing _m64 and floating point expressions may result in incorrect code

報告された問題は、コンパイラが MMX と x87 FPU 命令の混合を生成するときに発生します。コンパイラは _m64 データに MMX レジスタを使用し、コンパイラは浮動小数点データ型 double に x87 FPU レジスタまたは新しい XMM または YMM レジスタを使用します。Intel が MMX を設計したとき、MMX レジスタ データに x87 レジスタを再利用するという決定が下されました。これは、MMX の使用をサポートするためにオペレーティング システムを更新する必要がないようにするためです。この決定の欠点は、MMX と x87 FPU 命令を混在させることができないことです。FPU と MMX 命令が誤って混在するのを防ぐために、Intel 製の MMX レジスタのロードは、対応する FPU レジスタのタグ ワード ビットを SNAN (シグナリング NAN) としてマークします。これが、予期しない出力につながるものです。コンパイラとビルド オプションの組み合わせによっては、このコードが正しく機能する場合があります。このコードが機能する場合に考えられる理由: 1) コンパイラは倍精度データに XMM または YMM レジスタを使用します。2) コンパイラはすべての x87 FPU 値をメモリに保持し、MMX 命令全体で FPU レジスタの状態に依存しません。要するに、MMX 命令と x87 FPU 命令が混在するコードをコンパイラが生成できるようになる状況を回避するのは、コーダー次第です。「関数 'print_2_32_bit_int' には EMMS 命令がありません」や「_m64 と浮動小数点式を混在させると、コードが正しくない可能性があります」などの警告を真剣に受け止めてください。実行可能なアプローチの 1 つは、_m64 データ型を完全に回避することです。要するに、MMX 命令と x87 FPU 命令が混在するコードをコンパイラが生成できるようになる状況を回避するのは、コーダー次第です。「関数 'print_2_32_bit_int' には EMMS 命令がありません」や「_m64 と浮動小数点式を混在させると、コードが正しくない可能性があります」などの警告を真剣に受け止めてください。実行可能なアプローチの 1 つは、_m64 データ型を完全に回避することです。要するに、MMX 命令と x87 FPU 命令が混在するコードをコンパイラが生成できるようになる状況を回避するのは、コーダー次第です。「関数 'print_2_32_bit_int' には EMMS 命令がありません」や「_m64 と浮動小数点式を混在させると、コードが正しくない可能性があります」などの警告を真剣に受け止めてください。実行可能なアプローチの 1 つは、_m64 データ型を完全に回避することです。

_mm_empty() の使用に関する Paul R の提案は、Microsoft VS2010 の問題を解決します。「double C1 = 10」の前に追加すると、問題はなくなりました。_mm_empty については、 http: //software.intel.com/sites/products/documentation/studio/composer/en-us/2011Update/compiler_c/intref_cls/common/intref_mmx_emms_usage.htm で説明されています。

他の質問については、コマンド ラインを gcc のみに使用しており、IDE は使用していません。_mm_empty() を追加するか、MMX と x87 FPU コードを混在させない場合、古いバージョンの gcc は正常に動作するはずです。

于 2013-07-04T15:17:30.287 に答える