Martin Lísal říjen 2003 1 Rozdělení paralelních úloh z hlediska jejich spolupráce během výpočtu Podle spolupráce během výpočtu můžeme rozdělit paralelní úlohy na MPMD (Multiple Program Multiple Data) úlohy SPMD (Single Program Multiple Data) úlohy MPMD úlohy lze dále rozdělit na typ Master/Worker (obr. 1a) Coupled Multiple Analysis (obr. 1b) Úlohy typu Master/Worker jsou charakteristické existencí řídícího procesu (master, a.out v obr. 1a), který řídí ostatní procesy (worker, b.out v obr. 1a) a nechává si od nich počítat mezivýsledky. Úlohy typu Coupled Multiple Analysis jsou charakteristické použitím nezávislých procesů (a.out, b.out a c.out v obr. 1b), které řeší různé aspekty určitého problému. Např. při návrhu trupu letadla by program a.out řešil proudění, b.out by řešil pevnostní analýzu a c.out analýzu teplotní. SPMD úlohy (obr. 1c) používají stejnou kopii programu (single program) na všech procesorech. Procesy ale během výpočtu zpracovávají různá data (multiple data). SPMD úlohy jsou typické pro numerické výpočty a my se SPMD úlohami budeme výhradně zabývat v rámci tohoto předmětu. 1
2 SPMD úlohy a strategie paralelizace Uveďme si jednoduchý příklad paralelizace programu pro součet prvků vektoru, který ozřejmí pojem SPMD úlohy a naznačí strategii paralelizace SPMD úloh. Představme si, že máme vektor a mající 9 000 000 000 prvků. Úkol je sestavit paralelní program pro součet prvků vektoru a ( 9 000 000 000 i=1 a i ), přičemž máme k dispozici 3 procesory. Rozdělme si úlohu pomyslně na 3 části: (i) načtení vektoru a, S 1, (ii) vlastní výpočet součtu, P, a (iii) tisk součtu, S 2. Je zřejmé, že jen vlastní výpočet součtu P lze paralelizovat. 1 Paralelizaci provedeme tak, že každý procesor spočte 1/3 součtu a tu pak pošle na jeden procesor, který provede celkový součet, jež následně vytiskne. Paralelní program pro součet prvků vektoru zapsaný v jazyce FORTRAN může vypadat následovně (v místech programu, jež by měla obsahovat MPI paralelní příkazy, jsou komentáře označeny jako... ): 1 Načtení dat se nedoporučuje paralelizovat, neboť způsob načítání dat se liší systém od systému. 2
program soucet implicit none integer :: i,my_rank,p,n_loc,i_begin,i_end real :: a(9000000000), & sum_loc,sum_tot open(10,file= input.dat ) do i=1,9000000000 read(10,*) a(i) end do close(10) "MPI: zjisti počet procesů p, které se podílí na výpočtu" "MPI: zjisti moje pořadí my_rank ve výpočtu; my_rank=0,1,...,p-1" n_loc=9000000000/p Předpokládáme dělitelnost beze zbytku :-) i_begin=my_rank*n_loc+1 i_end=(my_rank+1)*n_loc sum_loc=0.0 do i=i_begin,i_end sum_loc=sum_loc+a(i) end do "MPI: zajisti sečtení jednotlivých sum_loc do sum_tot a pošli sum_tot např. na proces mající my_rank=0 " if(my_rank == 0) then write(*,*) sum_tot end if stop "soucet: Konec vypoctu" end program soucet 3
Obrázek 1: Paralelní úlohy z hlediska jejich spolupráce během výpočtu. (a) MPMD (Multiple Program Multiple Data) úloha typu Master/Worker, (b) MPMD úloha typu Coupled Multiple Analysis a (c) SPMD (Single Program Multiple Data) úloha. 4
Obrázek 1 (M. Lísal, 2. Týden) (a) MPMD úloha typu "Master/Worker" (b) MPMD úloha typu "Coupled Multiple Analysis" a.out b.out a.out b.out c.out (c) SPMD úloha a.out
Martin Lísal říjen 2003 1 Co je to MPI? MPI (Message Passing Interface) je knihovna funkcí a podprogramů, která umožňuje: vytvořit prostředí pro paralelní počítání; komunikaci mezi procesy během výpočtu např. posílání informací z procesu na proces; kolektivní operace např. sečtení mezivýsledků z procesů a uložení celkové součtu na určitý proces; topologizaci procesů t.j. např. seskupení určitého počtu procesů za účelem jejich spolupráce v rámci výpočtů. MPI lze použít ve spojení s programovacími jazyky FORTRAN, C a C++. 2 Vytvoření prostředí pro paralelní počítání Vytvořením prostředí pro paralelní počítání rozumíme: inicializaci a ukončení používání MPI; definování celkového počtu procesů nprocs, které se účastní výpočtu; definování pořadí procesu myrank. Demonstrujme si vytvoření paralelního prostředí na jednoduchém programu, který vypíše na obrazovku pořadí jednotlivých procesů. 1 1 Pokud nebude řečeno jinak, pracujeme s SPMD modelem paralelního programu: na všech uzlech se rozběhne stejná kopie programu (SP, single program), každá kopie programu pracuje s různými daty (MD, multiple data). 1
program par_env implicit none include mpif.h Budeme pouzivat MPI knihovnu integer :: ierr,nprocs,myrank call MPI_INIT(ierr) INITializuje MPI call MPI_COMM_SIZE(MPI_COMM_WORLD,nprocs,ierr) Default COMMunikator a celkovy pocet (SIZE) procesu nprocs call MPI_COMM_RANK(MPI_COMM_WORLD,myrank,ierr) Poradi (RANK) myrank ; myrank = 0, 1,..., nprocs-1 print*," Poradi procesu =",myrank call MPI_FINALIZE(ierr) Ukonci (FINALIZE) MPI end program par_env Komentář k programu: Include mpif.h říká, že budeme používat MPI knihovnu. MPI INIT(ierr) inicializuje MPI; ierr je chybová proměnná typu INTEGER (ierr = 0 když je vše v pořádku). MPI COMM SIZE(MPI COMM WORLD,nprocs,ierr) definuje celkový počet procesů nprocs, které se účastní výpočtu. MPI COMM RANK(MPI COMM WORLD,myrank,ierr) definuje pořadí procesu myrank. MPI FINALIZE(ierr) ukončí MPI. V celém programu používáme předdefinovaný (default) tzv. komunikátor MPI COMM WORLD - označení pro skupinu spolupracujících procesů. 2
3 Program typu Hello World Při učení nového programovacího jazyka se pravděpodobně každý setkal s programem, který vypíše na obrazovku pozdrav - program typu Hello World. Napišme si takovou verzi programu pomocí MPI. MPI Hello World program pošle z procesů majících pořadí myrank = 1, 2,..., nprocs 1 informaci o svém pořadí na proces s pořadím 0 a proces s pořadím 0 vytiskne tuto informaci na obrazovku. 3
program hello_world implicit none include mpif.h Budeme pouzivat MPI knihovnu integer :: STATUS(MPI_STATUS_SIZE) Pomocna promenna pouzita v MPI_RECV integer :: ierr,nprocs,myrank,tag,isource,act_proc call MPI_INIT(ierr) INITializujeme MPI call MPI_COMM_SIZE(MPI_COMM_WORLD,nprocs,ierr) Default COMMunikator a celkový pocet (SIZE) procesu nprocs call MPI_COMM_RANK(MPI_COMM_WORLD,myrank,ierr) Poradi (RANK) myrank ; myrank = 0, 1,..., nprocs-1 tag=1 if(myrank /= 0) then Ne_Mastr procesy act_proc=myrank call MPI_SEND(act_proc,1,MPI_INTEGER,0,tag,MPI_COMM_WORLD,ierr) Ne_Mastr procesy SEND info act_proc else Mastr proces do isource=1,nprocs-1 call MPI_RECV(act_proc,1,MPI_INTEGER,isource,tag,MPI_COMM_WORLD, & STATUS,ierr) Mastr proces RECV info act_proc print*," Hello World =",act_proc enddo endif call MPI_FINALIZE(ierr) Ukonci (FINALIZE) MPI end program hello_world 4
Komentář k programu: MPI SEND(...) posílá informace. MPI RECV(...) zajistí obdržení informace. 1. argument v MPI SEND/MPI RECV je posílaná/obdržená informace. 2. argument v MPI SEND/MPI RECV je velikost posílané/obdržené informace (1 pro skalár, počet prvků vektoru či matice, atd.). 3. argument v MPI SEND/MPI RECV značí MPI typ, který přibližně odpovídá typům v jazycích FORTRAN, C a C++. 4. argument v MPI SEND značí, na jaký proces se má zpráva poslat (v našem případě na proces 0). 4. argument v MPI RECV značí, z jakých procesů zpráva přichází (v našem případě z procesů 1, 2,..., nprocs 1). 5. argument v MPI SEND/MPI RECV je proměnná typu INTEGER (0-3267), která umožňuje dodatečné (pomocné) označení zprávy. Proměnná ST AT US v MPI RECV zpětně informuje MPI SEND o úspěšném doručení zprávy. 2 MPI RECV je až na ST AT US zrcadlovým obrazem MPI SEND. MPI SEND a MPI RECV jsou vzájemně synchronizované příkazy t.j. běh programu pokračuje, až když se oba příkazy dokončí. 2 Ostatní argumenty v MPI SEND/MPI RECV byly již vysvětleny. 5