No, questo non è garantito. Se si utilizza un BLAS NETLIB senza ottimizzazioni, è quasi vero che i risultati sono gli stessi. Ma per qualsiasi uso pratico di BLAS e LAPACK si usa un BLAS altamente ottimizzato e parallelo. La parallelizzazione provoca, anche se funziona solo in parallelo all'interno dei registri vettoriali di una CPU, che cambia l'ordine di valutazione dei singoli termini e cambia anche l'ordine della somma. Ora segue la proprietà associativa mancante nello standard IEEE che i risultati non sono gli stessi. Quindi può succedere esattamente ciò che hai menzionato.
Nel NETAS BLAS il prodotto scalare è solo un ciclo for srotolato da un fattore 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
e spetta al compilatore se ogni moltiplicazione viene aggiunta immediatamente a DTEMP o se tutti e 5 i componenti vengono sommati per primi e poi aggiunti a DTEMP. In OpenBLAS dipende dall'architettura un kernel più complicato:
__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"
...
che divide il prodotto scalare in piccoli prodotti scalari di lunghezza 4 e li riassume.
Utilizzando le altre implementazioni BLAS tipiche come ATLAS, MKL, ESSL, ... questo problema rimane lo stesso perché ogni implementazione BLAS utilizza ottimizzazioni diverse per ottenere codice veloce. Ma per quanto ne so uno ha bisogno di un esempio artificiale per causare risultati davvero errati.
Se è necessario che la libreria BLAS ritorni per gli stessi risultati (per quanto riguarda gli stessi bit), è necessario utilizzare una libreria BLAS riproducibile come: