Nagyteljesítményű párhuzamos feldolgozás (3. ea) Szálak, OpenMP, UPC Szeberényi Imre BME IIT <szebi@iit.bme.hu> M Ű E G Y E T E M 1 7 8 2 Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 1 -
Hol tartunk? Párhuzamos gépek modelljei Flynn-féle modell (osztályozás) Idealizált párhuzamos gép modellje Programozási modellek Közös memóriás Elosztott közös memóriás Üzenetküldéses Párhuzamos gépek osztályai Vektorprocesszoros gépek Szimmetrikus multiprocesszoros (SMP) Masszívan párhuzamos (MPP) Klaszter Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 2 -
Eszközök (nyelvek) Eszközeink nem kötődnek konkrét architektúrához, de hatékonyságuk architektúrafüggő lehet. Linda Express PVM MPI Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 3 -
Párh algoritmusok készítése Számítási modell (pl. PRAM) Algoritmus működés, hatékonyság Programozási modell Konkrét feldolgozó egység (processz, taszk, szál, processzor, mag) Szisztematikus programozási módszerek (pl. PACM) Programozási minták Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 4 -
Programozási minták Single Program Multiple Data (SPMD) gyakori módszer Master-Worker (master-slave) hibatűrés, terh. Kiegyenéítés kézenfekvő Pipeline egymás után kapcsolt processzáló elemek Divide and Conquer Fork - Join Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 5 -
SPMD minta Utasítás szinten SIMD-nek felel meg. Többnyire domain dekompozícióval jön létre. Legtöbb fejlesztőrendszer/környezet/nyelv preferálja. Eddigi példák is SPMD mintára épültek. Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 6 -
Szálak A processzek memóriaterületei egymástól teljesen elkülönítettek. A szálak olyan processzek, melyeknek csak a stack területe különül el. Így lényegesen gyorsabban lehet váltani közöttük, valamint könnyebben is kommunikálnak egymással. pthread_create(), pthread_join(), pthread_exit() pthread_mutex_..., pthread_cond_... Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 7 -
pthread példa #include <stdio.h> #include <pthread.h> void* do_loop(void *id) { int i, j; float f = 0; char me = *(char *)id; for (i=0; i<10; i++) { } for (j=0; j<5000000; j++) f++; printf("thread_%c: %d\n", me, i); } pthread_exit(null); thread-et megvalósító függvény thread egyedi adata Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 8 -
pthread példa/2 int main(int argc, char* argv[]) { pthread_t thread_a, thread_b; thread leírója char a='a', b='b', c='c'; } pthread_create(&thread_a, NULL, do_loop, &a); pthread_create(&thread_b, NULL, do_loop, &b); do_loop(&c); printf("ide nem jut!\n"); return 0; megvalósító függvény egyedi paraméter Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 9 -
mutex: Kölcsönös kizárás pthtread_mutex_init pthtread_ mutex_destroy pthtread_ mutex_lock pthtread_ mutex_trylock pthtread_ mutex_unlock Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 10 -
pthread_mutex... pthread_mutex_t mutex_cnt;... pthread_mutex_init(&mutex_cnt, NULL);... pthread_mutex_lock(&mutex_cnt); // kritikus régió pthread_mutex_unlock(&mutex_cnt); Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 11 -
condition: Feltétel változó pthtread_ cond_init pthtread_ cond_destroy pthtread_ cond_wait pthtread_ cond_timedwait pthtread_ cond_signal pthtread_ cond_broadcast Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 12 -
pthread_cond pthread_mutex_t mutex_cnt; pthread_cond_t cond_cnt; pthread_mutex_init(&mutex_cnt, NULL); pthread_cond_init(&cond_cnt, NULL);... // egyik szál pthread_mutex_lock(&mutex_cnt);... // kritikus régió, várni kell valamire pthread_cond_wait(&cond_cnt, &mutex_cnt);... pthread_mutex_unlock(&mutex_cnt); Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 13 -
pthread_cond (2)...... // másik szál pthread_mutex_lock(&mutex_cnt);... // a várt esemény bekövetkezett pthread_cond_signal(&cond_cnt);... pthread_mutex_unlock(&mutex_cnt);... Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 14 -
OpenMP Nyelvi annotáció A programozó a funkcionalitásra koncentrálhat. A párhuzamosítás csak lehetőség. Shared memóriás párhuzamosítás Ipari szabvány openmp.org, computing.llnl.gov/tutorials/openmp Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 15 -
FORK JOIN FORK JOIN Végrehajtási modell Master thread Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 16 -
Shared memoria modell A szálak változókon keresztül kommunikálnak. A megosztás nyelvi szinten definiált Versenyhelyzet kialakulhat Szinkronizációs eszközök Megosztás minimalizálása Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 17 -
Szintaxis #pragma omp construct [clause [clause] ] Egy blokkra vonatkozik (egy belépés, egy kilépés) OpenMP konstrukciók típusai: Parallel regions Work sharing Data Environment Synchronization Runtime functions/environment variables Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 18 -
Parallel regions #pragma omp parallel [clause...] newline structured_block if (scalar_expression) private (list) shared (list) default (shared none) firstprivate (list) reduction (operator: list) copyin (list) num_threads (integer-expression) Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 19 -
Parallel regions példa double D[1000] = { 1, 2, 3, 4 }; #pragma omp parallel shared { private int i; double sum = 0; for (i=0; i<1000; i++) sum += D[i]; printf( Thread %d computes %f\n, omp_get_thread_num(), sum); } // annyi példányban fut, ahány thread van. Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 20 -
Work sharing Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 21 -
WS: sections #pragma omp sections [clause...] newline { #pragma omp section newline structured_block #pragma omp section newline structured_block } private (list) firstprivate (list) lastpivate (list) reduction (operator: list) nowait Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 22 -
Sections példa #pragma omp sections { #pragma omp section a = computation_1(); #pragma omp section b = computation_2(); } c = a + b; Hosszú futási idejű valami Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 23 -
WS: single #pragma omp single [clause...] newline structured_block private (list) firstprivate (list) nowait Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 24 -
Ciklus kézi párhuzamosítás for (int i=0; i<n; i++) { a[i]=b[i]+c[i]; } #pragma omp parallel { int id = omp_get_thread_num(); int nthr = omp_get_num_threads(); int istart = id*n/nthr, iend = (id+1)*n/nthr; for (int i=istart; i<iend; i++) { a[i]=b[i]+c[i]; } } Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 25 -
Automatikus párhuzamosítás #pragma omp parallel #pragma omp for schedule(static) { for (int i=0; i<n; i++) { a[i]=b[i]+c[i]; } } Csak egyszerű for ciklus lehet: 1 db int ciklusváltozó, cmp. op: <, >, <=, > Növelés/csökkentés: ++, --, értékadó op. Ciklusfüggetlen init, last, növelés Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 26 -
WS: for #pragma omp for [clause...] newline for_loop Schedule (type [,chunk) ordered private (list) firstprivate (list) lastprivate (list) shared (list) reduction (operator: list) collapse nowait Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 27 -
Párhuzamos for problémái Load balancing Egyes részek futási ideje lehet, hogy nem azonos A futási idők eltérése csak ritkán becsülhetők előre Dinamikus szétosztás kellene Granualitás A szálak létrehozása, szinkronizálása akkor is idő, ha ezt eldugja a fordító. Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 28 -
Ütemezés schedule(static [, chunksize]) Statikus kiosztás Default: azonos darabok Round-robin (több darab, mint thread esetén) schedule(dynamic [, chunksize]) Dinamikus kiosztás Default chunksize = 1 schedule(guided [, chunksize]) Dinamikus, exponenciálisan csökken Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 29 -
Granularitás #pragma omp parallel if (expression) Párhuzamosítás a feltétellel vezérelhető #pragma omp num_threads (expression) A szálak száma módosítható Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 30 -
Data Environment Osztott változók - globális változók int sum = 0; #pragma omp parallel for for (int i=0; i<n; i++) sum += i; Privát Párh. blokk auto változói Függvények auto változói Explicit privát deklaráció esetén Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 31 -
Tárolási attribútumok megadása private: Privát példány keletkezik, de nem másolódik le az eredeti adat Ugyanaz, mintha {} között lenne firstprivate: Kezdő érték lemásolódik lastprivate: Legutolsó érték visszamásolódik threadprivate: Perzisztens a párh. részek között (globális) Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 32 -
Tárolási attribútumok pl. int i; #pragma omp parallel for private(i) for (i=0; i<n; i++) { } int idx=1; int x = 10; #pragma omp parallel for #pragma omp firsprivate(x) lastprivate(idx) for (i=0; i<n; i++) { if (data[i]==x) idx = i; } Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 33 -
Tárolási attribútumok pl./2 int data[100]; #pragma omp threadprivate(data) #pragma omp parallel for copyin(data) for (int i=0; i<n; i++) data[i]++; Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 34 -
Csak skalár Redukció int sum = 0; #pragma omp parallel for reduction(+: sum) for (int i =0; i<n; j++) sum = sum+a[i]*b[i]; Másolat készül, a végén elvégzi a műveletet x op expr x++, ++x, x--, --x, op nem lehet túlterhelt Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 35 -
Szinkronizációs mechanizmusok Single/Master execution #pragma omp single #pragma omp master Critical sections, Atomic updates #pragma omp critical [name] #pragma omp atomic update_statement Csak skalár, a redukciónál megismert formában. Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 36 -
Ordered Szinkronizációs mech./2 #pragma omp ordered int vec[100]; #pragma omp parallel for ordered for (int i=0; i<100; i++) { vec[i] = 2 * vec[i]; #pragma omp ordered printf( vec[i] = %d\n, vec[i]); } Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 37 -
Barriers Szinkronizációs mech./3 #pragma omp barrier Nowait #pragma omp sections nowait Flush #pragma omp flush (list) Reduction Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 38 -
Direktívák összefoglalása Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 39 -
Kontroll funkciók omp_set_dynamic(int)/ omp_get_dynamic() omp_set_num_threads(int)/ omp_get_num_threads() OMP_NUM_THREADS env. omp_get_num_procs() omp_get_thread_num() omp_set_nested(int)/omp_get_nested() omp_in_parallel() omp_get_wtime() omp_init_lock(), omp_destroy_lock(), omp_set_lock(), omp_unset_lock(), omp_test_lock() Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 40 -
Unified Parallel C (UPC) C99 kiterjesztése Közös memóriás modell, ami képes figyelembe venni a NUMA tulajdonságokat. Gyökerei 1999-re vezethetők vissza. Szupergépeken előszeretettel támogatják. upc-lang.org, upc.lbl.gov, upc.gwu.edu/tutorials/upc-sc05.pdf Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 41 -
UPC fontosabb jellemzői Explicit párhuzamos végrehajtási modell Teljesen független szálak (thread!= OS thread) Minden szálon függetlenül teljesül a C specifikáció (sok main). Particionált globális címtér (PGAS) megosztott (shared) adat, privát adat Skalár mindig p0-ban, tömb szétosztva Szinkronizációs primitívek Runtime könyvtár scatter,gathetr, reductions, exchange,.. Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 42 -
UPC kulcsszavak MYTHREAD, THREADS shared, realaxed, strict, upc_barrier, upc_notify, upc_wait upc_forall, upc_blokcsizeof, upc_elementsizeof, upc_localsizeof, UPC_MAXB_LOCK_SIZE upc_fence, Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 43 -
Memória modellek Process/Thread Címtér Message Passing Shared Memory PGAS MPI OpenMP UPC Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. 44
Particionált globális címtér A shared tömb változók elemei elosztottan helyezkednek el a memóriában valamelyik szálhoz rendelten (affinitás). A szálhoz közelebb levő adaton hatékonyabban dolgozhat egy-egy algoritmus. shared int a[100]; // ciklikusan eloszlik upc_forall(int i = 0; i < 100; i++; &a[i]) // az adott ciklus csak ott fut, ahol az adat van Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 45 -
Affinitás és blokkméret shared [block-size] type array[n]; affinity = (i/block-size)%threads shared [3] int A[4][THREADS]; Thf: THREADS = 4 Thread 0 Thread 1 Thread 2 Thread 3 A[0][0] A[0][3] A[1][2] A[2][1] A[0][1] A[1][0] A[1][3] A[2][2] A[0][2] A[1][1] A[2][0] A[2][3] A[3][0] A[3][1] A[3][2] A[3][3] Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. 46
PI példa shared long hits[threads]; // számlálók. upc_forall (i=0; i < my_trials; i++; continue) hits[mythread] += isinside(); upc_barrier; // bevár minden szálat if (MYTHREAD == 0) // összegzés for (i = 1; i < THREADS; i++) hits[0] += hits[i]; Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 47 -
Mintapéldák para.iit.bem.hu/~szebi/para/openmp para.iit.bem.hu/~szebi/para/upc #Az upc fordító eléréséhez belépés után: module load upc Nagyteljesítményű párhuzamos feldolgozás BME-IIT Sz.I. 2017.09.27. - 48 -