Wywoływanie mpi binarnie szeregowo jako podproces aplikacji mpi
Mam dużą równoległą (za pomocą MPI) aplikację symulacyjną, która wytwarza duże ilości danych. Aby ocenić te dane, używam skryptu Pythona.
Teraz muszę uruchomić tę aplikację wiele razy (> 1000) i obliczyć właściwości statystyczne z uzyskanych danych.
Do tej pory moim podejściem było równoległe uruchamianie skryptu Pythona (przy użyciu mpi4py, np. 48 węzłów) wywołanie kodu symulacji przy użyciusubprocess.check_call
. Potrzebuję tego połączenia, aby uruchomić aplikację do symulacji mpi w trybie szeregowym. W tym przypadku nie potrzebuję symulacji, aby również działać równolegle. Skrypt Pythona może następnie analizować dane równolegle i po zakończeniu uruchamia nową symulację, aż do zgromadzenia dużej liczby przebiegów.
Cele są
nie zapisuje całego zestawu danych z 2000 uruchomieńutrzymywanie pośrednich danych w pamięciStub MWE:
plikmulti_call_master.py
:from mpi4py import MPI
import subprocess
print "Master hello"
call_string = 'python multi_call_slave.py'
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()
print "rank %d of size %d in master calling: %s" % (rank, size, call_string)
std_outfile = "./sm_test.out"
nr_samples = 1
for samples in range(0, nr_samples):
with open(std_outfile, 'w') as out:
subprocess.check_call(call_string, shell=True, stdout=out)
# analyze_data()
# communicate_results()
plikmulti_call_slave.py
(byłby to kod symulacji C):from mpi4py import MPI
print "Slave hello"
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()
print "rank %d of size %d in slave" % (rank, size)
To nie zadziała. Wynikowe wyjściestdout
:
Master hello
rank 1 of size 2 in master calling: python multi_call_slave_so.py
Master hello
rank 0 of size 2 in master calling: python multi_call_slave_so.py
[cli_0]: write_line error; fd=7 buf=:cmd=finalize
:
system msg for write_line failure : Broken pipe
Fatal error in MPI_Finalize: Other MPI error, error stack:
MPI_Finalize(311).....: MPI_Finalize failed
MPI_Finalize(229).....:
MPID_Finalize(150)....:
MPIDI_PG_Finalize(126): PMI_Finalize failed, error -1
[cli_1]: write_line error; fd=8 buf=:cmd=finalize
:
system msg for write_line failure : Broken pipe
Fatal error in MPI_Finalize: Other MPI error, error stack:
MPI_Finalize(311).....: MPI_Finalize failed
MPI_Finalize(229).....:
MPID_Finalize(150)....:
MPIDI_PG_Finalize(126): PMI_Finalize failed, error -1
Wynikowe wyjściesm_test.out
:
Slave hello
rank 0 of size 2 in slave
Powodem jest to, że podproces zakłada uruchomienie jako aplikacja równoległa, podczas gdy ja zamierzam uruchomić go jako aplikację szeregową. Jako bardzo „hacky” obejście zrobiłem co następuje:
Skompiluj wszystkie potrzebne biblioteki świadome mpi z określoną dystrybucją mpi, tj. Intel mpiSkompiluj kod symulacyjny z inną biblioteką mpi, tj. OpenmpiGdybym teraz uruchamiał mój równoległy skrypt Pythona używając intel mpi, podstawowa symulacja nie byłaby świadoma otaczającego środowiska równoległego, ponieważ korzystała z innej biblioteki.
Przez jakiś czas działało to dobrze, ale niestety nie jest bardzo przenośne i trudne do utrzymania na różnych klastrach z różnych powodów.
mógłbym
umieść pętlę wywołującą podproces w skrypcie powłoki za pomocąsrun
Czy wymagałoby buforowania wyników w HDużyj jakiegoś rodzajuMPI_Comm_spawn
technika w pytonienie ma być tak używanytrudno się dowiedzieć, czy proces podprocesu został zakończonyprawdopodobnie konieczne zmiany w kodzie C.W jakiś sposób oszukać podproces w nie przesyłaniu informacji MPIpróbowałem manipulować zmiennymi środowiskowymi bezskutecznierównież nie powinien być używany w ten sposóbza pomocąmpirun -n 1
lubsrun
dla wywołania podprocesu nie pomagaCzy jest jakiś elegancki, oficjalny sposób na zrobienie tego? Naprawdę nie mam pomysłów i doceniam każdy wkład!