web-dev-qa-db-ja.com

順序付き/順序なしの比較とはどういう意味ですか?

SSE演算子を見る

CMPORDPS - ordered compare packed singles
CMPUNORDPS - unordered compare packed singles

順序付きおよび順序なしとはどういう意味ですか? x86命令セットで同等の命令を探しましたが、順序付けされていないようです(FUCOM)。

35
Dan

順序付き比較は、どちらのオペランドもNaNでないかどうかをチェックします。逆に、順序なし比較は、いずれかのオペランドがNaNであるかどうかをチェックします。

このページには、これに関する詳細情報が記載されています。

ここでの考え方は、NaNとの比較は不確定であるということです。 (結果を決定できません)したがって、順序付き/順序なしの比較では、これが当てはまる(または当てはまらない)かどうかがチェックされます。

double a = 0.;
double b = 0.;

__m128d x = _mm_set1_pd(a / b);     //  NaN
__m128d y = _mm_set1_pd(1.0);       //  1.0
__m128d z = _mm_set1_pd(1.0);       //  1.0

__m128d c0 = _mm_cmpord_pd(x,y);    //  NaN vs. 1.0
__m128d c1 = _mm_cmpunord_pd(x,y);  //  NaN vs. 1.0
__m128d c2 = _mm_cmpord_pd(y,z);    //  1.0 vs. 1.0
__m128d c3 = _mm_cmpunord_pd(y,z);  //  1.0 vs. 1.0
__m128d c4 = _mm_cmpord_pd(x,x);    //  NaN vs. NaN
__m128d c5 = _mm_cmpunord_pd(x,x);  //  NaN vs. NaN

cout << _mm_castpd_si128(c0).m128i_i64[0] << endl;
cout << _mm_castpd_si128(c1).m128i_i64[0] << endl;
cout << _mm_castpd_si128(c2).m128i_i64[0] << endl;
cout << _mm_castpd_si128(c3).m128i_i64[0] << endl;
cout << _mm_castpd_si128(c4).m128i_i64[0] << endl;
cout << _mm_castpd_si128(c5).m128i_i64[0] << endl;

結果:

0
-1
-1
0
0
-1
  • NaN1.0の順序付き比較falseを与えます。
  • NaN1.0の順序付けられていない比較trueを与えます。
  • 1.01.0の順序付き比較trueを与えます。
  • 1.01.0の順序なしの比較falseを与えます。
  • NaNNanの順序付き比較falseを与えます。
  • NaNNaNの順序付けられていない比較trueを与えます。
36
Mysticial

このIntelガイド: http://intel80386.com/simd/mmx2-doc.html には、かなり単純な2つの例が含まれています。

CMPORDPSは順序付けられた並列スカラーを比較します

オペコードサイクル命令0FC2 .. 07 2(3)CMPORDPS xmm reg、xmm reg/mem128

CMPORDPS op1、op2

op1には4つの単精度32ビット浮動小数点値が含まれていますop2には4つの単精度32ビット浮動小数点値が含まれています

op1[0] = (op1[0] != NaN) && (op2[0] != NaN)
op1[1] = (op1[1] != NaN) && (op2[1] != NaN)
op1[2] = (op1[2] != NaN) && (op2[2] != NaN)
op1[3] = (op1[3] != NaN) && (op2[3] != NaN)

TRUE  = 0xFFFFFFFF
FALSE = 0x00000000

CMPUNORDPSは順序付けられていない並列スカラーを比較します

オペコードサイクル命令0FC2 .. 03 2(3)CMPUNORDPS xmm reg、xmm reg/mem128

CMPUNORDPS op1、op2

op1には4つの単精度32ビット浮動小数点値が含まれていますop2には4つの単精度32ビット浮動小数点値が含まれています

op1[0] = (op1[0] == NaN) || (op2[0] == NaN)
op1[1] = (op1[1] == NaN) || (op2[1] == NaN)
op1[2] = (op1[2] == NaN) || (op2[2] == NaN)
op1[3] = (op1[3] == NaN) || (op2[3] == NaN)

TRUE  = 0xFFFFFFFF
FALSE = 0x00000000

違いは、[〜#〜]と[〜#〜](順序付き)と[〜#〜]です。または[〜#〜](順序なし)。

7
AusCBloke

TL:DR:順序なしは、2つのFP値が持つことができる関係です。 FUCOMの「順序なし」は、比較結果が順序付けされていない場合にFP例外が発生しないことを意味しますが、FCOMは発生します。これは、OQとOSのcmpps述語の違いと同じです。


ORDとUNORDは、cmppd/cmpps/cmpss/cmpsd insns (の完全なテーブルの述語の2つの選択肢です。アルファベット順で最初のcmppdエントリ) 。そのhtml抽出には読み取り可能なテーブル形式がありますが、Intelの公式のPDFオリジナルの方がやや優れています。 (リンクについては、 x86 タグwikiを参照してください)。

2つの浮動小数点どちらもNaNでない場合、オペランドは相互に順序付けられます。どちらかがNaNの場合、順序付けされていません。つまり、ordered = (x>y) | (x==y) | (x<y);。そうです、浮動小数点では、これらのことのどれも真実ではない可能性があります。浮動小数点の狂気の詳細については、 ブルース・ドーソンの優れた一連の記事を参照してください。

cmppsは、2つのスカラーを比較してフラグを設定する代わりに、述語を受け取り、結果のベクトルを生成します。これにより、事後に必要な述語を確認できます。したがって、チェックできるすべてのものに対して特定の述語が必要です。


同等のスカラーはcomiss/ucomissであり、FP比較結果(x87比較命令のように機能します(この最後のセクションを参照)からZF/PF/CFを設定します。答え)、しかしXMM regsの低い要素について)。

順序付けされていないことを確認するには、PFを確認してください。比較が順序付けられている場合は、他のフラグを調べて、オペランドが大きい、等しい、または小さい( )かどうかを確認できます。たとえば、jae上記または等しい )。


COMISS命令 は、ソースオペランドがQNaNまたはSNaNのいずれかである場合に、SIMD浮動小数点無効操作例外(#I)を通知するという点でUCOMISS命令とは異なります。 UCOMISS命令は、ソースオペランドがSNaNの場合にのみ、無効な数値例外を通知します。

通常、FP例外はマスクされるため、実際にプログラムが中断されることはありません。後で確認できるMXCSRのビットを設定するだけです。

これは述語のO/UQ対O/USフレーバーと同じですcmpps/vcmppsの場合。 cmp[ps][sd]命令のAVXバージョンでは、述語の選択肢が拡張されているため、それらを追跡するための命名規則が必要でした。

O対Uは、オペランドが順序付けられていないときに述語が真であるかどうかを示します。

Q vs. Sは、いずれかのオペランドがQuietNaNの場合に#Iが発生するかどうかを示します。 #どちらかのオペランドがSignaling NaNの場合、常に発生しますが、それらは「自然に発生する」ものではありません。自分でビットパターンを作成するだけで、他の操作からの出力としてそれらを取得することはありません(たとえば、後で問題を確実に検出するために、関数からのエラー戻り値として)。


X87に相当するものは、fcomまたはfucomを使用してFPUステータスを設定しますWord-> fstsw ax-> sahf、またはできれば fucomi は、EFLAGSをcomissのように直接設定します。

U /非Uの区別は、x87命令でもcomiss/ucomissの場合と同じです。

5
Peter Cordes