Сокращение, реализованное с использованием MPI_Allreduce()
, воспроизводимо при условии, что вы используете одинаковое количество процессоров, при условии, что реализация соблюдает следующее примечание, приведенное в разделе 5.9.1 стандарта MPI-2.2.
Совет разработчикам . Настоятельно рекомендуется MPI_REDUCE
реализовать его таким образом, чтобы при применении функции к одинаковым аргументам в одном и том же порядке получался один и тот же результат. Обратите внимание, что это может помешать оптимизации, использующей преимущества физического расположения процессоров. ( Конец совета разработчикам .)
Если вам нужно гарантировать воспроизводимость любой ценой, вы можете следовать рекомендациям в следующем параграфе:
Совет пользователям . Некоторые приложения могут не иметь возможности игнорировать неассоциативный характер операций с плавающей запятой или могут использовать пользовательские операции (см. Раздел 5.9.5), которые требуют специального порядка сокращения и не могут рассматриваться как ассоциативные. Такие приложения должны обеспечивать порядок оценки явно. Например, в случае операций, требующих строгого порядка вычисления слева направо (или справа налево), это можно сделать, собрав все операнды в одном процессе (например, с помощью
MPI_GATHER
), применив операцию сокращения в нужном порядке (например, с помощью
MPI_REDUCE_LOCAL
) и, если необходимо, передают или рассылают результат другим процессам (например, с помощью MPI_BCAST
). ( Конец совета пользователям .)
В более широком плане эффективные алгоритмы для большинства приложений используют преимущества локальности. Поскольку алгоритм действительно отличается при запуске на другом количестве процессов, просто нецелесообразно точно воспроизводить результаты при запуске на другом количестве процессов. Возможное исключение - многосетка с демпфированными сглаживателями Якоби или полиномиальными (например, чебышевскими), где этот простой метод может работать очень хорошо.
При одинаковом количестве процессов часто полезно обрабатывать сообщения в том порядке, в котором они получены (например, с использованием MPI_Waitany()
), что вводит недетерминизм. В таких случаях вы можете реализовать два варианта: быстрый, который получает в любом порядке, и «отладочный», который получает в статическом порядке. Это требует, чтобы все базовые библиотеки также были написаны для обеспечения такого поведения.
Для отладки в некоторых случаях вы можете изолировать часть вычислений, которая не предлагает такого воспроизводимого поведения, и выполнять это с избыточностью. В зависимости от того, как были разработаны компоненты, это изменение может быть небольшим количеством кода или очень навязчивым.