Как обратиться к числовой неассоциативности для параллельного сокращения?

17

Параллельное сокращение предполагает, что соответствующая операция является ассоциативной. Это предположение нарушается при добавлении чисел с плавающей запятой. Вы можете спросить, почему я забочусь об этом. Что ж, это делает результаты менее воспроизводимыми. И это ухудшается, когда моделируемый отжиг используется для оптимизации (или подгонки параметров) по подпрограммам, дающим такие невоспроизводимые результаты.

Каковы общие способы решения этой проблемы? Что можно сказать о следующих стратегиях?

  • Не заботьтесь о невоспроизводимости.
  • Не используйте параллельное сокращение с числами с плавающей запятой и сложением.
  • Создавайте рабочие пакеты подходящего размера воспроизводимым способом и выполняйте окончательное сокращение вручную.
  • Используйте более высокую точность для сложения (но не все компиляторы предлагают более высокую точность типов с плавающей запятой).
Томас Климпел
источник
Вас беспокоит воспроизводимость одного и того же числа процессов или воспроизводимость на другом количестве процессоров? Какую долю производительности вы готовы принять за побитовую воспроизводимость? Вас интересует только моделируемый отжиг?
Джед Браун
@JedBrown Меня беспокоит возможность получения воспроизводимых результатов, например, для устранения потенциальных проблем. Хорошо для меня, если есть способ воспроизвести результаты, например, используя то же количество процессоров (или просто «зная» количество процессоров, использованных изначально). Я хотел бы взять на себя удар производительности, связанный с использованием более высокой точности типов с плавающей запятой для самого сложения. Мои конкретные проблемы были в основном связаны с имитацией отжига и неожиданными различиями, но все они оказались настоящими ошибками.
Томас Климпел

Ответы:

15

Сокращение, реализованное с использованием MPI_Allreduce(), воспроизводимо при условии, что вы используете одинаковое количество процессоров, при условии, что реализация соблюдает следующее примечание, приведенное в разделе 5.9.1 стандарта MPI-2.2.

Совет разработчикам . Настоятельно рекомендуется MPI_REDUCEреализовать его таким образом, чтобы при применении функции к одинаковым аргументам в одном и том же порядке получался один и тот же результат. Обратите внимание, что это может помешать оптимизации, использующей преимущества физического расположения процессоров. ( Конец совета разработчикам .)

Если вам нужно гарантировать воспроизводимость любой ценой, вы можете следовать рекомендациям в следующем параграфе:

Совет пользователям . Некоторые приложения могут не иметь возможности игнорировать неассоциативный характер операций с плавающей запятой или могут использовать пользовательские операции (см. Раздел 5.9.5), которые требуют специального порядка сокращения и не могут рассматриваться как ассоциативные. Такие приложения должны обеспечивать порядок оценки явно. Например, в случае операций, требующих строгого порядка вычисления слева направо (или справа налево), это можно сделать, собрав все операнды в одном процессе (например, с помощью MPI_GATHER), применив операцию сокращения в нужном порядке (например, с помощью MPI_REDUCE_LOCAL) и, если необходимо, передают или рассылают результат другим процессам (например, с помощью MPI_BCAST). ( Конец совета пользователям .)

В более широком плане эффективные алгоритмы для большинства приложений используют преимущества локальности. Поскольку алгоритм действительно отличается при запуске на другом количестве процессов, просто нецелесообразно точно воспроизводить результаты при запуске на другом количестве процессов. Возможное исключение - многосетка с демпфированными сглаживателями Якоби или полиномиальными (например, чебышевскими), где этот простой метод может работать очень хорошо.

При одинаковом количестве процессов часто полезно обрабатывать сообщения в том порядке, в котором они получены (например, с использованием MPI_Waitany()), что вводит недетерминизм. В таких случаях вы можете реализовать два варианта: быстрый, который получает в любом порядке, и «отладочный», который получает в статическом порядке. Это требует, чтобы все базовые библиотеки также были написаны для обеспечения такого поведения.

Для отладки в некоторых случаях вы можете изолировать часть вычислений, которая не предлагает такого воспроизводимого поведения, и выполнять это с избыточностью. В зависимости от того, как были разработаны компоненты, это изменение может быть небольшим количеством кода или очень навязчивым.

Джед браун
источник
6

По большей части я тоже отвечу Джеду. Однако есть и другой выход: учитывая размер обычных чисел с плавающей запятой, вы можете хранить каждое число в 4000-битном числе с фиксированной запятой. Таким образом, если вы сделаете сокращение для чисел с плавающей запятой, таким образом, вы получите точное вычисление, независимо от ассоциативности. (Извините, у меня нет ссылки на то, кто придумал эту идею.)

Виктор Эйххоут
источник
1
Я не думаю, что он был первым, но у вашего коллеги, доктора Бэндбилда, определенно есть хорошая статья на эту тему: sites.utexas.edu/jdm4372/2012/02/15/…
Джефф,
5

Вы можете реализовать численно устойчивый алгоритм сокращения в MPI так же, как в последовательном. Конечно, может быть удар по производительности. Если вы можете позволить себе реплицировать вектор, просто используйте MPI_Gather и сделайте численно устойчивое сокращение серийного номера в корне. В некоторых случаях вы можете обнаружить, что снижение производительности не имеет большого значения.

Другим решением является использование широких аккумуляторов, как описано здесь . Вы можете сделать это с MPI в качестве пользовательского сокращения, хотя оно будет использовать гораздо большую пропускную способность.

Компромиссом для вышеперечисленного является использование компенсированного суммирования. См. Ссылки «Суммирование Кахана» для деталей. Хайкам « Точность и стабильность численных алгоритмов » является отличным ресурсом по этой теме.

Джефф
источник
2

Я хотел бы отметить, что вместо использования арифметики с более высокой точностью для сложения существует возможность использования скомпенсированного суммирования (см. [1]). Это может повысить точность суммирования без необходимости прибегать к более крупным типам данных.

[1] Higham, NJ. Точность суммирования с плавающей точкой. SIAM Journal of Scientific Computing 14, 783–799 (1993).

Хуан М. Белло-Ривас
источник