Podstawy MPI-2: część II Dynamiczne zarządzanie procesami

Slides:



Advertisements
Podobne prezentacje
C++ wykład 2 ( ) Klasy i obiekty.
Advertisements

C++ wykład 4 ( ) Przeciążanie operatorów.
Ćwiczenie (1) Dostosuj poniższy program do potrzeb zdefiniowanych w treści programu zaliczeniowego: #include void dodaj(){}; void edytuj(){}; void usun(){};
Język C/C++ Funkcje.
Programowanie obiektowe
Programowanie obiektowe
Wzorce.
Wprowadzenie do języka skryptowego PHP – cz. 2
Systemy rozproszone W. Bartkiewicz
Kamil Smitkiewicz Bezpieczeństwo w PHP.
PROGRAMOWANIE STRUKTURALNE
dynamiczny przydział pamięci
argumenty wiersza poleceń: getopt
formatowanie kodu źródłowego
Zaawansowana obsługa sygnałów
Programowanie imperatywne i język C Copyright, 2004 © Jerzy R. Nawrocki Wprowadzenie.
Programowanie imperatywne i język C
Modularyzacja i struktury danych w C Copyright, 2005 © Jerzy R. Nawrocki Wprowadzenie.
Modularyzacja i struktury danych w C Copyright, 2005 © Jerzy R. Nawrocki Wprowadzenie.
Programowanie imperatywne i język C Copyright, 2004 © Jerzy R. Nawrocki Wprowadzenie.
Wprowadzenie do SystemC
1 Dygresja: cztery płyty główne…. 2 Dygresja: osobliwości C /* cos o nieistniejacym typie Boolean */ /* oraz o operatorze przecinkowym */ #include int.
Gniazda komunikacji sieciowej w języku Java
Programowanie w C Wykład 3
PRZEPEŁNIENIE BUFORA B u f f e r O v e r f l o w
Instytut Fizyki Teoretycznej
Język ANSI C Operacje we/wy
Komunikacja zbiorowa: część II
Język Java Wielowątkowość.
Semafory według normy POSIX
Wątki.
Typy złożone, case, stałe. Typ zbiorowy type typ_zb = set of typ_podstawowy; Typem podstawowym może być tylko typ porządkowy. Typem podstawowym może być
nowe operatory & . (kropka) * operator rzutowy -> , (przecinek)
Schemat Hornera Mgr inż. Michał Szucki.
Programowanie imperatywne i język C Copyright, 2006 © Jerzy R. Nawrocki Wstęp do.
Podstawy programowania II Wykład 2: Biblioteka stdio.h Zachodniopomorska Szkoła Biznesu.
Równoległy algorytm metody Jacobiego rozwiązywania zagadanienia brzegowego dla eliptycznych równań różniczkowych cząstkowych.
Podstawy programowania. Język C i C++– podstawy Temat: 1
GOSPODARKA PAMIĘCIĄ, STRUMIENIE (i nie tylko)
Przekazywanie argumentów
Współczynnik przyspieszenia n - wielkość zadania p - liczba procesorów T(n,p) – czas wykonania.
Automatyka i Robotyka Systemy czasu rzeczywistego Wykład 4.
Programowanie obiektowe – zastosowanie języka Java SE
Inicjalizacja i sprzątanie
Programowanie obiektowe Wykład 3 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21 Dariusz Wardowski.
Definiowanie typów danych użytkownika
Podstawy informatyki 2013/2014
Przekazywanie parametrów do funkcji oraz zmienne globalne i lokalne
Komendy SQL do pracy z tabelami i bazami
Wykład 10 typ zbiorowy rekurencja.
Systemy operacyjne (wiosna 2014)
Funkcje w C++ Funkcja – wydzielony fragment kodu użyty w programie (raz lub więcej razy) spełniający określone zadanie, np. obliczenie średniej ocen.
Kurs języka C++ – wykład 4 ( )
K URS JĘZYKA C++ – WYKŁAD 1 ( ) Łagodne wprowadzenie do języka C++
Technologie internetowe Wykład 5 Wprowadzenie do skrytpów serwerowych.
1 dynamiczny przydział pamięci malloc() free() realloc() calloc() memset() memcpy( ) mempcpy( ) memmove() (wskaźniki!! )
Programowanie proceduralne Podstawy Programowania dla geoinformatyków Wykład 3 Rafał Witkowski, 2015.
1 Uzupełnienie dot. przekazywania argumentów #include struct nowa { int f; char line[20000]; int k; } reprezentant; int main() { void funkcja7( struct.
1 SBD, L.Banachowski Oprogramowanie strony serwera cz. 1 Powtórzenie wyk ł adu 6.
Paweł Starzyk Obiektowe metody projektowania systemów
Podsumowanie wiedzy MPDI2 sem.3 INFORMATYKA. tworzenie nowego pliku i katalogu, nawigacja po katalogach, listowanie zawartości katalogu, zmiana nazw,
Seminarium Dyplomowe: Metodyka i Techniki Programowania Autor: Bartłomiej Fornal.
Pakiety numeryczne Skrypty, funkcje Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania.
ASP.NET Dostęp do bazy danych z poziomu kodu Elżbieta Mrówka-Matejewska.
Dominik Benduski Michał Mandecki Podstawy Visual Basic w Excelu.
Programowanie I Rekurencja.
K URS JĘZYKA C++ – WYKŁAD 3 ( ) Przenoszenie Składowe statyczne Funkcje wbudowane Argumenty domyślne.
Klasy wewnętrzne. Praktyka użycia interfejsów i klas wewnętrznych
Programowanie obiektowe – zastosowanie języka Java SE
dynamiczny przydział pamięci
Zapis prezentacji:

