Liczba punktów dwóch wektorów zmiennoprzecinkowych o pojedynczej precyzji daje różne wyniki w jądrze CUDA niż na hoście

Podczas debugowania niektórych kodów CUDA porównywałem je z odpowiednimi kodami CPUprintf stwierdzenia i zauważyłem, że w niektórych przypadkach moje wyniki były różne; niekoniecznie były błędne na obu platformach, ponieważ znajdowały się w błędach zaokrąglania zmiennoprzecinkowego, ale wciąż jestem zainteresowany wiedzą, co powoduje tę różnicę.

Udało mi się śledzić ten problem, uzyskując różne wyniki produktów dot. Zarówno w kodzie CUDA, jak i w kodzie hosta mam wektory a i b typufloat4. Następnie na każdej platformie obliczam produkt dot i wypisuję wynik, używając tego kodu:

printf("a: %.24f\t%.24f\t%.24f\t%.24f\n",a.x,a.y,a.z,a.w);
printf("b: %.24f\t%.24f\t%.24f\t%.24f\n",b.x,b.y,b.z,b.w);
float dot_product = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w;
printf("a dot b: %.24f\n",dot_product);

a wynikowy wydruk dla CPU to:

a: 0.999629139900207519531250   -0.024383276700973510742188 -0.012127066962420940399170 0.013238593004643917083740
b: -0.001840781536884605884552  0.033134069293737411499023  0.988499701023101806640625  1.000000000000000000000000
a dot b: -0.001397025771439075469971

a dla jądra CUDA:

a: 0.999629139900207519531250   -0.024383276700973510742188 -0.012127066962420940399170 0.013238593004643917083740
b: -0.001840781536884605884552  0.033134069293737411499023  0.988499701023101806640625  1.000000000000000000000000
a dot b: -0.001397024840116500854492

Jak widać, wartości a i b wydają się być bitowo równoważne na obu platformach, ale wynik dokładnie tego samego kodu różni się nieznacznie. Rozumiem, że mnożenie zmiennoprzecinkowe jest dobrze zdefiniowane zgodnie ze standardem IEEE 754 i jest niezależne od sprzętu. Mam jednak dwie hipotezy, dlaczego nie widzę takich samych wyników:

Optymalizacja kompilatora polega na ponownym porządkowaniu mnożeń i odbywa się w innej kolejności na GPU / CPU, co daje różne wyniki.Jądro CUDA używa połączonego operatora multi-add (FMA), jak opisano whttp://developer.download.nvidia.com/assets/cuda/files/NVIDIA-CUDA-Floating-Point.pdf. W tym przypadku wyniki CUDA powinny być nieco dokładniejsze.

questionAnswers(1)

yourAnswerToTheQuestion