Учитывая две разные реализации BLAS, можем ли мы ожидать, что они будут делать одни и те же вычисления с плавающей запятой и возвращать одинаковые результаты? Или может случиться, например, что скалярное произведение вычисляется как а один - как ( x 1 y 1 + x 2 y 2 ) + ( х 3 у 3 + х 4
поэтому, возможно, дать другой результат в арифметике IEEE с плавающей запятой?
floating-point
blas
Федерико Полони
источник
источник
Ответы:
Нет, это не гарантировано. Если вы используете NETLIB BLAS без каких-либо оптимизаций, в большинстве случаев верно, что результаты совпадают. Но для любого практического использования BLAS и LAPACK используется высокооптимизированный параллельный BLAS. Распараллеливание приводит к тому, что, даже если оно работает только параллельно внутри векторных регистров ЦП, меняется порядок вычисления отдельных членов и изменяется порядок суммирования. Теперь из отсутствующего ассоциативного свойства в стандарте IEEE следует, что результаты не совпадают. Так что именно то, что вы упомянули, может произойти.
В NETLIB BLAS скалярное произведение является только циклом for, развернутым в 5 раз:
и это зависит от компилятора, если каждое умножение добавляется в DTEMP немедленно или если все 5 компонентов суммируются первыми и затем добавляются в DTEMP. В OpenBLAS ядро зависит от архитектуры:
который разбивает скалярное произведение на маленькие скалярные произведения длины 4 и суммирует их.
При использовании других типичных реализаций BLAS, таких как ATLAS, MKL, ESSL, ... эта проблема остается той же, поскольку каждая реализация BLAS использует различные оптимизации для получения быстрого кода. Но, насколько я знаю, нужен искусственный пример, чтобы вызвать действительно ошибочные результаты.
Если необходимо, чтобы библиотека BLAS возвращала для тех же результатов (побитовых и одинаковых), необходимо использовать воспроизводимую библиотеку BLAS, такую как:
источник
Краткий ответ
Если две реализации BLAS написаны для выполнения операций в одном и том же порядке, а библиотеки были скомпилированы с использованием одних и тех же флагов компилятора и с одинаковым компилятором, то они дадут вам один и тот же результат. Арифметика с плавающей запятой не случайна, поэтому две идентичные реализации дадут одинаковые результаты.
Однако есть множество вещей, которые могут нарушить это поведение ради производительности ...
Более длинный ответ
IEEE также определяет порядок, в котором эти операции выполняются, в дополнение к тому, как должна вести себя каждая операция. Однако, если вы компилируете свою реализацию BLAS с такими опциями, как «-ffast-math», компилятор может выполнять преобразования, которые были бы истинными в точной арифметике, но не «правильными» в плавающей точке IEEE. Канонический пример - неассоциативность сложения с плавающей запятой, как вы указали. При более агрессивных настройках оптимизации будет предполагаться ассоциативность, и процессор будет делать как можно больше параллельно, переупорядочивая операции.
источник
if (x == 0) assert(x == 0)
может произойти сбой, который с определенной точки зрения так же хорош, как и случайный.if (x != 0) assert(x != 0)
из-за арифметики с повышенной точностью.В общем нет. Оставляя в стороне ассоциативность, выбор флагов компилятора (например, включение инструкций SIMD, использование сложного умножения и т. Д.) Или аппаратного обеспечения (например, используется ли расширенная точность ) может привести к различным результатам.
Есть некоторые попытки получить воспроизводимые реализации BLAS. См. ReproBLAS и ExBLAS для получения дополнительной информации.
источник