Podstawy MPI-2: część II Dynamiczne zarządzanie procesami

MPI-1 MPI-2 Pula procesorów przydzielonych do zadania jest ustalona przy wywołaniu mpirun. mpirun uruchamia tę samą aplikację na wszystkich procesorach, stąd mnogość if (rank==master), itp. w kodzie. Nie ma narzędzi do uruchomienia komunikacji z innymi procesami. Można dodawać/zwalniać procesory w toku wykonywania aplikacji. Można uruchamiać inne aplikacje z poziomu danej aplikacji. Dany proces może nawiązywać komunikację z innymi procesami.

Kiedy ogranicznenia MPI-1 są uciążliwe? Jeżeli musimy policzyć wiele (dziesiątki a nawet setki) zadań jedno- albo niewielo-procesorowych (np. obliczenia kwantowomechaniczne dla wielu konformacji) a “trywialne” zrównoleglenie aplikacji jest niemożliwe lub nieopłacalne. Jeżeli chcemy napisać program, który musi wywoływać co jakiś czas inną aplikację (np. dynamiczna wizualizacja wyników).

Przykład programu z użyciem MPI-1 startującego wiele kopi aplikacji jednoprocesorowej z różnymi argumentami linii polecenia Każdy procesor czyta plik fort.1 zawierający argumenty linii polecenia dla poszczególnych procesorów. Używając instrukcji call system, dany procesor wykonuje skrypt runall z argumentami linii polecenia odpowiadającymi jego rzędowi. Ten schemat można uogólnić na startowanie różnych aplikacji jednoprocesorowych w zależności od rzędu procesora.

driver.f include “mpif.h” parameter (maxcom=100000) character*80 command(0:maxcom-1) integer rank, size, IERROR integer i,ncom call MPI_Init( IERROR ) call MPI_COMM_RANK( MPI_COMM_WORLD, rank, IERROR ) call MPI_COMM_SIZE( MPI_COMM_WORLD, size , IERROR ) ncom=0 do i=0,maxcom-1 read (1,'(a)',end=10) command(i) ncom=ncom+1 enddo 10 continue do i=rank,ncom-1,size print *,"Processor",rank," executes runall "//command(i) call system("./runall "//command(i)) print *,"Processor",rank," has finished" call MPI_FINALIZE( IERROR ) stop end

