Non, ce n'est pas garanti. Si vous utilisez un NETLIB BLAS sans aucune optimisation, il est généralement vrai que les résultats sont les mêmes. Mais pour toute utilisation pratique de BLAS et LAPACK, on utilise un BLAS parallèle hautement optimisé. La parallélisation provoque, même si elle ne fonctionne qu'en parallèle à l'intérieur des registres vectoriels d'un CPU, que l'ordre de façon dont les termes simples sont évalués change et que l'ordre de la sommation change également. Maintenant, il résulte de la propriété associative manquante dans la norme IEEE que les résultats ne sont pas les mêmes. Donc, exactement ce que vous avez mentionné peut arriver.
Dans le NETLIB BLAS, le produit scalaire n'est qu'une boucle for déroulée par un facteur 5:
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
et il appartient au compilateur si chaque multiplication est ajoutée à DTEMP immédiatement ou si les 5 composants sont additionnés en premier et ensuite ajoutés à DTEMP. Dans OpenBLAS, cela dépend de l'architecture d'un noyau plus compliqué:
__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"
...
qui divise le produit scalaire en petits produits scalaires de longueur 4 et les résume.
En utilisant les autres implémentations BLAS typiques comme ATLAS, MKL, ESSL, ... ce problème reste le même car chaque implémentation BLAS utilise différentes optimisations pour obtenir du code rapide. Mais pour autant que je sache, il faut un exemple artificiel pour provoquer des résultats vraiment défectueux.
S'il est nécessaire que la bibliothèque BLAS renvoie pour les mêmes résultats (au niveau du bit la même), il faut utiliser une bibliothèque BLAS reproductible telle que: