Descargar la presentación
La descarga está en progreso. Por favor, espere
Publicada porRikke Mogensen Modificado hace 6 años
1
Abiadura handiko konputagailuak (top500 zerrenda).
Arkitektura Paraleloak IF - EHU 9. OpenMP eta MPI: programa paraleloak sortzeko “tresnak” (sarrera). Abiadura handiko konputagailuak (top500 zerrenda).
2
Aplikazio paraleloen programazioa
MIMD motako sistema paraleloen arkitektura bietako bat izan daiteke: memoria partekatukoa edo memoria banatukoa. Aplikazio paraleloak programatzea oso desberdina da eredu batean eta bestean.
3
Aplikazio paraleloen programazioa
Memoria partekatuko sistemetan, SMP sistemetan batik bat, OpenMP da “tresna” erabiliena. Memoria banatuko (MPP, cluster-ak) sistemen programazioa, ordea, mezu-ematearen bidez egiten da, MPI erabiliz. Beste aukera batzuk: UPC (Unified Parallel C) shrmem (Cray) Txartel grafikoak: CUDA / OpenCL
4
Aplikazio paraleloen programazioa
Earth Simulator
5
OpenMP laburpena
6
Sarrera OpenMP da gaurko estandarra memoria partekatuko aplikazio paraleloak programatzeko. Ez da programazio-lengoaia berri bat, API bat baizik (application programming interface), osagai hauekin: sasiaginduak konpiladorearentzat (C) #pragma omp <sasiagindua> liburutegi-funtzio bakan batzuk ingurune-aldagai batzuk
7
OpenMP-k erabiltzen duen programazio-eredua Fork / Join da.
Sarrera OpenMP-k erabiltzen duen programazio-eredua Fork / Join da. Une batean, hari nagusiak P hari sortzen ditu, paraleloan exekuta daitezen. hari nagusia FORK atal paraleloa JOIN hari nagusia
8
Honela bereiziko dira exekutatuko diren atazak:
Sarrera Hari guztiek kode-kopia berdina exekutatuko dute (SPMD). Hari bakoitzak identifikadore (tid) bat darama. Honela bereiziko dira exekutatuko diren atazak: if (tid == 0) then ... else ... lana banatzen duten eraikitzaile espezifikoen bidez (work sharing).
9
Sarrera Laburbilduz, programa serie batetik abiatuta, OpenMP programa paralelo bat lortzeko, honako hauek gehitu behar dira: sasiaginduak: atal paraleloak (kode errepikatua), lan-banaketa (hari bakoitzeko ataza bat) edota harien arteko sinkronizazioa adierazteko. liburutegi-funtzioak (include <omp.h>): hariak kudeatzeko edo sinkronizatzeko.
10
Adibidea main () { #pragma omp parallel private(tid) {
for (i=0; i<100000; i++) { A[i] = A[i] + 1; B = B + A[i]; } printf(“ B = %d \n”, B); #pragma omp parallel private(tid) { } tid = omp_get_thread_num(); printf (“ %d haria abiatu da \n”, tid); #pragma omp for schedule(static) reduction(+:B) if (tid==0)
11
Oinarrizko kontzeptuak
0 Prozesu paraleloak (hariak). 1 ATAL PARALELOAK. Aldagaien izaera. 2 LAN-BANAKETA. Datuak: for begiztak. Iterazioen banaketa. Funtzioak: sections / single / ... 3 SINKRONIZAZIOA. Sekzio kritikoak, sarrailak, hesiak.
12
Oinarrizko kontzeptuak
0 Hari kopurua estatikoki, ingurune-aldagai bat: > export OMP_NUM_THREADS = 10 dinamikoki, funtzio baten bidez: omp_set_num_threads (10); 0 Nor naiz / zenbat gara? tid = omp_get_thread_num(); nth = omp_get_num_threads();
13
1 ATAL PARALELOAK (parallel regions)
# pragma omp parallel [aldag,...] { kodea } Hari bakoitzean errepikatu, eta paraleloan exekutatuko den kode zatia. Atal paralelo baten aldagaiak partekatuak (shared) edo pribatuak (private) izan daitezke.
14
Atal paraleloak > Adibide sinple bat (kaixo): hesia
... #define N 12 int i, tid, nth, A[N]; main ( ) { for (i=0; i<N; i++) A[i]=0; #pragma omp parallel { nth = omp_get_num_threads (); tid = omp_get_thread_num (); printf ("tid = %d haria abian (%d hari) \n", tid, nth); A[tid] = 10 + tid; printf (" tid = %d haria bukatuta \n", tid); } for (i=0; i<N; i++) printf (“A(%d) = %d \n”, i, A[i]); private(tid,nth) shared(A) hesia
15
? Lan-banaketa: for begiztak 2 LAN-BANAKETA: begiztak
Begiztak dira paralelismoa modu “sinplean” ustiatzeko gunerik nagusiak (ale xeheko datu-paralelismoa – domain decomposition). Jakina, ez da nahikoa errepikapen hutsa. #pragma omp parallel shared(A) private(i) { for (i=0; i<10000; i++) A[i] = A[i] + 1; } ?
16
! Lan-banaketa: for begiztak Honako hau egin beharko genuke:
#pragma omp parallel shared(A) private(tid,nth, hasi,buka,i) { tid = omp_get_thread_num(); nth = omp_get_num_threads(); hasi = tid * / nth; buka = (tid+1) * / nth; for (i=hasi; i<buka; i++) A[i] = A[i] + 1; } ! Iterazioen banaketa pragma omp for sasiaginduarekin egiten da, “automatikoki”.
17
Lan-banaketa: for begiztak
#pragma omp parallel [...] { … #pragma omp for [klausulak] for (i=0; i<10000; i++) A[i] = A[i] + 1; … } aldagaien izaera iterazioen banaketa sinkronizazioa hesia
18
Lan-banaketa: for begiztak
#pragma omp parallel for private (i,j,X) for (i=0; i<N; i++) for (j=0; j<M; j++) { X = B[i][j] * B[i][j]; A[i][j] = A[i][j] + X; C[i][j] = X * 2 + 1; } for (i=0; i<N; i++) for (j=0; j<M; j++) { X = B[i][j] * B[i][j]; A[i][j] = A[i][j] + X; C[i][j] = X * 2 + 1; } Kanpo begizta exekutatuko da paraleloan, eta hariek barneko begizta exekutatuko dute. Ale “ertaineko” paralelismoa. i, j eta X aldagaiak pribatuak dira.
19
Lan-banaketa: for begiztak
for (i=0; i<N; i++) #pragma omp parallel for private (j,X) for (j=0; j<M; j++) { X = B[i][j] * B[i][j]; A[i][j] = A[i][j] + X; C[i][j] = X * 2 + 1; } for (i=0; i<N; i++) for (j=0; j<M; j++) { X = B[i][j] * B[i][j]; A[i][j] = A[i][j] + X; C[i][j] = X * 2 + 1; } Barne begizta exekutatuko da paraleloan (kanpokoa seriean). Ale xeheko paralelismoa. j eta X aldagaiak pribatuak dira.
20
Nola banatzen dira begizta baten iterazioak harien artean?
Iterazioen banaketa Nola banatzen dira begizta baten iterazioak harien artean? Begiztaren bukaeran hesi bat dagoenez, eraginkortasun-galera nabaria izango da harien lan-karga orekatuta ez badago. Schedule klausulak hainbat banaketa-estrategia adieraztea ahalbidetzen du, hala estatikoak nola dinamikoak.
21
Iterazioen banaketa > Adibide bat Gogoratu:
#pragma omp parallel for shared(A) private(i) schedule(static,2) for (i=0; i<32; i++) A[i] = A[i] + 1; tid iterazioak 0: 0,1, 8,9, 16,17, 24,25 1: 2,3, 10,11, 18,19, 26,27 2: 4,5, 12,13, 20,21, 28,29 3: 6,7, 14,15, 22,23, 30,31 Gogoratu: estatikoa kostu txikia / datuen ingurutasun ona dinamikoa kostu handiagoa / lan-karga orekatuagoa
22
Lan-banaketa: funtzioak
Funtzio-paralelismoa ere egin daiteke, sections sasiagindua erabiliz. Adibidez, #pragma omp parallel [klausulak] { #pragma omp sections [klausulak] #pragma omp section fun1(); fun2(); fun3(); } fun1 fun2 fun3 pragma omp sections
23
Lan-banaketa: funtzioak
Atal paralelo baten barruan, ataza jakin bat hari bakar bati esleitzeko, single sasiagindua erabil daiteke. Hari bakar batek exekutatuko du ataza hori, baina ez dakigu zein.
24
Harien sinkronizazioa
Harien arteko datu-dependentziak desagerrarazi ezin badira, haien exekuzioa sinkronizatu egin behar da. OpenMP-k sinkronizazio-funtzio ohikoenak eskaintzen ditu: elkarrekiko esklusioa eta gertaeren bidezko sinkronizazioa.
25
Harien sinkronizazioa
a. Sekzio kritikoak: pragma omp critical #pragma omp parallel for for (i=0; i<N; i++) { A[i] = fun(i); if (A[i]>MAX) #pragma omp critical(SMAX) { if (A[i]>MAX) MAX = A[i]; } if (A[i]<MIN) #pragma omp critical(SMIN) { if (A[i]<MIN) MIN = A[i]; } } Adibidez, bektore baten maximoa eta minimoa kalkulatzea.
26
Harien sinkronizazioa
a. Sekzio kritikoak: pragma omp atomic Sekzio kritiko berezi bat, RMW motako eragiketa sinple bat egiteko. Esaterako, #pragma omp parallel ... { ... #pragma omp atomic X = X + 1; }
27
Harien sinkronizazioa
b. Sarrailak - omp_set_lock (&S) itxaron S sarraila ireki arte; orduan, itxi sarraila atomikoki. - omp_unset_lock (&S) S sarraila ireki. - omp_test_lock (&S) S sarrailaren balioa aztertu; T/F itzultzen du.
28
Harien sinkronizazioa
> Adibide bat #pragma omp parallel private(nire_it) { omp_set_lock(&S1); nire_it = i; i = i + 1; omp_unset_lock(&S1); while (nire_it<N) A[nire_it] = A[nire_it] + 1; }
29
Harien sinkronizazioa
c. Hesiak: pragma omp barrier #pragma omp parallel private(tid) { tid = omp_get_thread_num(); A[tid] = fun(tid); #pragma omp for for (i=0; i<N; i++) B[i] = fun(A,i); for (i=0; i<N; i++) C[i] = fun(A,B,i); D[tid] = fun(tid); } #pragma omp barrier nowait
30
Laburpena Ingurune-aldagai eta funtzio batzuk (hari kopurua, identifikadoreak...) Atal paraleloak definitzeko sasiagindua #pragma omp parallel [ald…] Lana banatzeko sasiaginduak #pragma omp for [ald,sched…] #pragma omp sections [ald] Sinkronizazio-sasiaginduak eta -funtzioak #pragma omp critical [s] / atomic #pragma omp barrier sarrailak (set_lock, unset_lock, test_lock)
31
Informazio gehiago LIBURUAK WEB KONPILADOREAK
• R. Chandra et al.: Parallel Programming in OpenMP Morgan Kaufmann, 2001. WEB • (3.0 espezifikazioa, softwarea…) KONPILADOREAK • ordaintzekoak • dohain: adibidez, Intel-eko C/C++ konpiladorea, edo gcc
32
MPI laburpena
33
Sarrera Memoria partekatuko sistemetan (SMP) aukera OpenMP bada, memoria banatuko sistemak pro-gramatzeko gaurko “estandarra”, mezu-ematearen bidez, MPI da (message-passing interface). Komunikazio-funtzio multzo handi bat, prozesadoreen artean mezuak bidaltzeko. MPI-k esplizituki adierazten du prozesuen arteko komunikazioa, hau da: -- datu-mugimenduak -- sinkronizazioa
34
MPIren paralelismo-eredua SPMD da.
Komunikazio motak Bi komunikazio mota: • puntutik puntura • globala MPIren paralelismo-eredua SPMD da. if (pid == 1) BIDALI_pid2-ra else if (pid == 2) HARTU_pid1-etik Gogoratu: prozesu bakoitzak helbide-espazio propio eta independentea dauka.
35
Komunikazio moduak (1):
Komunikazio motak Komunikazio moduak (1): • sinkronoa Komunikazioa ez da gauzatzen harik eta igorlea eta hartzailea ados jartzen diren arte. • buffer baten bidez (buffered) Igorleak buffer batean uzten du mezua, eta itzultzen da. Komunikazioa hartzailea prest dagoenean gauzatzen da. Bufferra ezin da berrerabili hustu arte.
36
Komunikazio moduak (2):
Komunikazio motak Komunikazio moduak (2): • blokeakorra Itxaron egiten da komunikazioa gauzatu arte. Komunikazio sinkronoa blokeakorra da beti. Bufferren bidezkoan, bi aukerak daude. • ez blokeakorra Itzuli egiten da eta exekuzioarekin jarraitzen da. Geroago, egiaztatu egiten da komunikazioa bete den.
37
Estrategia bakoitzak abantailak eta desabantailak ditu:
Komunikazio motak Estrategia bakoitzak abantailak eta desabantailak ditu: > sinkronoa: hartzailea prest badago mezuak hartzeko, azkarragoa da (mezuaren kopia bat aurrezten dugu). Datuak trukatzeaz gain, prozesuak sinkronizatu egiten du. Adi: blokeakorra denez, litekeena da deadlock bat gertatzea! > buffered: igorlea ez da blokeatzen hartzailea prest ez badago, baina mezuaren kopia(k) egin behar dira (motelagoa da).
38
Sarrera Prozesuak (kopurua eta esleipena) estatikoki kudeatzen dira (dinamikoki kudeatzeko ere aukera dago). Prozesuek identifikadore bana daukate: pid. Exekuzio paraleloan parte hartzen duten prozesuak “komunikatzaile”-tan biltzen dira. Komunikatzaile baten prozesuak bakarrik komunika daitezke haien artean. MPI_COMM_WORLD komunikatzailea hasieran sortzen da, eta prozesu guztiak biltzen ditu.
39
Oinarrizko funtzioak 300 funtzio baino gehiagok osatzen dute MPI, baina 6 dira funtzio nagusiak: programak hasi eta bukatzeko, 2 prozesu kopurua kontrolatzeko, 2 komunikaziorako, 2 Sintaxia: MPI_Funtzioa(…)
40
1. Programen hasiera eta bukaera:
O. funtz.: Init / Finalize 1. Programen hasiera eta bukaera: > MPI_Init(&argc, &argv); > MPI_Finalize(); Bi MPI funtzio horiek dira lehena eta azkena edozein programatan.
41
2. Prozesuak identifikatzeko
O. funtz.: Comm_rank / _size 2. Prozesuak identifikatzeko > MPI_Comm_rank(comm, &pid); pid-a itzultzen du, prozesuaren identifikadorea (comm taldearen barruan). Prozesuek bi parametroren bidez identifikatzen dira: pid-a eta taldea (comm, adibidez, MPI_COMM_WORLD). > MPI_Comm_size(comm, &prk); prk itzultzen du, comm taldearen prozesu kopurua.
42
Oinarrizko funtzioak Adibide sinple bat #include <stdio.h>
#include <mpi.h> main (int argc, char *argv[]) { int pid, prk, A = 2; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &pid); MPI_Comm_size(MPI_COMM_WORLD, &prk); A = A + 1; printf(“%d proz.(%d-tik) abian. A = %d\n”, pid,prk,A); MPI_Finalize(); }
43
A 3. Mezuak bidaltzeko eta hartzeko O. funtz.: Send / Receive B
Prozesuen arteko komunikazioak bi “jokalari” behar ditu (gutxienez): igorlea eta hartzailea. Igorleak mezua bidaltzeko funtzioa exekutatuko du, eta hartzaileak mezua hartzeko funtzioa. A B bidali hartu Komunikazioa lankidetza-prozesu bat da. Bi funtzioetako bat exekutatzen ez bada, komunikazioa ez da gauzatuko (eta agian deadlock bat sortuko da!).
44
Oinarrizko funtzioa mezu bat bidaltzeko:
O. funtz.: Send / Receive Oinarrizko funtzioa mezu bat bidaltzeko: > MPI_Send(&mess, count, type, dest, tag, comm); - mezua: [mess count (tamaina), type] - hartzailea: [dest, comm (taldea)] - tag: kontrol-kode bat, tartean (mezu mota, ordena...)
45
Oinarrizko funtzioa mezu bat hartzeko:
O. funtz.: Send / Receive Oinarrizko funtzioa mezu bat hartzeko: > MPI_Recv(&mess, count, type, source, tag, comm, &status); - mezua (tokia): [mess, count, type] - igorlea: [source, comm] - tag: mezu mota... - status: hartu den mezuari buruzko kontrol-informazioa Recv blokeatu egiten da mezua hartu arte.
46
Adibidea ... #define N 10 int main (int argc, char **argv) {
int pid, npr, itur, helb, datk, tag; int i, VA[N]; MPI_Status info; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD,&pid); for (i=0;i<N;i++) VA[i] = 0; if (pid == 0) for (i=0;i<N;i++) VA[i] = i; helb = 1; tag = 0; MPI_Send(VA, N, MPI_INT, helb, tag, MPI_COMM_WORLD); } else if (pid == 1) { for (i=0;i<N;i++) printf(“%4d”,VA[i]); itur = 0; tag = 0; MPI_Recv(VA, N, MPI_INT, itur, tag, MPI_COMM_WORLD, &info); MPI_Get_count(&info, MPI_INT, &datk); printf(“Datuak pr%d-tik; tag = %d, datk = %d \n”, info.MPI_SOURCE, info.MPI_TAG, datk); for (i=0;i<datk;i++) printf(“%4d”,VA[i]); } MPI_Finalize();
47
Send / Receive gehiago Sinkronoa: Berehalakoa:
MPI_Ssend (&mes,count,datatype,dest,tag,comm); Ez du kontrola itzultzen harik eta hartzaileak mezua hartzen duen arte. Berehalakoa: MPI_Isend (...); Exekutatu ahala itzultzen da; gero, komunikazioa bete den jakin ahal izateko: MPI_Test (...) 0 (ez) edo 1 (bai) itzultzen du MPI_Wait (...) itxaron komunikazioa gauzatu arte
48
Komunikazio kolektiboak
Hainbat aplikaziotan, komunikazioa prozesu askoren artean egin behar da, batera. Komunikazioa kolektiboa da komunikatzailearen prozesu guztiek parte hartzen badute. Adibidez: broadcast bat; datuak prozesadore batetik gainerako guztietara bidaltzen dira. Banan-banan begizta baten barruan?
49
Komunikazio kolektiboak
Komunikazio kolektiboko funtzioak blokeakorrak dira. Komunikatzailearen prozesu guztiek exekutatu behar dute funtzioa. Hiru mota 1 Datu-mugimenduak 2 Talde-eragiketak 3 Sinkronizazioa
50
KK: datu-mugimenduak 1a Broadcast: datuak prozesadore batetik (root) gainerakoetara bidaltzeko. A P0 P2 P3 P1 A P0 P2 P3 P1 A > MPI_Bcast(&mess, count, type, root, comm); (gauzatze logaritmikoa, arbola bat)
51
KK: datu-mugimenduak 1b Scatter: prozesadore baten datuak guztien artean banatzeko ABCD P0 P2 P3 P1 A B C D P0 P2 P3 P1 C B D A 1c Gather: prozesadore guztietako datuak batean biltzeko A P0 P2 P3 P1 C D B A P0 P2 P3 P1 C D B ABCD
52
KK: talde-eragiketak 2. Reduce (arbola)
P0 P2 P3 P1 C D B A P0 P2 P3 P1 C D B A+B+C+D Allreduce: emaitza prozesu guztietan geratuko da (Reduce + BC)
53
KK: sinkronizazioa 3. Sinkronizazio-hesiak
Komunikatzailearen prozesu guztien arteko sinkronizazio globala. MPI_Barrier (comm); Funtzioa blokeatu egiten da, harik eta prozesu guztiak exekutatu arte.
54
Komunikazio kolektiboak
> Adibidea: V(i) = V(i) * V(j) batura = 0; for (j=0; j<N; i++) batura = batura + V[j]; for (i=0; i<N; i++) V[i] = V[i] * batura; 1. Irakurri N (pid = 0) 2. Broadcast: N/prk (bektore lokalaren tamaina) 3. Scatter: V bektorea (dagozkien zatiak) 4. Batura partzialaren kalkulua 5. Allreduce: batura partzialak (denok lortzen dute batura) 6. Kalkulu lokala: V(i) * batura 7. Gather: emaitzak 8. Inprimatu emaitzak (pid = 0)
55
Ad.: PI zenbakiaren kalkulua
#include <stdio.h> #include <mat.h> #include “mpi.h” int main (int argc, char **argv) { int pid, prk, i, n; double PI = ; double h, ×, pi_lok, pi_glob, batura; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD,&pid); MPI_Comm_size(MPI_COMM_WORLD,&prk); if (pid == 0) { printf(“ Tarte kopurua”; scanf("%d",&n); } MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); h = 1.0 / (double) n; batura = 0.0; for (i=pid; i<n; i+=prk) { x = (i + 0.5) * h; batura += 4.0 / (1.0 + x*x); } pi_lok = h * batura; MPI_Reduce(&pi_lok, &pi_glob, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); if (pid == 0) printf("pi(+/-) = %.16f, errorea = %.16f\n", pi_glob, fabs(pi_glob - PI)); MPI_Finalize(); }
56
Banaketa askekoak: MPICH / LAM
MPIren gauzatzeak Banaketa askekoak: MPICH / LAM Oro har, cluster batean MPI programa bat exekutatu baino lehen, zera behar da: - sistema paraleloa osatzen duten makinen zerrenda fitxategi batean izatea. - makina bakoitzean, komunikazioetarako erabili behar den daemon bat exekutatzea. - sortu nahi den prozesu kopurua adieraztea: mpiexec -n 8 pi
57
Informazio gehiago LIBURUAK WEB
• P. S. Pacheco: Parallel Programming with MPI. Morgan Kaufmann, 1997. • W. Groop et al.: Using MPI. Portable Parallel Programming with the Message Passing Interface (2. ed.). MIT Press, 1999. • M. Snir et al.: MPI - The complete reference (vol. 1 & 2). The MIT Press, 1998. WEB • www-unix.mcs.anl.gov/mpi/ (dena)
Presentaciones similares
© 2025 SlidePlayer.es Inc.
All rights reserved.