runall fort.1 skrypt PBS start.mat #!/bin/csh -f cd $1; run >! $2.monte 1/0.60 1 1/0.60 2 1/0.60 3 1/0.60 4 1/0.60 5 1/0.60 6 1/0.60 7 1/0.60 8 1/0.60 9 1/0.60 10 1/0.60 11 1/0.60 12 1/0.60 13 1/0.60 14 1/0.60 15 1/0.60 16 1/0.60 17 1/0.60 18 1/0.60 19 1/0.60 20 skrypt PBS start.mat #PBS -N ZUCH #PBS -q dque #PBS -l nodes=10:ppn=2 set NPROCS=`cat\ $PBS_NODEFILE | wc -l` echo $NPROCS processors used time mpirun –machinefile\ $PBS_NODEFILE -np $NPROCS\ -nolocal -p4wd\ $PBS_O_WORKDIR\ $PBS_O_WORKDIR/driver

Wykorzystanie rozszerzeń MPI-2: równoległe kopiowanie pcp n-m plik_źródłowy kopia np. pcp 1-10 testfile /tmp/testfile_out ma skopiować plik testfile jako testfile_out do katalogów /tmp maszyn o numerach od 1 do 10. W “Using MPI-2”, katalog starting pcp.c - wersja w MPI-1 (kod dla mastera robotników) pcp-master.c pcp-slave.c – MPI-1, rozdzielone kody pcp-spawn-master.c pcp-spawn-slave.c – MPI-2, rozdzielone kody

Motywacja Rozwiązanie Często zachodzi konieczność szybkiego skopiowania np. programu wykonywalnego lub pliku danych wejściowyh na dyski lokalne wszystkich maszyn przydzielonych do zadania. scp w pętli foreach lub while działa sekwencyjnie a zatem wolno. Rozwiązanie Zorganizować kopiowanie jako czytanie fragmetów pliku a następnie rozsyłanie ich po “drzewie” do robotników, którzy zapisują część na swoich dyskach lokalnych i przesyłają dalej. Najlepiej zastosować do tego celu MPI_Bcast, który rozsyła wiadomości po “drzewie”.

Schemat kopiowania równoległego z wykorzystaniem MPI_Bcast 3 Bufor czytany Bufor przesyłany Bufor zapisywany na dysku lokalnym 1 4 2 5

pcp.c: początek programu /* pcp from SUT, in MPI */ #include "mpi.h" #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #define BUFSIZE 256*1024 #define CMDSIZE 80 int main( int argc, char *argv[] ) { int myrank, mystatus, allstatus, done, numread; char outfilename[128], controlmsg[80]; int infd, outfd; char buf[BUFSIZE]; MPI_Init( &argc, &argv ); MPI_Comm_rank( MPI_COMM_WORLD, &myrank );

