Подтвердить что ты не робот

Численные ошибки округления с плавающей запятой

Во время поиска какого-то многозначного материала я столкнулся с вопросом о точности округления numpy.dot():

Numpy: Разница между точками (a, b) и (a * b).sum()

Так как у меня на компьютере есть две (разные) компьютеры с процессорами Haswell, которые должны обеспечить FMA и все, я думал, что испытаю пример, данный Офионом в первом ответе, и я получил результат, несколько удивил меня:

После обновления/установки/исправления lapack/blas/atlas/numpy я получаю следующее на обеих машинах:

>>> 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

Таким образом, стандартное умножение + sum() более точное, чем np.dot(). timeit однако подтвердил, что версия .dot() быстрее (но не очень) для float64 и float128.

Может ли кто-нибудь объяснить это?

edit: Я случайно удалил информацию о версиях numpy: те же результаты для 1.9.0 и 1.9.3 с python 3.4.0 и 3.4.1.

4b9b3361

Ответ 1

Похоже, недавно они добавили специальное Pairwise Sumation к ndarray.sum для улучшения числовой стабильности.

Из PR 3685 это влияет на:

all add.reduce calls that go over float_add with IS_BINARY_REDUCE true
so this also improves mean/std/var and anything else that uses sum.

Смотрите здесь для изменения кода.