回答:
いいえ、それは保証されていません。最適化なしで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ライブラリを使用する必要があります。
短い答え
2つのBLAS実装がまったく同じ順序で操作を実行するように記述されており、ライブラリが同じコンパイラフラグと同じコンパイラを使用してコンパイルされた場合、同じ結果が得られます。浮動小数点演算はランダムではないため、2つの同一の実装では同一の結果が得られます。
ただし、パフォーマンスのためにこの動作を壊す可能性のあるさまざまなものがあります...
長い答え
IEEEは順序も指定します各操作の動作方法に加えて、これらの操作が実行ます。ただし、「-ffast-math」などのオプションを使用してBLAS実装をコンパイルすると、コンパイラーは正確な算術では正しいがIEEE浮動小数点では「正しくない」変換を実行できます。正規の例は、指摘したように、浮動小数点加算の非結合性です。より積極的な最適化設定では、結合性が想定され、プロセッサは操作を並べ替えることにより、可能な限り並行して処理を行います。
if (x == 0) assert(x == 0)
かもしれない時々ビューの特定のポイントからランダムとして良いようである、失敗します。
if (x != 0) assert(x != 0)
拡張精度の計算のため、である必要があります。
一般的に、いいえ。結合性は別として、コンパイラフラグ(SIMD命令の有効化、Fused Multiply Addの使用など)またはハードウェア(拡張精度が使用されているかどうかなど)の選択によって異なる結果が生じる場合があります。
再現可能なBLAS実装を取得するための努力があります。詳細については、ReproBLASおよびExBLASを参照してください。