Группировка задач MPI по хосту
Я хочу легко выполнять коллективные коммуникации независимо на каждой машине моего кластера. Допустим, у меня есть 4 машины с 8 ядрами на каждой, моя программа MPI будет выполнять 32 задачи MPI. Что я хотел бы, для данной функции:
- на каждом хосте только одна задача выполняет вычисление, другие задачи ничего не делают во время этого вычисления. В моем примере вычисление выполнят 4 задачи MPI, еще 28 ожидают.
- По завершении вычислений каждая задача MPI для каждой будет выполнять коллективную связь ТОЛЬКО с локальными задачами (задачами, выполняющимися на одном хосте).
Концептуально я понимаю, что должен создать один коммуникатор для каждого хоста. Я искал вокруг, и ничего не нашел явно, делая это. Мне не очень комфортно с группами MPI и коммуникаторами. Вот мои два вопроса:
- такое MPI_Get_processor_name достаточно уникален для такого поведения?
- в целом, у вас есть кусок кода, который делает это?
4 ответа
В спецификации сказано, что MPI_Get_processor_name
возвращает "Уникальный спецификатор для фактического (в отличие от виртуального) узла", так что я думаю, что вы будете в порядке с этим. Я предполагаю, что вы соберете все имена хостов, а затем назначите группы процессоров для создания своих коммуникаторов; или дублируйте MPI_COMM_WORLD, превратите имена в целочисленные хэши и используйте mpi_comm_split для разбиения набора.
Вы также можете воспользоваться подходом, который предлагает janneb, и использовать специфичные для реализации опции для mpirun, чтобы гарантировать, что реализация MPI назначает задачи таким образом; OpenMPI использует --byslot для генерации этого порядка; с mpich2 вы можете использовать -print-rank-map, чтобы увидеть отображение.
Но действительно ли это то, что вы хотите сделать? Если другие процессы бездействуют, пока работает один процессор, как это лучше, чем все избыточно выполняют вычисления? (Или это очень интенсивно использует память или ввод-вывод, и вы беспокоитесь о конфликте?) Если вы собираетесь делать много этого - обработка распараллеливания на узле сильно отличается от распараллеливания вне узла - тогда Вы можете подумать о гибридных моделях программирования - выполнение одной задачи MPI на узел и подзадач MPI_spawning или использование OpenMP для связи на узле, как предложено HPM.
Я не думаю (образованная мысль, не окончательная), что вы сможете делать то, что вы хотите полностью из вашей программы MPI.
Ответ системы на звонок MPI_Get_processor_name
зависит от системы; в вашей системе это может вернуться node00
, node01
, node02
, node03
в зависимости от обстоятельств, или он может вернуться my_big_computer
для любого процессора, на котором вы на самом деле работаете. Первое более вероятно, но это не гарантировано.
Одной из стратегий будет запуск 32 процессов и, если вы сможете определить, на каком узле работает каждый из них, разделите ваш коммуникатор на 4 группы, по одной на каждом узле. Таким образом, вы можете самостоятельно управлять внутренними и внутренними коммуникациями.
Другой стратегией было бы запустить 4 процесса и закрепить их на разных узлах. То, как вы прикрепляете процессы к узлам (или процессорам), будет зависеть от вашей среды выполнения MPI и любой вашей системы управления заданиями, такой как Grid Engine. Вероятно, это потребует установки переменных среды, но вы ничего не скажете нам о своей системе времени выполнения, поэтому мы не можем догадаться, что они могут быть. Затем вы можете динамически порождать каждый из 4-х процессов (7 или 8) и привязывать их к тому же узлу, что и начальный процесс. Чтобы сделать это, прочитайте тему интеркоммуникаторов и документацию вашей системы времени выполнения.
Третья стратегия, которая сейчас немного сумасшедшая, состоит в том, чтобы запускать 4 отдельные программы MPI (по 8 процессов в каждой), по одной на каждом узле кластера, и присоединяться к ним по мере их выполнения. Прочитать о MPI_Comm_connect
а также MPI_Open_port
для деталей.
Наконец, для дополнительного удовольствия вы можете подумать о том, чтобы гибридизировать вашу программу, запустив по одному MPI-процессу на каждом узле, и заставить каждый из этих процессов выполнять программу OpenMP с общей памятью (под).
Обычно ваша среда выполнения MPI может управляться, например, переменными среды, как задачи распределяются по узлам. По умолчанию используется последовательное распределение, то есть для вашего примера 32 задачи распределены по 4 8-ядерным компьютерам, которые у вас будут
- Машина 1: MPI занимает 0-7
- машина 2: MPI занимает 8-15
- Машина 3: MPI занимает 16-23
- машина 4: MPI занимает 24-31
И да, MPI_Get_processor_name должно получить имя хоста, чтобы вы могли выяснить, где находятся границы между хостами.
Современный ответ MPI 3 на это состоит в том, чтобы вызватьMPI_Comm_split_type