BLAS実装は、まったく同じ結果をもたらすことが保証されていますか?


17

2つの異なるBLAS実装を考えると、まったく同じ浮動小数点計算を行い、同じ結果を返すと期待できますか?または1つのようにスカラー積を計算することは、例えば、起こることができる そしてような一つ そうおそらくIEEE浮動小数点に異なる結果を与えます算術?

バツ1y1+バツ2y2+バツ3y3+バツ4y4
バツ1y1+バツ2y2+バツ3y3+バツ4y4

1
このスレッドにはBLASの品質に関する苦情がいくつかあります。ページでCBLASを検索してください。それは...だけでなく、彼らは同じ結果が得られていないことを示唆している、すべてではなく、それらのいずれかのタスクのために正確に十分あるでしょう
サボルチ

回答:


15

いいえ、それは保証されていません。最適化なしでNETLIB BLASを使用している場合、結果が同じであることはほぼ間違いありません。しかし、BLASとLAPACKを実際に使用する場合は、高度に最適化された並列BLASを使用します。並列化により、CPUのベクトルレジスタ内でのみ並列に動作する場合でも、単一の項が評価される順序が変わり、合計の順序も変わります。結果は同じではないというIEEE標準の欠落している連想プロパティの形式に従います。まさにあなたが言及したことが起こる可能性があります。

NETLIB BLASでは、スカラー積は、係数5で展開されたforループのみです。

DO I = MP1,N,5
          DTEMP = DTEMP + DX(I)*DY(I) + DX(I+1)*DY(I+1) +
     $            DX(I+2)*DY(I+2) + DX(I+3)*DY(I+3) + DX(I+4)*DY(I+4)
END DO

各乗算がすぐにDTEMPに追加されるか、5つのコンポーネントすべてが最初に合計されてからDTEMPに追加されるかは、コンパイラ次第です。OpenBLASでは、アーキテクチャに応じて、より複雑なカーネルが使用されます。

 __asm__  __volatile__
    (
    "vxorpd     %%ymm4, %%ymm4, %%ymm4               \n\t"
    "vxorpd     %%ymm5, %%ymm5, %%ymm5               \n\t"
    "vxorpd     %%ymm6, %%ymm6, %%ymm6               \n\t"
    "vxorpd     %%ymm7, %%ymm7, %%ymm7               \n\t"

    ".align 16                           \n\t"
    "1:                          \n\t"
        "vmovups                  (%2,%0,8), %%ymm12         \n\t"  // 2 * x
        "vmovups                32(%2,%0,8), %%ymm13         \n\t"  // 2 * x
        "vmovups                64(%2,%0,8), %%ymm14         \n\t"  // 2 * x
        "vmovups                96(%2,%0,8), %%ymm15         \n\t"  // 2 * x

    "vmulpd      (%3,%0,8), %%ymm12, %%ymm12 \n\t"  // 2 * y
    "vmulpd    32(%3,%0,8), %%ymm13, %%ymm13 \n\t"  // 2 * y
    "vmulpd    64(%3,%0,8), %%ymm14, %%ymm14 \n\t"  // 2 * y
    "vmulpd    96(%3,%0,8), %%ymm15, %%ymm15 \n\t"  // 2 * y

    "vaddpd      %%ymm4 , %%ymm12, %%ymm4 \n\t"  // 2 * y
    "vaddpd      %%ymm5 , %%ymm13, %%ymm5 \n\t"  // 2 * y
    "vaddpd      %%ymm6 , %%ymm14, %%ymm6 \n\t"  // 2 * y
    "vaddpd      %%ymm7 , %%ymm15, %%ymm7 \n\t"  // 2 * y

    "addq       $16 , %0	  	     \n\t"
	"subq	        $16 , %1            \n\t"      
    "jnz        1b                   \n\t"
...

スカラー積を長さ4の小さなスカラー積に分割し、それらを合計します。

ATLAS、MKL、ESSLなどの他の典型的なBLAS実装を使用する場合...各BLAS実装は異なる最適化を使用して高速コードを取得するため、この問題は同じままです。しかし、私が知る限り、本当に間違った結果を引き起こすには人工的な例が必要です。

BLASライブラリが同じ結果(ビット単位で同じ)を返す必要がある場合、次のような再現可能なBLASライブラリを使用する必要があります。


8

短い答え

2つのBLAS実装がまったく同じ順序で操作を実行するように記述されており、ライブラリが同じコンパイラフラグと同じコンパイラを使用してコンパイルされた場合、同じ結果が得られます。浮動小数点演算はランダムではないため、2つの同一の実装では同一の結果が得られます。

ただし、パフォーマンスのためにこの動作を壊す可能性のあるさまざまなものがあります...

長い答え

IEEEは順序も指定します各操作の動作方法に加えて、これらの操作が実行ます。ただし、「-ffast-math」などのオプションを使用してBLAS実装をコンパイルすると、コンパイラーは正確な算術では正しいがIEEE浮動小数点では「正しくない」変換を実行できます。正規の例は、指摘したように、浮動小数点加算の非結合性です。より積極的な最適化設定では、結合性が想定され、プロセッサは操作を並べ替えることにより、可能な限り並行して処理を行います。

a+bc


3
「浮動小数点演算はランダムではありません」。...これは明示的に記述する必要があることを悲しいですが、あまりにも多くの人々がそれだと思うようです
パイプ

さて、予測不可能でランダムに見えるのはかなり似ており、多くのイントロプログラミングクラスは「浮動小数点数を等しいかどうか比較しない」と言います。
タイラーオルセン

@TylerOlsenこれは質問には関係ありません。これらのクラスがそのようなことを言う理由ではありませんが、IIRCでは、平等を当てにできないコンパイラバグのクラスがありました。例えば、if (x == 0) assert(x == 0) かもしれない時々ビューの特定のポイントからランダムとして良いようである、失敗します。
キリル

@Kirill申し訳ありませんが、私は多くの人が浮動小数点の仕組みを実際に学ばないということを指摘しようとしていました。歴史的な点については、それは一種の恐ろしいことですが、ゲームに入る前に解決されたに違いありません。
タイラーオルセン

@TylerOlsenおっと、私の例は間違っています。if (x != 0) assert(x != 0)拡張精度の計算のため、である必要があります。
キリル

4

一般的に、いいえ。結合性は別として、コンパイラフラグ(SIMD命令の有効化、Fused Multiply Addの使用など)またはハードウェア(拡張精度が使用されているかどうかなど)の選択によって異なる結果が生じる場合があります。

再現可能なBLAS実装を取得するための努力があります。詳細については、ReproBLASおよびExBLASを参照してください。


1
インテルのMKL BLASの最新バージョンの条件付き数値再現性(CNR)機能も参照してください。このレベルの再現性を得ると、通常、計算が遅くなり、大幅に遅くなる可能性があることに注意してください!
ブライアンボーチャーズ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.