#c #multiplication #openmpi #double-precision
#c #умножение #openmpi #двойная точность
Вопрос:
В моем коде у меня есть это умножение в коде C со всеми типами переменных как double[]
f1[0] = (f1_rot[0] * xu[0]) (f1_rot[1] * yu[0]);
f1[1] = (f1_rot[0] * xu[1]) (f1_rot[1] * yu[1]);
f1[2] = (f1_rot[0] * xu[2]) (f1_rot[1] * yu[2]);
f2[0] = (f2_rot[0] * xu[0]) (f2_rot[1] * yu[0]);
f2[1] = (f2_rot[0] * xu[1]) (f2_rot[1] * yu[1]);
f2[2] = (f2_rot[0] * xu[2]) (f2_rot[1] * yu[2]);
соответствующий этим значениям
Force Rot1 : -5.39155e-07, -3.66312e-07
Force Rot2 : 4.04383e-07, -1.51852e-08
xu: 0.786857, 0.561981, 0.255018
yu: 0.534605, -0.82715, 0.173264
F1: -6.2007e-07, -4.61782e-16, -2.00963e-07
F2: 3.10073e-07, 2.39816e-07, 1.00494e-07
это умножение, в частности, приводит к неправильному значению -4.61782e-16 вместо 1.04745e-13
f1[1] = (f1_rot[0] * xu[1]) (f1_rot[1] * yu[1]);
Я вручную проверил другие умножения на калькуляторе, и все они, похоже, выдают правильные значения.
это открытый mpi-скомпилированный код, и приведенный выше результат предназначен для запуска одного процессора, при запуске нескольких процессоров могут быть разные значения, например, 40 процессоров выдают 1.66967e-13 в результате умножения F1 [1].
Это какая-то ошибка mpi? или проблема с точностью типа? и почему это работает нормально для других умножений?
Комментарии:
1. MPI намекает на условие гонки: математика почти никогда не является ошибкой.
2. что такое f1_rot[0] и f1_rot[1]/
3. Да, я бы также сказал, что вы создали условие гонки. Возможно, вы забыли какой-то барьер перед показанным вами кодом (
f1_rot
,xu
, и т. Д. не устанавливается надежно до выполнения умножения).4. @user3344003 Принудительно Rot1 и принудительно Rot2
Ответ №1:
Ваша проблема является очевидным результатом так называемого катастрофического суммирования: как мы знаем, с плавающей запятой двойной точности могут обрабатываться числа около 16 значащих десятичных знаков.
f1[1] = (f1_rot[0] * xu[1]) (f1_rot[1] * yu[1])
= -3.0299486605499998e-07 3.0299497080000003e-07
= 1.0474500005332475e-13
Это то, что мы получаем с числами, которые вы привели в своем примере.
Обратите внимание (-7) - (-13) = 6
, что это соответствует числу десятичных знаков в строке с плавающей запятой, которое вы приводите в своем примере: (например: -5.39155e-07 -3.66312e-07, каждая мантисса имеет точность 6 десятичных знаков). Это означает, что вы использовали здесь плавающие значения с одинарной точностью.
Я уверен, что в ваших вычислениях точность ваших чисел больше, поэтому вы получаете более точный результат.
В любом случае, если вы используете плавающие значения с одинарной точностью, вы не можете ожидать лучшей точности. С двойной точностью вы можете найти точность до 16. Вы не должны доверять разнице между двумя числами, если только она не больше мантиссы:
- Плавающие значения простой точности: (a — b) / b > = ~ 1e-7
- Плавающие значения двойной точности: (a — b) / b > = ~ 4e-16
Для получения дополнительной информации см. Эти примеры …или таблица в этой статье …
Комментарии:
1. Хорошо, теперь я понимаю, как я получаю эти числа. Однако это означает, что при переходе на большее количество процессоров происходит потеря точности? как это происходит и можно ли это исправить?
2. Похоже, вы делаете матричный продукт. Для больших матриц суммируется более двух членов. В случае, если вас интересуют коэффициенты, теоретически можно использовать некоторые методы для уменьшения потери информации: например, суммирование отдельно отрицательных и положительных чисел от наименьшего (по абсолютному значению) до наибольшего. Существует также так называемое суммирование Кахана … это может быть более адаптировано к матрицам. В любом случае, вы не будете делать это вручную, некоторые библиотеки делают это нормально.
3. >>> В общем, вам не понадобится большая точность для всех коэффициентов вашей матрицы; действительно, матрица — это набор из множества значений, которые имеют значение вместе. Когда вы заметите потерю точности, это не будет касаться самых больших коэффициентов, будут затронуты только те, которые незначительны. Однако вы можете получить плохо обусловленную матрицу, если контраст между меньшими и большими коэффициентами высок.
4. Чтобы повысить точность ваших чисел, должны быть некоторые (символьные) библиотеки, которые делают это очень хорошо. Однако вы можете заметить замедление в ваших вычислениях. Вы можете попробовать GNU … например