pcp.c: przesyłanie nazwy pliku if ( myrank == 0 ) { makehostlist( argv[1], "targets" ); strcpy( outfilename, argv[3] ); if ( (infd = open( argv[2], O_RDONLY ) ) == -1 ) { fprintf( stderr, "input file %s does not exist\n", argv[2] ); sprintf( controlmsg, "exit" ); MPI_Bcast( controlmsg, CMDSIZE, MPI_CHAR, 0, MPI_COMM_WORLD ); MPI_Finalize(); return( -1 ); } else { sprintf( controlmsg, "ready" ); if ( strcmp( controlmsg, "exit" ) == 0 ) {

pcp.c: otwieranie plików if ( myrank == 0 ) sprintf( controlmsg, outfilename ); MPI_Bcast( controlmsg, CMDSIZE, MPI_CHAR, 0, MPI_COMM_WORLD ); if ( (outfd = open( controlmsg, O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU ) ) == -1 ) mystatus = -1; else mystatus = 0; MPI_Allreduce( &mystatus, &allstatus, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD ); if ( allstatus == -1 ) { fprintf( stderr, "output file %s could not be opened\n", outfilename ); MPI_Finalize(); return( -1 ); } /* at this point all files have been successfully opened */ printf("all files opened\n");

pcp.c: kopiowanie done = 0; while ( !done ) { if ( myrank == 0 ) numread = read( infd, buf, BUFSIZE ); MPI_Bcast( &numread, 1, MPI_INT, 0, MPI_COMM_WORLD ); if ( numread > 0 ) { MPI_Bcast( buf, numread, MPI_BYTE, 0, MPI_COMM_WORLD ); write( outfd, buf, numread ); } else { close( outfd ); done = 1; MPI_Finalize();

Program pcp będzie działać ale: nie będzie działać jak “zwykłe” polecenie unixowe a będzie musiał być uruchomiony pod mpirun, lista maszyn, na które będzie kopiowany plik jest przekazywana do mpirun w postaci pliku stojącego po –machinefile. Rozmnażanie procesów w MPI-2 Program wywołujemy na jednym procesorze jak polecenie unixową; mpirun niepotrzebny. Proces wywołujący tworzy listę maszyn na podstawie argumentów linii polecenia a następnie otwiera z nimi komunikację. Inny kod będzie wykonywał master a inny robotnicy.

pcp-master.c: przesyłanie nazwy pliku Najpierw podzielimy program na kod mastera (pcp-master) i robotników (pcp-slave) pcp-master.c: przesyłanie nazwy pliku makehostlist( argv[1], "targets" ); strcpy( outfilename, argv[3] ); if ( (infd = open( argv[2], O_RDONLY ) ) == -1 ) { fprintf( stderr, "input file %s does not exist\n", argv[2] ); sprintf( controlmsg, "exit" ); MPI_Bcast( controlmsg, CMDSIZE, MPI_CHAR, 0, MPI_COMM_WORLD ); MPI_Finalize(); return( -1 ); } else { sprintf( controlmsg, "ready" );

pcp-master.c: otwieranie pliku danych sprintf( controlmsg, outfilename ); MPI_Bcast( controlmsg, CMDSIZE, MPI_CHAR, 0, MPI_COMM_WORLD ); if ( (outfd = open( outfilename, O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU ) ) == -1 ) mystatus = -1; else mystatus = 0; MPI_Allreduce( &mystatus, &allstatus, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD ); if ( allstatus == -1 ) { fprintf( stderr, "output file %s could not be opened\n", outfilename ); MPI_Finalize(); return( -1 ); }

pcp-master.c: kopiowanie /* at this point all files have been successfully opened */ done = 0; while ( !done ) { numread = read( infd, buf, BUFSIZE ); MPI_Bcast( &numread, 1, MPI_INT, 0, MPI_COMM_WORLD ); if ( numread > 0 ) { MPI_Bcast( buf, numread, MPI_BYTE, 0, MPI_COMM_WORLD ); write( outfd, buf, numread ); } else { close( outfd ); done = 1; MPI_Finalize();

pcp-slave.c: odbieranie nazwy pliku i otwieranie pliku MPI_Bcast( controlmsg, CMDSIZE, MPI_CHAR, 0, MPI_COMM_WORLD ); if ( strcmp( controlmsg, "exit" ) == 0 ) { MPI_Finalize(); return -1; } if ( (outfd = open( controlmsg, O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU ) ) == -1 ) mystatus = -1; else mystatus = 0; MPI_Allreduce( &mystatus, &allstatus, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD ); if ( allstatus == -1 ) { return( -1 );

pcp-slave.c: kopiowanie /* at this point all files have been successfully opened */ done = 0; while ( !done ) { MPI_Bcast( &numread, 1, MPI_INT, 0, MPI_COMM_WORLD ); if ( numread > 0 ) { MPI_Bcast( buf, numread, MPI_BYTE, 0, MPI_COMM_WORLD ); write( outfd, buf, numread ); } else { close( outfd ); done = 1; MPI_Finalize();

Wprowadzanie cech MPI-2 Master Robotnicy Tworzenie informacji o procesie wywołującym (MPI_Info_create i MPI_Info_set). Rozmnażanie procesów z przekazaniem informacji o procesie wywołującym (MPI_Comm_spawn). Tworzenie wspólnego komunikatora zawierającego mastera i robotników (MPI_Comm_merge). Uzyskiwanie informacji o procesie wywołującym (MPI_Get_parent).

MPI_INFO_CREATE(info) [OUT info] utworzony obiekt informacyjny (handle) C: int MPI_Info_create(MPI_Info *info) FORTRAN/FORTRAN90: MPI_INFO_CREATE(INFO, IERROR) INTEGER INFO, IERROR C++: static MPI::Info MPI::Info::Create() MPI_INFO_CREATE tworzy nowy obiekt informacyjny, niezawierający na razie żadnych (klucz,wartość).

MPI_INFO_SET(info, key, value) [INOUT info] obiekt informacyjny (handle) [IN key] klucz (string) [IN value] wartość (string) C: int MPI_Info_set(MPI_Info info, char *key, char *value) FORTRAN/FORTRAN90: MPI_INFO_SET(INFO, KEY, VALUE, IERROR) INTEGER INFO, IERROR CHARACTER*(*) KEY, VALUE C++: void MPI::Info::Set(const char* key, const char* value) MPI_INFO_SET dodaje parę (klucz, wartość) do obiektu informacyjnego; poprzednio ustalona wartość klucza jest nadpisywana.

MPI_INFO_DELETE(info, key) [INOUT info] obiekt informacyjny (handle) [IN key] klucz (string) C: int MPI_Info_delete(MPI_Info info, char *key) FORTRAN/FORTRAN90: MPI_INFO_DELETE(INFO, KEY, IERROR) INTEGER INFO, IERROR CHARACTER*(*) KEY C++: void MPI::Info::Delete(const char* key) MPI_INFO_DELETE usuwa parę (klucz,wartość) z danego obiektu informacyjnego.

MPI_COMM_SPAWN(command, argv, maxprocs, info, root, comm, intercomm, array_of_errcodes) [IN command] nazwa programu który ma być wystartowany na odległych procesorach; ważna tylko dla mastera (string) [IN argv] argumenty linii polecenia do przekazania dla robotników; ważne tylko dla mastera (tablica łańcuchów) [IN maxprocs] maksymalna liczba procesów potomnych; ważne tylko dla mastera (integer) [IN info] zbiór par (klucz,wartość), mówiących systemowi gdzie wystartować procesy potomne; ważne tylko dla mastera (handle) [IN root] rząd procesu, który ustala poprzednie argumenty (integer) [IN comm] komunikator (wewnętrzny) zawierający procesy tworzące procesy potomne (handle) [OUT intercomm] interkomunikator pomiędzy grupą oryginalną i noworozmnożonymi procesami (handle) [OUT array_of_errcodes] tablica kodów błędów; jeden dla procesu (array of integer)

C: int MPI_Comm_spawn(char *command, char *argv[], int maxprocs, MPI_Info info, int root, MPI_Comm comm, MPI_Comm *intercomm, int array_of_errcodes[]) FORTRAN/FORTRAN90: MPI_COMM_SPAWN(COMMAND, ARGV, MAXPROCS, INFO, ROOT, COMM, INTERCOMM, ARRAY_OF_ERRCODES, IERROR) CHARACTER*(*) COMMAND, ARGV(*) INTEGER INFO, MAXPROCS, ROOT, COMM, INTERCOMM, ARRAY_OF_ERRCODES(*), IERROR C++: MPI::Intercomm MPI::Intracomm::Spawn(const char* command, const char* argv[], int maxprocs, const MPI::Info& info, int root, int array_of_errcodes[]) const MPI::Intercomm MPI::Intracomm::Spawn(const char* command, const char* argv[], int maxprocs, const MPI::Info& info, int root) const

MPI_COMM_GET_PARENT(parent) [OUT parent] komunikator rodzicielski (handle) C: int MPI_Comm_get_parent(MPI_Comm *parent) FORTRAN/FORTRAN90: MPI_COMM_GET_PARENT(PARENT, IERROR) INTEGER PARENT, IERROR C++: static MPI::Intercomm MPI::Comm::Get_parent() MPI_COMM_GET_PARENT zwraca interkomunikator utworzony przez proces(y) rodzicielski(e) poleceniem MPI_COMM_SPAWN lub MPI_COMM_SPAWN_MULTIPLE; jeżeli takie polecenie nie zostało wydane lub interkomunikator został zwolniony, zwraca MPI_COMM_NULL.

Ilustracja działania MPI_Comm_spawn i MPI_Comm_parent Procesy rodzicielskie Procesy potomne MPI_Comm_spawn MPI_Init Interkomunikator Procesy potomne jako grupa odległa Procesy rodzicielskie jako grupa odległa Zwracany przez MPI_Comm_spawn Zwracany przez MPI_Comm_parent

pcp-spawn-master.c: początek /* pcp from SUT, in MPI */ #include "mpi.h" #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #define BUFSIZE 256*1024 #define CMDSIZE 80 int main( int argc, char *argv[] ) { int mystatus, allstatus, done, numread; char outfilename[128], controlmsg[80]; int infd, outfd; char buf[BUFSIZE]; char soft_limit[20]; MPI_Info hostinfo; MPI_Comm pcpslaves; MPI_Init( &argc, &argv ); makehostlist( argv[1], "targets“, &num_hosts ); MPI_Info_create( &hostinfo ); MPI_Info_set( hostinfo, "file", "targets" ); MPI_Info_set( hostinfo, "soft", soft_limit );

pcp-spawn-master.c: przydzielanie procesorów, do których ma być kopiowany plik MPI_Comm_spawn( "pcp_slave", MPI_ARGV_NULL, num_hosts, hostinfo, 0, MPI_COMM_SELF, &pcpslaves, MPI_ERRCODES_IGNORE ); MPI_Info_free( &hostinfo ); strcpy( outfilename, argv[3] ); if ( (infd = open( argv[2], O_RDONLY ) ) == -1 ) { fprintf( stderr, "input %s does not exist\n", argv[2] ); sprintf( controlmsg, "exit" ); MPI_Bcast( controlmsg, CMDSIZE, MPI_CHAR, 0, pcpslaves ); MPI_Finalize(); return( -1 ); } else { sprintf( controlmsg, "ready" );

pcp-spawn-master.c: przesyłanie nazwy pliku celowego sprintf( controlmsg, outfilename ); MPI_Bcast( controlmsg, CMDSIZE, MPI_CHAR, 0, pcpslaves ); if ( (outfd = open( outfilename, O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU ) ) == -1 ) mystatus = -1; else mystatus = 0; MPI_Allreduce( &mystatus, &allstatus, 1, MPI_INT, MPI_MIN, pcpslaves ); if ( allstatus == -1 ) { fprintf( stderr, "output file %s could not be opened\n", outfilename ); MPI_Finalize(); return( -1 ); }

pcp-spawn-master.c: kopiowanie /* at this point all files have been successfully opened */ done = 0; while ( !done ) { numread = read( infd, buf, BUFSIZE ); MPI_Bcast( &numread, 1, MPI_INT, 0, pcpslaves ); if ( numread > 0 ) { MPI_Bcast( buf, numread, MPI_BYTE, 0, pcpslaves ); write( outfd, buf, numread ); } else { close( outfd ); done = 1; MPI_Comm_free( &pcpslaves ); MPI_Finalize();

pcp-spawn-slave.c: uzyskiwanie informacji od procesu wywołującego i otwieranie pliku celowego MPI_Comm_get_parent( &slavecomm ); MPI_Bcast( controlmsg, CMDSIZE, MPI_CHAR, 0, slavecomm ); if ( strcmp( controlmsg, "exit" ) == 0 ) { MPI_Finalize(); return( -1 ); } if ( (outfd = open( controlmsg, O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU ) ) == -1 ) mystatus = -1; else mystatus = 0; MPI_Allreduce( &mystatus, &allstatus, 1, MPI_INT, MPI_MIN, slavecomm ); if ( allstatus == -1 ) {

pcp-spawn-slave.c: kopiowanie /* at this point all files have been successfully opened */ done = 0; while ( !done ) { MPI_Bcast( &numread, 1, MPI_INT, 0, slavecomm ); if ( numread > 0 ) { MPI_Bcast( buf, numread, MPI_BYTE, 0, slavecomm ); write( outfd, buf, numread ); } else { close( outfd ); done = 1; MPI_Comm_free( &slavecomm ); MPI_Finalize(); return 0;

Uwagi dotyczące MPI_Comm_spawn MPI_UNIVERSE_SIZE mówi ile maksymalnie procesów potomnych można utworzyć a MPI_UNIVERSE_FLAG czy ta zmienna jest zdefiniowana przez system. MPI_UNIVERSE_SIZE definiuje “wszechświat” wszystkich komunikatoró, zarówno wystartowanych jak i potencjalnych komunikatorów potomnych. Zmienną tę można ustawić przy uruchamianiu aplikacji pod mpiexec, np: mpiexec –usize 4 –n 1 ./myprog Zadanie zostanie wystartowane na jednym procesorze z możliwością rozszerzenia do czterech.

Przykład int world_size, universe_size, *universe_sizep, flag; … MPI_Attr_get(MPI_COMM_WORLD, MPI_UNIVERSE_SIZE,&universe_sizep, &flag); if (!flag) { printf("This MPI does not support UNIVERSE_SIZE. How many processes total?"); scanf("%d", &universe_size); } else universe_size = *universe_sizep; if (universe_size == 1) printf("No room to start workers"); strcpy(worker_program, "./workers" ); printf("Nome do programa: %s\n",worker_program); ... error = MPI_Comm_spawn(worker_program, MPI_ARGV_NULL, universe_size-1,Info, 0, MPI_COMM_SELF, &everyone,MPI_ERRCODES_IGNORE);

Tworzenie procesów potomnych obniża efektywność działania programu, dlatego w miarę możności należy pracować na puli od razu przydzielonej do zadania.

Przykład wywołania połączenia z innymi procesami przez serwer i zaakceptowania połączenia przez robotników Serwer: gets(port_name); MPI_Comm_connect(port_name,MPI_INFO_NULL,0, MPI_COMM_WORLD,&server); Robotnicy: MPI_Open_port(MP_INFO_NULL,port_name); MPI_Comm_accept(port_name,MPI_INFO_NULL,port_name);

Unifikacja startowania zadań równoległych w MPI-2 MPI-1: zwykle mpirun ale też yod i inne narzędzia. Składnia mpirun zależna od implementacji. MPI-2: mpiexec (dla kompatybilności jest zwykle podlikowany jako mpirun). Najprościej, np.: mpiexec –n 4 ./myprog działa jak mpirun –np 4 ./myprog Inne parametry: -soft, -host, -arch, -wdir, -path, -file, -usize

Argumenty polecenia są w pliku myfile. mpiexec –n 32 –soft 16 myprog Jeżeli dostępne są 32 procesory to startuje myprog na 32, jeżeli nie na 16. mpiexec –n 4 –host denali –wdir /home/me/outfiles myprog Startuje myprog na 4 procesorach maszyny denali używając jako katalogu roboczego /home/me/outfiles. mpiexec –n 12 –soft 1:12 –arch sparc-solaris \ -path /home/me/sunprogs myprog Usiłuje wystartować myprog na 12 procesorach ale użyje od 1 do 12 w zależności od tego ile jest dostępnych, ograniczając się do maszyn o architekturze sparc-solaris i poszukując myprog w /home/me/sunprogs. mpiexec –file myfile Argumenty polecenia są w pliku myfile.