Istnieje wiele wyzwań technicznych, które sprawiają, że dokładna powtarzalność wyników obliczeniowych jest bardzo trudna do osiągnięcia.
Na poziomie oprogramowania zmiany w kodzie lub dowolnej bibliotece używanej przez kod mogą oczywiście powodować różne wyniki. Byłbyś zaskoczony liczbą bibliotek pomocniczych, które mogą ostatecznie zostać połączone w typowy kod naukowy.
Na niższym poziomie rekompilacja dowolnego kodu lub dowolnej biblioteki używanej przez kod przy użyciu nowego kompilatora lub przy różnych włączonych optymalizacjach kompilatora może również powodować problemy. Jednym z powodów jest to, że różne operacje w kodzie mogą być wykonywane w innej kolejności podczas rekompilacji kodu. Ponieważ dodawanie zmiennoprzecinkowe nie jest asocjacyjne (a + b) + c <> a + (b + c), może to dać różne wyniki.
OK, co z tego, jeśli zachowamy całe środowisko oprogramowania (system operacyjny, biblioteki i skompilowany kod) poprzez (np.) Wypalenie go na rozruchowej płycie CD-ROM, która uruchomi kod. Czy możemy być pewni, że uzyskamy takie same wyniki, jeśli uruchomimy ten kod na innym komputerze?
Co zaskakujące, niektóre kody w rzeczywistości zmieniają kolejność obliczeń w oparciu o aspekty konkretnego modelu procesora, na którym są uruchomione. Na przykład zoptymalizowane biblioteki algebry liniowej zwykle dzielą mnożenia macierzy, aby pracować na blokach, które zmieszczą się w pamięci podręcznej. Gdy Intel wypuszcza nowy mikroprocesor z większą pamięcią podręczną, kod może dynamicznie dostosowywać rozmiar bloku, co skutkuje arytmetyką, która jest wykonywana w innej kolejności i daje różne wyniki. Inne kody dynamicznie dostosowują kolejność obliczeń na podstawie ilości dostępnej pamięci - jeśli uruchomisz kod na komputerze z większą ilością pamięci, co może spowodować, że arytmetyka zostanie wykonana w innej kolejności, a tym samym da inne wyniki.
Sprawy stają się niezwykle skomplikowane, gdy dodaje się wielowątkowy kod, ponieważ dokładna historia wykonania różnych wątków jest często niedeterministyczna, co może ponownie powodować wykonywanie operacji arytmetycznych w innej kolejności od jednego uruchomienia do następnego.
W praktyce najbardziej, na co naprawdę można liczyć, są wyniki, które są podobne w zależności od maszyny, aż do tolerancji dokładności zastosowanych algorytmów. np. jeśli mam problem ze znalezieniem roota i używam bisekcji, aby uzyskać root w granicach + -1.0e-10, to powinienem być szczęśliwy, dopóki różne maszyny generują odpowiedzi, które są zgodne w ramach tej tolerancji.