Nie, to nie jest gwarantowane. Jeśli używasz NETLIB BLAS bez żadnych optymalizacji, to w większości przypadków prawdą jest, że wyniki są takie same. Ale do każdego praktycznego zastosowania BLAS i LAPACK stosuje się wysoce zoptymalizowany równoległy BLAS. Równoległość powoduje, nawet jeśli działa ona równolegle tylko w rejestrach wektorowych CPU, że zmienia się kolejność, w jakiej oceniane są poszczególne warunki, a także zmienia się kolejność sumowania. Teraz z brakującej właściwości asocjacyjnej w standardzie IEEE wynika, że wyniki nie są takie same. Może się zdarzyć dokładnie to, o czym wspomniałeś.
W NETLIB BLAS iloczyn skalarny jest tylko pętlą for rozwiniętą 5-krotnie:
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
i to od kompilatora zależy, czy każde zwielokrotnienie zostanie dodane do DTEMP natychmiast, czy wszystkie 5 składników zostanie najpierw zsumowane, a następnie dodane do DTEMP. W OpenBLAS jest zależne od architektury bardziej skomplikowane jądro:
__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"
...
który dzieli iloczyn skalarny na małe iloczyny skalarne o długości 4 i sumuje je.
Używając innych typowych implementacji BLAS, takich jak ATLAS, MKL, ESSL, ... ten problem pozostaje ten sam, ponieważ każda implementacja BLAS korzysta z różnych optymalizacji w celu uzyskania szybkiego kodu. Ale o ile mi wiadomo, potrzebny jest sztuczny przykład, aby spowodować naprawdę błędne wyniki.
Jeśli konieczne jest, aby biblioteka BLAS zwróciła te same wyniki (pod względem bitów to samo), należy użyć odtwarzalnej biblioteki BLAS, takiej jak: