Питон многопроцессорной обработки в ЛПУ
У меня есть скрипт на python, который я написал с помощью модуля многопроцессорной обработки, для более быстрого выполнения. Расчет идет до неловкости параллельно, поэтому эффективность вычислений зависит от количества процессоров. Теперь я хотел бы использовать это в программе MPI, которая управляет вычислением MCMC на нескольких компьютерах. Этот код содержит вызов system (), который вызывает скрипт python. Тем не менее, я нахожу, что, когда он называется таким образом, эффективность увеличивается от использования многопроцессорной обработки python пропадает.
Как я могу заставить мой скрипт python сохранять прирост скорости от многопроцессорной обработки при вызове из MPI?
Вот простой пример, который аналогичен гораздо более сложным кодам, которые я хочу использовать, но показывает то же самое общее поведение. Я пишу исполняемый скрипт python под названием junk.py.#!/usr/bin/python
import multiprocessing
import numpy as np
nproc = 3
nlen = 100000
def f(x):
print x
v = np.arange(nlen)
result = 0.
for i, y in enumerate(v):
result += (x+v[i:]).sum()
return result
def foo():
pool = multiprocessing.Pool(processes=nproc)
xlist = range(2,2+nproc)
print xlist
result = pool.map(f, xlist)
print result
if __name__ == '__main__':
foo()
Когда я запускаю это из оболочки сам по себе, используя "top", я вижу три процесса python, каждый из которых занимает 100% процессора на моей 16-ядерной машине.
node094:mpi[ 206 ] /usr/bin/time junk.py
[2, 3, 4]
2
3
4
[333343333400000.0, 333348333450000.0, 333353333500000.0]
62.68user 0.04system 0:21.11elapsed 297%CPU (0avgtext+0avgdata 16516maxresident)k
0inputs+0outputs (0major+11092minor)pagefaults 0swaps
Однако, если я вызываю это с mpirun, каждый процесс python занимает 33% процессора, и в целом он занимает примерно в три раза больше времени для запуска. Вызов с помощью-np 2 или более приводит к большему количеству процессов,но не ускоряет вычисление.
node094:mpi[ 208 ] /usr/bin/time mpirun -np 1 junk.py
[2, 3, 4]
2
3
4
[333343333400000.0, 333348333450000.0, 333353333500000.0]
61.63user 0.07system 1:01.91elapsed 99%CPU (0avgtext+0avgdata 16520maxresident)k
0inputs+8outputs (0major+13715minor)pagefaults 0swaps
(дополнительные примечания: это mpirun 1.8.1, python 2.7.3 на Linux Debian версии wheezy. Я слышал, что system() не всегда разрешена в программах MPI, но она работала для меня в течение последних пяти лет на этом компьютере. Для пример я вызвал параллельный код на основе pthread из system() в программе MPI, и он использует 100% cpu для каждого потока, как требуется. Кроме того, в случае, если вы собирались предложить запустить скрипт python в последовательном режиме и просто вызвать его на большем количестве узлов...вычисление MCMC включает фиксированное число цепочек, которые должны двигаться синхронно, поэтому вычисление, к сожалению, не может быть реорганизовано таким образом.)
1 ответ:
Mpirun OpenMPI, v1. 7 и более поздние версии , по умолчанию привязывает процессы к ядрам - то есть, когда он запускает python junk.py процесс, он связывает его с ядром, на котором он будет работать. Это нормально, и правильное поведение по умолчанию для большинства случаев использования MPI. Но здесь каждая задача MPI затем разветвляет больше процессов (через пакет многопроцессорной обработки), и эти разветвленные процессы наследуют состояние привязки своего родителя - так что все они привязаны к одному ядру, борясь между собой. (Столбец " P " в верхней части покажет вам, что все они находятся на одном процессоре)
Если вы mpirun-np 2, вы найдете два набора из трех процессов, каждый на другом ядре, каждый борется между собой.
С OpenMPI вы можете избежать этого, отключив привязку,
mpirun -np 1 --bind-to none junk.py
Или выбрать какую-то другую привязку, которая имеет смысл, учитывая окончательную геометрию вашего запуска. MPICH имеетаналогичные варианты с hydra .
Обратите внимание, что fork()ing подпроцессов с mpi не всегда безопасно или поддерживается , особенно с кластерами, работающими с InfiniBand interconnects, но mpirun/mpiexec OpenMPI предупредит вас, если это не безопасно.