Podczas poszukiwania jakiegoś numpy rzeczy, natknąłem pytanie omawiając zaokrąglania dokładność numpy.dot():NumPy zmiennoprzecinkowych zaokrąglania błędy
Numpy: Difference between dot(a,b) and (a*b).sum()
Ponieważ zdarza mi się mieć dwa (różne) Komputery z Haswell-CPU na biurku, który powinien dostarczyć FMA i wszystko, myślałem, że przetestuję przykład podany przez Ophiona w pierwszej odpowiedzi, i uzyskałem wynik, który nieco mnie zaskoczył:
Po aktualizacji/instalacji/ustalając lapack/blas/atlas/numpy, otrzymuję na obu maszynach:
>>> a = np.ones(1000, dtype=np.float128)+1e-14
>>> (a*a).sum()
1000.0000000000199999
>>> np.dot(a,a)
1000.0000000000199948
>>> a = np.ones(1000, dtype=np.float64)+1e-14
>>> (a*a).sum()
1000.0000000000198
>>> np.dot(a,a)
1000.0000000000176
Więc standardowe mnożenie + suma() jest bardziej precyzyjne niż np.dot(). timeit jednak potwierdził, że wersja .dot() jest szybsza (ale niewiele) zarówno dla float64, jak i float128.
Czy ktoś może wyjaśnić to?
edytuj: Przypadkowo usunąłem informacje o wersjach numpy: takie same wyniki dla wersji 1.9.0 i 1.9.3 z pythonem 3.4.0 i 3.4.1.
Co ciekawe, tę rozbieżność dostaję tylko w NumPy 1.9.2, a nie NumPy 1.8.2. Obie używają blas + lapack (nie atlas). Z NumPy 1.8.2, wyniki są identyczne z kropką i sumą, sugerując identyczne zdarzenia zaokrąglania, w NumPy 1.9.2, mnożenie + suma() jest bardziej precyzyjna. –
Zobacz http://docs.scipy.org/doc/numpy/release.html#better-numerical-stability- for-sum-in-some-cases –
Również https://github.com/numpy/numpy/pull/3685, czyli tam, gdzie wprowadzono zmianę w wyrażeniu "suma". –