23.04.2013 Views

LEKSIONE PER SISTEMET E SHPERNDARA DHE PARALELE

LEKSIONE PER SISTEMET E SHPERNDARA DHE PARALELE

LEKSIONE PER SISTEMET E SHPERNDARA DHE PARALELE

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

<strong>LEKSIONE</strong> <strong>PER</strong> <strong>SISTEMET</strong> E<br />

SH<strong>PER</strong>NDARA <strong>DHE</strong><br />

<strong>PARALELE</strong><br />

DEGA INFORMATIKE EKONOMIKE<br />

Neki Frasheri<br />

Tirane, 2012<br />

1


Table of Contents<br />

HYRJE..................................................................................................................................................3<br />

Sistemet sekuenciale dhe paralele....................................................................................................3<br />

Nevoja per perpunime paralele........................................................................................................4<br />

Perpunimi paralel i te dhenave.........................................................................................................4<br />

HYRJE NE OpenMP............................................................................................................................5<br />

ARKITEKTURAT <strong>PARALELE</strong>...........................................................................................................8<br />

Arkitektura SISD.............................................................................................................................8<br />

Arkitektura SIMD............................................................................................................................8<br />

Arkitektura GPU..............................................................................................................................9<br />

Arkitektura HyperThread...............................................................................................................11<br />

Arkitektura MIMD.........................................................................................................................11<br />

Arkitektura CPU Multi-core..........................................................................................................12<br />

Arkitektura GRID..........................................................................................................................13<br />

ARKITEKTURA E KUJTESAVE.....................................................................................................15<br />

Kategorizimi i Kujtesave...............................................................................................................15<br />

Sistemet paralele me kujtese te perbashket....................................................................................16<br />

Kujtesa ne sistemet GPU...............................................................................................................17<br />

Kujtesa e Jashtme dhe Skedaret.....................................................................................................18<br />

KOMUNIKIMI MIDIS PROCESEVE..............................................................................................20<br />

Paralelizimi i te Dhenave dhe Rasti i OpenMP.............................................................................20<br />

OpenMP.........................................................................................................................................21<br />

RPC (Remote Procedure Call).......................................................................................................21<br />

MESSAGE PASSING INTERFACE (MPI).......................................................................................25<br />

Krijimi i proceseve paralele MPI...................................................................................................26<br />

Komunikimi Midis Proceseve MPI...............................................................................................26<br />

Parametrat e Procedurave ne MPI.................................................................................................28<br />

ZHVILLIMI I PROGRAMEVE <strong>PARALELE</strong>....................................................................................32<br />

Coptimi dhe Paralelizimi i Algoritmit...........................................................................................32<br />

Kompleksiteti i Algoritmeve Paralele............................................................................................40<br />

2


HYRJE<br />

Sistemet sekuenciale dhe paralele<br />

Kompjuteri i Fon Nojman:<br />

– perbehet nga CPU dhe Kujtesa<br />

– ne Kujtese mbahet vargy i instruksioneve dhe te dhenat<br />

– cdo instruksion ne CPU vepron mbi nje te dhene nga Kujtesa<br />

– instruksionet ekzekutohen njeri pas tjetrit ~ sekuencialisht ne CPU<br />

Programimi klasik presupozon ekzekutim sekuencial te instrucksioneve.<br />

Sot procesoret kane te pakten 2 core (alias “CPU”).<br />

Programet ekzekutohen si procese te pavarur sekuenciale ne core e ndryshme.<br />

A mund te “thyhet” principi i sekuencialitetit?<br />

Pjeserisht po.<br />

Shembull:<br />

Mbledhja e dy vektoreve c[i] = a[i] + b[i]; per i=1,2,...,n<br />

Rradha e punes ne sistemin sekuencial:<br />

1. i=1 => CPU<br />

2. a[i] => CPU<br />

3. CPU + b[i] => CPU<br />

4. CPU => c[i]<br />

5. i=i+1 => CPU<br />

6. … perseritje e grupit te instruksioneve <br />

Ku: CPU ketu perfaqeson regjister ne procesor.<br />

Koha e ekzekutimit eshte T = n * DT<br />

ku DT ~ koha e ekzekutimit te grupit te instruksioneve .<br />

Veprimi i mbledhjes te dy elementeve ne pozicionin “i” eshte veprim i pavarur dhe<br />

mund te kryhet pavaresissht nga mbledhjet e tjera. Po te disponojme numer te<br />

mjaftueshem CPU-sh mund te kryejme secilen nga mbledhjet ne nje CPU te vecante dhe<br />

koha e ekzekutimit do te shkurtohej “n” here: T1 = T / n = DT<br />

3


Nevoja per perpunime paralele<br />

– modelime dhe simulime ekonomike<br />

– klimatologji: dinamika e atmosferes dhe oqeaneve<br />

– biologji: dinamika dhe bashkeveprimi i molekulave komplekse<br />

– fizike: bashkeveprimi i nje numri te madh trupash<br />

– etj...<br />

Shembull:<br />

Inversioni i anomalive te gravitetit ne gjeofizike.<br />

Matet intensiteti i gravitetit ne siperfaqen e Tokes dhe perftohet nje matrice 2D ~<br />

anomalia.<br />

Kerkohet shperndarja e densitetit te mases nentoke ~ nje matrice “prismatike” 3D qe<br />

perfaqeson “gjeoseksionin”.<br />

Problemi eshte i “keq-pozuar” - zgjidhja nuk eshte as e vetme as e qendrueshme.<br />

Ne nje sistem me 1000 procesore per nje gjeoseksion 3D me permasa 4x4x2 km i<br />

coptuar ne matricen 3D me 2,099,601 elemente qe perfqesojne kuboide me permasa<br />

50x50x50m te nentokes u deshen 27 ore llogaritje. Per te njejtin model por me kuboide<br />

me permasa 25m do te duhej nje vit llogaritjesh ne sistemin me 1000 procesore.<br />

Rendi i veprimeve eshte O(N^8), ku N eshte numri i elementeve ne nje brinje te<br />

gjeoseksionit prizmatik.<br />

Perpunimi paralel i te dhenave<br />

Konsiston ne coptimin e grupeve te veprimeve dhe ekzekutimin e tyre ne procesore / core te<br />

vecanta, dhe me pas ne integrimin e copave rezultateve ne nje te vetme. Eventualisht kjo mund te<br />

kerkoje modifikimin e algoritmit llogarites.<br />

Jo cdo algoritem pranon / mund te paralelizohet.<br />

Mundesia e paralelizimit dhe rruga per realizimin e tij varen nga:<br />

– algoritmi (mundesia e ndarjes ne “copa” paralele te pavarura)<br />

– arkitektura e bashkesise se procesoreve<br />

– arkitektura e kujteses (dhe lidhja e saj me procesoret)<br />

– gjuha e programimit<br />

Shembull:<br />

a) mbjedhja e dy vektoreve paralelizohet lehte c[i] = a[i] + b[i]<br />

4


) shuma e termave te nje vektori paralelizohet me veshtiresi S = Σ a[i]<br />

HYRJE NE OpenMP<br />

Librari me modulet per manaxhimin e thread paralele.<br />

Gjuhet e programimit C dhe FORTRAN<br />

Sistemet MS-Windows dhe Linux<br />

Kompilimi behet duke shtuar parametrin “-fopenmp”:<br />

gcc -fopenmp program.c -o program<br />

Ekzekutimi behet normalisht.<br />

Koncepti baze: paralelizimi realizohet duke krijuar (klonuar) thread paralele qe mund te<br />

ekzekutohen ne core te ndryshme (kur ka me shume thread se core kemi konkurence per kapjen e<br />

kohes te CPU duke cenuar efektin e paralelizimit).<br />

Dallimi midis “procese” dhe “thread” ne perdorimin e kujteses:<br />

– proceset perdorin hapesira vetiake te kujteses<br />

– thread ndajne te njejten hapesire kujtese<br />

Thread paralele krijohen duke “klonuar” (kujto konanden “fork” ne Linux) procesin rrenje (qe<br />

krijohet kur programi leshohet per ekzekutim):<br />

Procesi<br />

baze<br />

v<br />

v<br />

v<br />

fork<br />

w<br />

w<br />

w<br />

w<br />

w<br />

proces<br />

proces<br />

Thread<br />

paralel<br />

.<br />

.<br />

.<br />

w<br />

w<br />

w<br />

w<br />

w<br />

proces<br />

Thread<br />

paralel<br />

.<br />

.<br />

.<br />

.<br />

w<br />

w<br />

w<br />

w<br />

w<br />

thread<br />

thread<br />

thread<br />

...<br />

Thread<br />

paralel<br />

.<br />

.<br />

.<br />

.<br />

w<br />

w<br />

w<br />

w<br />

w<br />

Thread<br />

paralel<br />

.<br />

.<br />

.<br />

.<br />

w<br />

w<br />

w<br />

w<br />

w<br />

5


join<br />

v<br />

v<br />

v<br />

join<br />

.<br />

.<br />

.<br />

join<br />

.<br />

.<br />

.<br />

Ku: v ~ kod qe ekzekutohet vetem ne procesin baze (sekuencial)<br />

join<br />

.<br />

.<br />

.<br />

w ~ kodi qe ekzekutohet sekuencialisht por i perseritur ne thread paralele<br />

join<br />

.<br />

.<br />

.<br />

Strukture qe paralelizohet relativisht lehte eshte cikli “For” ne rastin kur iteracionet e tij jane te<br />

pavarur nga njeri tjetri.<br />

Shembull:<br />

Shembull:<br />

Paralelizohet lehte:<br />

for i=1 to n<br />

c[i] = a[i] + b[i]<br />

Paralelizohet me veshtiresi:<br />

for i=1 to n<br />

s = s + a[i]<br />

Ne disa raste me ndryshime te vogla iteracionet mund te behen te pavarur:<br />

Iteracione te ndervarur:<br />

Analiza e shumes te vektoreve:<br />

Kodi i shumes te dy vektoreve:<br />

for i=1 to n<br />

j = j + 5<br />

c[j] = a[j] + b[j]<br />

for i = 1 to n<br />

c[i] = a[i] + b[i]<br />

Numri i iteracioneve: n<br />

Numri i thread paralele: m<br />

Cdo thread duhet te kryeje: k = int(n/m) iteracione<br />

Iteracione te pavarur:<br />

for i=1 to n<br />

j = i * 5<br />

c[j] = a[j] + b[j]<br />

for i=1 to k<br />

thread 0 >>>>>>>>>>>>>>x>>>>>>>>>>>>>>>>>>x>>>>>>>>>>>>><br />

for i=k+1 to 2k<br />

thread 1 ..............->>>>>>>>>>>>>>>>>>-.............<br />

for i=2k+1 to 3k<br />

thread 2 ..............->>>>>>>>>>>>>>>>>>-.............<br />

. . .<br />

for i=(m-1)k+1 to n<br />

thread 3 ..............->>>>>>>>>>>>>>>>>>-.............<br />

Kodi i nevojshem per klonimin e thread dhe ribashkimin e tyre ndertohet nga kompilatori.<br />

6


Programisti e kontrollon procesin e ndertimit te kodit te paralelizueshem duke perdorur direktiven<br />

PRAGMA:<br />

Shembull:<br />

Shembull:<br />

#pragma omp parallel num_threads(m)<br />

Mbledhja e dy vektoreve<br />

#pragma omp parallel num_threads(m)<br />

for (i=0; i


ARKITEKTURAT <strong>PARALELE</strong><br />

Arkitektura SISD<br />

SISD ~ Single Instruction Single Data ~ arkitektura klasike sekuenciale:<br />

CPU<br />

RAM<br />

>>>>>>>>>>>><br />

>>>>>>>>>>>><br />

koha<br />

Ku: ~ kalimi i nje instruksioni nga RAM ne CPU<br />

~ shkembim i nje te dhene midis RAM dhe CPU<br />

Rasti i mbledhjes te dy vektoreve: c[i] = a[i] + b[i]<br />

Konsierojme problemin te thjeshtezuar:<br />

– nje instruskion mbledhjeje<br />

>>>>>>>>>>>><br />

– shume cifte te dhenash te pavarura mbi te cilat vepron instruksioni i mpledhjes<br />

>>>>>>>>>>>><br />

Per rastet e nje situate te tille per veprime elementare ne CPU, kjo e fundit eshte ndertuar sipas<br />

parimit te “konvejerit te punes” ~ pipeline / SIMD:<br />

Arkitektura SIMD<br />

SIMD ~ Single Instruction Multiple Data<br />

Arkitektura njihet dhe me emrin “vektoriale”, e specializuar per veprimet me vektoret.<br />

Ndertimi i brenshem i CPU me blloqe (koncepti i firmware ~ mikro-instruksione):<br />

IN<br />

Instruksioni ekzekutohet i “shumefishuar” si vargje mikro-instruksionesh dhe paralelisht me njeri<br />

tjetrin – mikro-instruksioni i seciles kopje te instruksionit ne nje bllok te CPU, cdo kopje e<br />

instruksiont trajton nje te dhene te veten:<br />

IN<br />

instruksioni ~ mi-1 => mi-2 => mi-3 => mi-4<br />

mi-1<br />

data4<br />

mi-2<br />

data3<br />

mi-3<br />

data2<br />

mi-4<br />

data1<br />

OUT<br />

OUT<br />

8


Figura me poshte tregon zhvendosjen e te dhenave neper blloqet e mikro-instruksioneve te CPU:<br />

Instruksioni si varg<br />

mikro-instruksionesh<br />

Koha<br />

data1 hyn ne CPU data1<br />

data2 hyn ne CPU data2 data1<br />

mi-1 mi-2 mi-3 mi-4<br />

data3 hyn ne CPU data3 data2 data1<br />

data4 hyn ne CPU data4 data3 data2 data1<br />

Procesoret Intel kane arkitekture pipeline. Optimizimi i kodit per shfrytezimin e paralelizimit mund<br />

te behet duke perdorur kompilatoret Intel.<br />

Arkitektura GPU<br />

Procesoret grafike (GPU ~ Graphic Processing Unit) te nivelit te larte NVIDIA dhe AMD<br />

RAEDON shfrytezojne konceptin SIMD per te pershpejtuar veprimet e renderizimit te imazheve ne<br />

levizje.<br />

core core core core core cache<br />

core core core core core cache<br />

core core core core core cache<br />

core core core core core cache<br />

core core core core core cache<br />

core core core core core cache<br />

Si e tille GPU mund te perdoret per llogaritje paralele sipas logjikes SIMD – i njejti kod “GPU”<br />

ekzekutohet ne secilen core te GPU me te dhena te ndryshme.<br />

Programimi behet duke perdorur zgejrimet e gjuhes C:<br />

– OpenCL<br />

– CUDA (rasti i NVIDIA)<br />

Programisti karton kodin “kernel” qe duhet te ekzekutohet ne core-t e GPU dhe duhet te parashikoje<br />

KUJTESA<br />

E<br />

<strong>PER</strong>BASHKET<br />

9


transferimin e te dhenave nga RAM ne kujtesen e GPU.<br />

Ku: ~ CPU kontrollon shkembimet midis RAM dhe GPU<br />

Shembull:<br />

~ transferim kodi dhe te dhenash midis RAM dhe GPU<br />

Mbledhja e dy vektoreve.<br />

Kodi klasik:<br />

for i = 1 to n<br />

c[i] = a[i] + b[i]<br />

Kodi “kernel” per GPU ne parim do te ishte (i thjeshtezuar):<br />

c[i] = a[i] + b[i]<br />

qe do te perseritej ne secilen core te GPU me vleren perkatese te indeksit “i” (ne kete<br />

shembull detajet e programimit te GPU nuk jane paraqitur).<br />

Ekzekutimi i kodit klasik do te kerkonte 99% te kohes te CPU, ndersa ekzekutimi me<br />

ndihmen e nje GPU me 48 core ekrkoi vetem 3% kohe te CPU.<br />

Per te punuar me GPU duhet:<br />

BUS<br />

CPU RAM CPU<br />

Kodi “kernel”<br />

Te dhenat<br />

– te instalohen gjuhet perkatese (OpenCL dhe / ose CUDA)<br />

– te programohet vecas kodi per CPU dhe vecas kodi per GPU<br />

– te parashikohen shkembimet e te dhenave midis RAM dhe GPU<br />

10


Arkitektura HyperThread<br />

Ne disa kategori procesoresh Intel eshte realizuar e ashtuquajtura teknologji hyperthread.<br />

Arkitektura e nje CPU klasike (nje core e vetme) eshte:<br />

mjedisi<br />

i<br />

thread<br />

ALU<br />

Kur thread i zene vendin njeri tjetrit ne CPU, duhet te ndrohet dhe mjedisi i therad (vlerat e<br />

regjistrave, tabelat e faqeve te kujteses etj), gje qe kerkon njefare kohe.<br />

Ne CPU hyperthread eshte shumefishuar elektronika e mjedisit te thread:<br />

mjedisi<br />

i<br />

thread<br />

ALU<br />

mjedisi<br />

i<br />

thread<br />

Ne kete menyre CPU mban njekohesisht 2 (ose me shume (?)) mjedise per thread te ndryshem,<br />

duke mundesuar pershpejtimin e shkembimit te thread ne CPU (shmanget koha e shkembimit te<br />

mjediseve). Nga pikpamja e shpejtesise te punes, nje core me dy hyperthread punon sikur te ishte<br />

“nje core e gjysem”.<br />

Arkitektura MIMD<br />

MIMD ~ Multiple Instruction Multiple Data<br />

Rasti “kalsik” i kesaj arkitekture do te ishte nje makine me shume procesore / core te lidhur njeri me<br />

tjetrin ne formen e nje matrice:<br />

11


Pergjithesisht makina te tilla jane te ralla dhe perdoren per perpunime speciale. Programimi i tyre,<br />

sistemet operative dhe gjuhet e programimit jane teper te nderlikuara.<br />

Sot perdoren gjeresisht sisteme paralele me te thjeshta – cluster me CPU te lidhura midis tyre ne nje<br />

BUS. Makina te tilla kane zakonisht disa CPU, secila me nje ose disa core:<br />

RAM<br />

CPU<br />

Rrjeti lokal i nje laboratori mund te trajtohet si nje “makine paralele” e tille ~ cluster me CPU<br />

(shiko dhe arkitekturen grid).<br />

Problemi me kete arkitekture eshte shkembimi i te dhenave midis CPU-ve. Brenda nje nyjeje<br />

CPU+RAM mund te punohet me thread paralele qe ndajne te njejten zone kujtese, ndersa<br />

shkembimi i te dhenave midis nyjeve (e thene ndryshe – midis proceseve) kerkon mekanizma te<br />

vecante. Nje i tille eshte MPI – Message Passing Interface.<br />

Zgjidhja MPI konsiston ne “klonimin” e proceseve (perfshi kujtesen), duke krijuar nga procesi baze<br />

(i startuar me fillimin e ekzekutimit te programit) nje grup procesesh analoge paralele qe<br />

ekzekutohen ne CPU te ndryshme. Programisti mund te kontrolloje rrjedhen e ekzekutimit duke<br />

mundesuar qe procese te ndryshme te ekzekutojne copa kodi te ndryshme, duke realizuar<br />

perafersisht logjiken MIMD.<br />

RAM<br />

CPU<br />

MPI eshte nje librari plotesuese per gjuhet C dhe FORTRAN, qe permban modulet e klonimit te<br />

proceseve dhe procedurat e shkembimit te mesazheve midis proceseve.<br />

Kompilimi behet me komanden “mpicc” dhe ekzekutimi me komanden “mpirun”.<br />

Arkitektura CPU Multi-core<br />

RAM<br />

CPU<br />

Arkitektura multi-core konsiston ne CPU te perbere nga disa njesi te vecanta te pavarura perpunimi,<br />

e thene ndryshe disa CPU ne nje chip te vetem:<br />

RAM<br />

CPU<br />

RAM<br />

CPU<br />

12


core core core core<br />

cache cache cache cache<br />

CACHE<br />

BUS<br />

RAM<br />

Sot shumica e PC-ve kane CPU me dy ose me shume core.<br />

Arkitektura GRID<br />

Grid eshte nje sistem paralel i perbere nga disa nyje CPU+RAM te lidhura ne rrjet lokal ~ cluster<br />

me PC. Cdo nyje / PC eshte teresisht e pavarur dhe ka sistemin e vet operativ te zakonshem (MS-<br />

Windows ose Linux). Shpesh rrjetat lokale konfigurohen te punojne si grid gjate nates. MPI mund<br />

te perdoret per komunikimin midis proceseve ne nyjet e ndryshme, por ekzekutimi i nje programi<br />

paralel ne nje cluster te tille kerkon mbeshtetjen nga middleware i nevojshem per te klonuar<br />

proceset ne makina te pavarura. Per me teper mbi grid dhe middleware perkates shiko sistemet<br />

CONDOR dhe GLOBUS.<br />

Midleueri grid duhet te zgjithe tre detyra:<br />

a) te verifikoje certifikatat e perdoruesve dhe te sistemeve qe bashkeveprojne ne grid, te monitoroje<br />

gjendjen e sistemit, te mbaje historikun e ngjarjeve dhe vellimin e puneve te kryera nga<br />

perdoruesit.<br />

b) te mare kerkesat per ekzekutim nga perdoruesit dhe, duke u bazuar ne informacionin mbi<br />

ngarkesen e castit te segementeve (cluster”) te vecanta te grid, te dergoje punet per ekzekutim ne<br />

segmentet me pak te ngarkuar.<br />

c) te mbaje regjistrin me skedaret e rezervuar ne pika te ndryshme te sistemit, te ofroje mundesine e<br />

kapjes te skedareve nga perdoruesit, dhe te sinkronizoje permbajtjen e kopjeve shumefishe.<br />

Siguria<br />

+ Monitorimi<br />

User<br />

Interface<br />

Intranet / Internet<br />

“dispecer”<br />

13


Segmentet / cluster grid perbehen nga :<br />

1. LAN<br />

2. Computer Element (CE ~ host i “dispetcerit” lokal)<br />

3. Storage Element (SE ~ sistemi qe ofron hapesire disku)<br />

4. Monitoring node (MON)<br />

5. Work Node (WN ~ kompjuterat qe ekzekutojne punet)<br />

6. Softueri:<br />

(a) Administratori i puneve (pbs, torque, maui ...)<br />

(b) Administratori i skedareve (gridftp …)<br />

(c) Sistemi i informacionit (bdii …)<br />

(d) Sistemi i monitorimit (mon ...)<br />

“Grid” i shperndare ka topologji te ngjashme si ne figure:<br />

– “dispecer” global<br />

– monitorues global<br />

– segmente grid<br />

“Dispeceri” global komunikon me nje cluster grid vetem me CE dhe SE.<br />

Siguria ne sistemet grid bazohet ne certifikatat elektronike. Cdo perdorues dhe cdo nyje kopjuterike<br />

me te drejta per shkembime me “dispetcerin” (CE, SE, MON) duhet te kete certifikaten e vet te<br />

leshuar nga autoritete CA te njohur nga sistemi.<br />

Per te shmangur perdorimin e vazhdueshem te nje certifikate, qe sjell rezikun e zberthimit te saj nga<br />

pale te treta, ndiqet praktika e perdorimit te certifikatave te perkoheshme. Me ndihmen e certifikates<br />

permanente sistemi qe do te komunikoje me dike gjeneron nje certifikate te perkoheshme (e quajtur<br />

dhe “proxy”) dhe e perdor ate per pune gjate nje sesioni brenda nje afati kohor te caktuar (zakonisht<br />

~ 24 ore).<br />

Cdo kompjuter pune (WN) mund te jete multi-core. Paralelizimi ne grid eshte i mundur kur te<br />

dhenat fillestare te aplikimit mund te coptohen dhe perpunohet ne menyre te pavarur ne WN te<br />

dnryshme, ose kur perdoret MPI qe mundeson shkembimin e te dhenave midis proceseve ne WN te<br />

ndryshme.<br />

15


ARKITEKTURA E KUJTESAVE<br />

Kategorizimi i Kujtesave<br />

Perseritje: Thread dhe Procese<br />

Nje nga dallimet midis thread dhe procese eshte puna me kujtesen:<br />

Kujtesa e perbashket RAM RAM RAM<br />

kujtese vetiake kujtese vetiake kujtese vetiake proces_0 proces_1 proces_2<br />

thread_0 thread_1 thread_2<br />

Thread ndajne te njejten zone kujtese, ndoshta duke patur dhe dicka “personale”. Thread mund te<br />

komunikojme midis tyre nepermjet kujteses kryesore te perbashket.<br />

Proceset perdorin [seksione] te vecanta kujtese. Proceset mund te komunikojne midis tyre me<br />

ndihmen e sistemit te shfrytezimit.<br />

Perfundime: Kategorizimi i kujtesave<br />

E pare ne kendveshtimin e harduerit, si thread dhe procese jane kode ne ekzekutim ne ne ndonje<br />

CPU (alias core).Komunikimi midis CPU dhe RAM behet nepermjet kujtesave cache te cdo CPU:<br />

RAM<br />

cache<br />

cache cache cache<br />

core_0 core_1 core_2<br />

Ne nje CPU mund te ndodhet nje cache e perbashket per te tera core-t dhe cdo core te kete cache e<br />

vet. Kjo logjike mund te shtrihet ne sistemet e shperndara.<br />

Si rregull ne sistemet e shperndara cdo nyje (computer node) ka RAM e vet, dhe nuk ka komunikim<br />

direkt midis RAM ne nyjet e vecanta, pervetse nepermjet sistemeve te shfrytezimit dhe midleuerit te<br />

nevojshem. Ne rastin e nje cluster me PC kemi:<br />

PC_a PC_b PC_c<br />

core_0 core_1 core_0 core_1 core_0 core_1<br />

cache cache cache cache cache cache<br />

cache cache cache<br />

RAM RAM RAM<br />

OS + Midleuer<br />

LAN<br />

16


E pare ne teresi,<br />

– cdo core ka cache e vet,<br />

– grupet “PC” me core kane kujtesa dhe cache te perbashketa<br />

– grupet “PC” me core kane RAM te perbashket<br />

Perfundimi: dallohen tre kategori kujesash:<br />

1. kujtesa e shperndare<br />

2. kujtesa e ndare/perbashket [shared]<br />

3. kujtesa cache<br />

a) vetiake e cdo core<br />

b) e perbashket si CPU<br />

Problem me kujetsen e ndare: konkurimi per kapjen e kujteses nga thread/procese konkurente (ne te<br />

njekten CPU).<br />

Ky kategorizim percakton dhe teknikat e programimit paralel (dhe ne pergjithesi te programimit te<br />

sistemeve te shperndara):<br />

1. Shkembimet midis proceseve ne CPU te ndryshme dhe kujteses te shperndare behen vetem<br />

nepermjet midleuerit - MPI<br />

2. Shkembimet midis thread ne nje CPU dhe kujteses te ndare/perbashket behen si nepermjet<br />

midleuerit MPI dhe OpenMP<br />

3. Cache kontrollohet nga hardueri ... duhet mare ne konsiderate per te patur performance ne<br />

kohe<br />

Optimizimi i punes mund te realizohet nese midis CPU perdoret MPI dhe midis core ne nje CPU<br />

perdoret OpenMP, vecanerisht nese hardueri eshte i tipit “multithread”.<br />

Sistemet paralele me kujtese te perbashket<br />

Ndersa ne sistemet cluster cdo CPU ka pak core, kemi dhe sisteme paralele te “integruara” ku<br />

shume core (qindra ...) ndajne te njejten RAM:<br />

RAM<br />

core core core core core core core core core core<br />

Ndersa ne nje cluster duhet te perdorim MPI per komunikimin midis proceseve, nje sistem te tille<br />

17


me kujetse te perbashket mund te punohet edhe vetem me OpenMP. Por platforma te tilla jane te<br />

pakta. Ne shumicen e rasteve sistemet paralele bazohen ne cluster.<br />

Kujtojme se sistemet cloud pergjithesisht realizohen ne cluster. Ne dallim nga cluster “tradicional”<br />

si grup PC i lidhur ne LAN, ne sistemet paralele te ketij lloji per lidhjen midis tyre te CPU perdoren<br />

switch me gjeresi bande disa [dhjetra] Gbps.<br />

Kujtesa ne sistemet GPU<br />

Organizimi tipik i arkitektures GPU:<br />

core core core core core core core core cache<br />

core core core core core core core core cache<br />

core core core core core core core core cache<br />

core core core core core core core core cache<br />

Cfare mund te thuhet:<br />

BUS<br />

CPU RAM<br />

Kujtesa<br />

e<br />

Perbashket<br />

• Core jane grupuar ne blloqe, cdo bllok ka kujtesen e vet (“cache”) => e vogel ...<br />

• Bashkesia e blloqeve ndan kujtesen e perbashket => e madhe ...<br />

• Kodi paralel duhet te kopjohet nga RAM ne kujtesen e GPU per tu ekzekutuar sipas SIMD<br />

neper core.<br />

• Te dhenat dhe rezultate duhet te shkembehen midis RAM dhe kujteses te GPU ...<br />

• Thread brenda nje blloku duhet te konkurojne per kapjen e cache, nderkohe qe core ne<br />

pergjithesi duhet te konkurojne per kapjen e kujteses te perbashket. Problemi eshte ne<br />

shkrim !!!<br />

Shfrytezimi efektiv i kapaciteteve paralele te GPU kerkoj jo vetem algoritmimin duke konsideruar<br />

paralelizimin SIMD, por dhe koston nga shfrytezimi i kujteses:<br />

• shkembimi i te dhenave midis RAM dhe GPU<br />

• shfrytezimi i kujteses te GPU nga thread<br />

18


Kujtesa e Jashtme dhe Skedaret<br />

Kujtesa e jashtme nenkupton disqet magnetike (Hard Disk Devices) dhe paisjet e tjera si CD dhe<br />

USB-memory-stick.<br />

Ne sistemet paralele te tipit cluster nyjet kompjuter (me Sistemin e Shfrytezimit OS dhe Sistemin e<br />

Skedareve FS vetiake) te vecanta kane disqet e tyre te vecanta dhe komunikimi me to mund te behet<br />

nepermjet NFS (Network File System).<br />

RAM RAM RAM RAM RAM RAM<br />

CPU CPU CPU CPU CPU CPU<br />

HDD HDD HDD HDD HDD HDD<br />

OS/FS OS/FS OS/FS OS/FS OS/FS OS/FS<br />

N F S<br />

L A N<br />

Pavaresisht nga shkalla e integrimit te sistemit paralel dhe perdorimi i NFS, puna me skedaret<br />

paraqet problemin e konkurences – disa thread / procese paralele punojne ne kuadrin e te njejtit<br />

algoritem per te njejtin problem dhe probabiliteti qe te lexojne dhe shkruajne ne njejtet skedare<br />

eshte i larte.<br />

Rezikshemria e kompromentimit te te dhenave nga konkurenca e pa kontrolluar varion ne varesi te<br />

menyres te kapjes te skedareve:<br />

Menyra e Kapjes N procese ne lexim<br />

N procese ne lexim<br />

1 proces ne shkrim<br />

N procese ne shkrim<br />

Rezikshmeria Nuk ka E mesme E larte<br />

Problematika Nuk ka<br />

Mund te shkaktoje<br />

prishje te sinkronizimit<br />

te punes midis<br />

proceseve<br />

Problem tjeter eshte ndarja e nje skedari ne “copa” per proceset e ndryshme paralele:<br />

Proceset mund te<br />

prishin te dhenat e njeri<br />

tjetrit<br />

Proces 0 Proces 1 Proces 2 Proces 3 Proces 4 Proces 5<br />

V V V V V V<br />

Copa I Copa II Copa III Copa IV Copa V Copa VI<br />

Skedaret vetem ne lexim mund te happen ne menyren e zakonshme, por nese proceset duhet ta<br />

19


ndajne copat e skedarit programisti duhet te parashikoje kapjen relative.<br />

Zgjidhja “universale” eshte puna konkurente me skedaret, qe nenkupton cdo proces kap ne lexim /<br />

shkrim vetem copen e tij. Kjo mund te behet me procedurat perkatese qe ofrohen nga librarite e<br />

programimit paralel.<br />

OpenMP nuk ka parashikon trajtim te konkurences per skedaret dhe pergjegjesia bije mbi<br />

programistin...<br />

MPI parashikon procedurat per konkurencen e skedareve:<br />

– skedari shikohet si bashkesi “qelizash” me ndihmen e “pamjes/maskes” (view):<br />

∙ zhvendosja ne bajte (pointer) e pamejs nga fillimi skedarit<br />

∙ tipi elementar (?) i te dhenave (etype), [variabel i thjeshte ose strukture]<br />

∙ “pamja-maske” mbi skedarin (filetype)<br />

– futet kuptimi i “tipit derivat te te dhenave” (derived data type)<br />

∙ shembull: nqs. 'x' eshte etype qe perfaqeson nje “qelize”, 'oxxooo' eshte nje tip derivat qe<br />

perfaqeson qelizen e dyte dhe te trete te nje skedari, ku 'o' perfaqeson “vrime” (qelize qe<br />

nuk konsiderohet) ~ alias “filetype”<br />

– Per tre procese “pamja” ne fillim te skedarit do te ishte (shembull):<br />

∙ (0, X, XXOOOO) ~ procesi i pare kap dy qelizat e para<br />

∙ (0, X, OOXXOO) ~ procesi i dyte kap qelizat e trete dhe katert<br />

∙ (0, X, OOOOXX) ~ procesi i trete kap qelizat e peste dhe gjashte<br />

∙ Me tej pamja mund te zhvendoset duke avancuar pointer ne fillimin e grupit te dyte te<br />

qelizave, respektivisht per secilin proces:<br />

(sizeof(XXXXXX), X, XXOOOO)<br />

(sizeof(XXXXXX), X, OOXXOO)<br />

(sizeof(XXXXXX), X, OOOOXX)<br />

∙ Procesi i pare e shikon skedarin si:<br />

XXOOOO XXOOOO XXOOOO XXOOOO ...<br />

∙ Procesi i dyte e shikon skedarin si:<br />

OOXXOO OOXXOO OOXXOO OOXXOO ...<br />

∙ Procesi i trete e shikon skedarin si:<br />

OOOOXX OOOOXX OOOOXX OOOOXX ...<br />

– cdo proces punon me “qelizen” e vet duke perdorur funksionet specifike te MPI:<br />

∙ MPI_File_Open<br />

∙ MPI_File_Write<br />

∙ MPI_File_Read<br />

∙ MPI_File_Close<br />

20


KOMUNIKIMI MIDIS PROCESEVE<br />

Paralelizimi i te Dhenave dhe Rasti i OpenMP<br />

Tre kategori problemesh:<br />

1. Paralelizimi i plote<br />

Te dhenat fillestare mund te perpunohen teresisht vecas.<br />

Shembull: mbledhja e dy vektoreve<br />

c[i] = a[i] + b[i]<br />

2. Paralelizimi i pjesshem<br />

Bashkesia {i=1,...,n} mund te ndahet ne copa te pavarura {{i=ns,nt}}<br />

Rezultati final meret nga bashkimi mekanik i copave.<br />

Perpunimi mund te behet ne nje bashkesi procesesh paralele qe kryejne te njejten<br />

skeme llogaritjesh, pa nevoje nderkomunikimi (per shkak llogaritjesh) midis tyre.<br />

Llogaritjet mund te kryhen ne grup kompjuterash te pavarur, duke ndare punen<br />

manualisht ose me ndihmen e nje midleware. Tipike ne sistemet cluster / grid.<br />

Te dhenat mund te coptohen ne copa te pavarura gjate perpunimit dhe keto copa mund te<br />

perpunohen ne paralel.<br />

Shembull: shuma e elementeve te nje vektori<br />

n<br />

S = Σ1 a[i]<br />

3. Paralelizimi i veshtire<br />

nt<br />

Mund te ndahet ne copa te pavarura { S = Σns<br />

duhet te shumohen rezultatet nga copat paralele.<br />

a[i] } por per rezultatin final<br />

Perpunimi mund te behet ne nje bashkesi procesesh paralele qe kryejne te njejten<br />

skeme llogaritjesh, por duhet realizuar nderkomunikimi midis tyre per<br />

shperndarjen dhe grumbullimin e rezultateve te pjeseshme.<br />

Llogaritjet mund te kryhen ne nje kompjuter multi-procesor duke perdorur<br />

OpenMP ose ne nje cluster-grid duke perdorur MPI.<br />

Te dhenat pjeserisht mund te perpunohen pavaresisht nga njera tjetra nga procese te vecante<br />

qe kryejne detyra te ndryshme (skema logaritese te ndryshme) dhe kane nevoje per<br />

nderkomunikim te rastit midis tyre.<br />

Llogaritjet mund te kryhen me perdorimin e MPI, RPC (Remote Procedure Calls) ose duke<br />

21


OpenMP<br />

programuar direkt ne rrjet me socket.<br />

Eshte teknike e thejshte paralelizimi qe mund te ndaje perpunimin e te dhenave (konkretisht nje<br />

cikel for) ne copa qe realizohen nga thread paralele.<br />

Normalisht cdo thread kryen te njejten skeme llogaritese por me te dhena te ndryshme. Megjithate<br />

duke perdorur funksionin omp_get_thread_num() programisti mund te kape numrin rendor te<br />

thread dhe te parashikoje ndryshime te skemes llogaritese ne thread te vecante.<br />

Nderkomunikimi midis thread i mundshem vetem nepermjet ndarjes te te dhenave (fillestare ose<br />

rezultate te pjeseshme) ne kujtesen e perbashket (shared). Programisti duhet te kujdeset per<br />

konkurencen e thread ne kapjen e kujteses per shkrim per te shmangur perplasjet apo bllokimet<br />

reciproke.<br />

RPC (Remote Procedure Call)<br />

RPC eshte me e gjere se kuadri i programimit paralel dhe mundeson zhvillimin e aplikimeve te<br />

shperndara (ku copat e ndryshme te aplikimit mund te ekzekutohen edhe paralelisht) duke zgjeruar<br />

kuptimin e thirrjes te procedurave nga brenda nje sistemi operativ (rasti klasik) midis sistemeve<br />

operative te ndryshme mbi nje rrjet (rasti i shperndare - “thirrje ne distance:<br />

22


Per realizimin e thirrjes te nje procedure ne distance veprohet sipas parimit “klient – server”.<br />

Procesi ne makinen A (klienti) kerkon te therrase nje procedure ne makinen B (serveri).<br />

Qe te mund te behet nje gje e tille duhet:<br />

a. Ne makinen klient A programi qe kerkon thirrjen duhet te kete te inkorporuar (gjate<br />

kompilimit+lidhjes) procedurat e RPC per thirrje ne distance, konkretisht rpc_call(), ku si<br />

parameter jepen identifikuesi i procedures qe duhet thirrur ne makinen server B dhe te dhenat e<br />

nevojshme. Programisti i programit klient nuk merret me detajet si realizohet thirrja.<br />

b. Ne makinen server B duhet te jete aktiv sherbimi RPC qe pret thirrjet nga distanca, organizon<br />

realizimin e tyre ne lokal dhe dergimin e rezultateve ne makinen klient.<br />

Per te siguruar pavresine e sistemit RPC nga shumellojshmeria e procedurave, thirrja ne makinen<br />

klient “lehtesohet” nepermjet nje cope kodi stub klient qe pergatit thirrjen ne varesi te detajeve te<br />

procedures qe thirret. Ne makinen server sherbimi RPC ndihmohet nga nje tjeter stub server qe<br />

merret me detajet e thirrjes te procedures konkrete.<br />

Praktikisht ne te tre makinat ku behet:<br />

– zhvillimi i aplikimit<br />

– ekzekutimi i programit klient<br />

– ekzekutimi i procedurave te thirrura nga distanca<br />

duhet te jete instaluar paketa perkatese e softuerit RPC.<br />

Procedurat RPC “parakompilohen” me ndihmen e komandes rpcgen, e cila krijon kater skedare<br />

ne gjuhen C:<br />

rpcgen rpcprog.x<br />

– rpcprog_clnt.c ~ kodi i stub klient<br />

– rpcprog_svc.c ~ kodi i stub server<br />

– rpcprog_xdr.c ~ kodi per eXxternal Data Representation<br />

– rpcprog.h ~ kodi header perkates<br />

Keto skedare perfshihen ne kompilimin e aplikimit.<br />

RPC eshte e pavarur nga lloji i platformes harduer dhe softuer te makinave klient dhe server. Kjo<br />

gje mundeson bashkeveprimin e sistemeve te ndryshme ne rrjet, nderkohe qe vete puna e RPC<br />

nderlikohet ngaqe duhet te kujdeset per formatet e te dhenave (qe eventualisht mund te jene te<br />

ndryshme ne makinat A dhe B).<br />

Procedurat RPC ne makinen server duhet te “regjistrohen” qe te njihen dhe te mund te aktivizohen<br />

nga sherbimi RPC me ndihmen e procedures rpc_reg(). Ekziston edhe nje numer procedurash te<br />

23


gatshme (te regjistruara) qe ndodhen ne librarine librpcsvc.<br />

Thirrja e nje procedure ne distance behet me proceduren rpc_call(), qe ka nente parametra:<br />

int rpc_call<br />

(<br />

)<br />

char *host, // server name<br />

u_long prognum, // numri i procedures ne sever<br />

u_long versnum, // versioni i serverit<br />

xdrproc_t inproc, // filtri XDR per kodimin e argumentave<br />

char *in, // pointer per argumentat<br />

xdrproc_t outproc, // filtri XDR per kodimin e rezultateve<br />

char *out, // adresa ku do te vendosen rezultatet<br />

char *nettype, // lloji i transportit ne rrjet<br />

Nga nje interpretim i kuptimit te prametrave, cdo procedure e PRC identifikohet me nje<br />

numer ne server:<br />

ne grupe 0x20000000 sipas skemes:<br />

0x0 - 0x1fffffff ~ paracaktuar nga IANA<br />

0x20000000 - 0x3fffffff ~ percaktohet / propozohet nga perdoruesit<br />

0x40000000 - 0x5fffffff ~ transient<br />

0x60000000 – 0x........ ~ e rezervuar<br />

Ka dhe disa procedura RPC klient te gatshme, qe mund te thirren pa ndihmen e rpc_call:<br />

Routine Description<br />

rnusers Return number of users on remote machine<br />

rusers Return information about users on remote machine<br />

havedisk Determine if remote machine has disk<br />

rstats Get performance data from remote kernel<br />

rwall Write to specified remote machines<br />

… …<br />

Disa procedura te tjera si ether(), mount(), rquota(), spray() nuk gjenden ne<br />

librarite e gatshme por kane numrat perkates te paracektuar. Nje liste e pjesshme e procedurave<br />

RPC te “para-numeruara” eshte:<br />

RPC Number Program Description<br />

100000 PMAPPROG port mapper<br />

100001 RSTATPROG remote stats<br />

100002 RUSERSPROG remote users<br />

100003 NFSPROG network file system<br />

24


100004 YPPROG yellow pages<br />

… … …<br />

Ne transmetimin e te dhenave (argumenta dhe rezultate) RPC perdor nje format standard te pavarur<br />

nga platformat External Data Representation (XDR). Te dhenat “serializohen” ne formatin XDR<br />

para dergimit dhe “deserializohen” ne marrje, veprime qe kryhen nga nga stub perkates. Te dhenat<br />

elementare serializohen ne 4 bajt pavaresisht nga tipi i tyre ne makinen konkrete. Tipet baze jane:<br />

xdr_int() xdr_u_int() xdr_enum()<br />

xdr_long() xdr_u_long() xdr_bool()<br />

xdr_short() xdr_u_short() xdr_wrapstring()<br />

xdr_char() xdr_u_char()<br />

si dhe “blloqet parafabrikuese”:<br />

xdr_array() xdr_bytes() xdr_reference()<br />

xdr_vector() xdr_union() xdr_pointer()<br />

xdr_string() xdr_opaque()<br />

Programisti gjate zhvillimit te nje aplikimi qe perdor RPC duhet:<br />

– harton kodin standard ne C per aplikimin duke parashikuar thirrjet e procedurave RPC<br />

– harton kodin specifik RPC dhe e parakompilon me rpcgen<br />

∙ percakton tipet e te dhenave argument dhe rezultat per procedurat RPC<br />

∙ percakton numrat e procedurave RPC ne segmentin e rezervuar per perdoruesit<br />

– bashkon kodin standard C me skedaret e prodhuar nga rpcgen<br />

– kompilon kodin e bashkuar<br />

Protokolli RPC eshte percaktuar nga IETF fillimisht ne RFC1831 ne 1995 (versioni 1) dhe<br />

modifikuar me RFC5531 [http://tools.ietf.org/html/rfc5531] ne 2009 (versioni 2). Perdoruesit mund<br />

te aplikojne tek IANA per “zyrtarizimin” e numrave te procedurave RPC vetiake.<br />

Shenim:<br />

…<br />

• IANA eshte “Internet Assigned Numbers Authority” [http://www.iana.org/] dhe administron<br />

klasat e numrave IP, serverat rrenje te sistemit DNS dhe protokollet.<br />

• IETF eshte “Internet Engineering Task Force” [http://www.ietf.org/] dhe perpunon<br />

standardet dhe specifikimet e protokolleve te Internetit.<br />

25


MESSAGE PASSING INTERFACE (MPI)<br />

Behet fjale per “klonimin” e nje processi ne disa procese paralele, gje qe lejon kryerjen e<br />

llogaritjeve paralele ne disa CPU. Teknologjia MPI realizon “klonimin” dhe komunikimin midis<br />

proceseve. E ekzekutuar ne nje makine (nje sistem shfrytezimi i vetem), MPI mundeson<br />

shfrytezimin paralel te disa core te CPU. Ndersa ne rast perdorimi ne cluster do te duhet dhe nje<br />

middleware “dispetcer” per te shperndare proceset e klonuara ne makina te ndryshme, zgjidhje qe<br />

perdoret ne sistemet grid.<br />

Krahasuar me OpenMP, kjo e fundit punon me thread paralele qe ndajne te njejten hapesire kujtese<br />

(klonimi konsiston ne shumefishimin e PCB dhe ndoshta te ndonje cope kujtese per variabla<br />

private). Klonimi iproceseve nenkupton shumefishimin e gjithe hapesires te kujteses qe ze procesi<br />

baze, gje qe kerkon hapesire kujtese dhe kohe pune te sistemit. Per kete aresye paralelizimi me<br />

OpenMP mund te “coptohet” gjate kodit, ndersa ai me MPI eshte mire te behet ne fillim te procesit<br />

baze. Ne rastin e MPI duhet te perdoret identifikimi i proceseve per te kontrolluar kush nga proceset<br />

do te kryeje llogaritje paralele e kush sekuenciale.<br />

Per krahasim jepet figura e meposhtme:<br />

ku:<br />

T0 T1 T2 T3 T4 T5 P0 P1 P2 P3 P4 P5<br />

Thread / proces baze<br />

Perpunim paralel<br />

26


Krijimi i proceseve paralele MPI<br />

Si rregull, klonimi i proceseve ne MPI behet ne fillim te procesit baze duke thirrur proceduren:<br />

MPI_Init (&argc,&argv)<br />

Kjo procedure thirret vetem nje here dhe para thirrjes te procedurave te tjera te MPI. Dy argumentat<br />

sherbejne per te derguar ne proceset e klonuar vlerat e parametrave te ekzekutimit te programit.<br />

Ne fund te punes ne te tere proceset duhet te ekzekutohet thirrja e procedures MPI_Finalize().<br />

Numri identifikues i proceseve paralele eshte i rendesishem per te dalluar segmentet e kodit<br />

sekuencial nga ato paralele. Per me teper numri i proceseve paralele percaktohet ne komanden e<br />

ekzekutimit te programit (ndryshe nga OpenMP ku ky numer vendoset ne direktiven #pragma ne<br />

kodin e programit). Per keto aresye si rregull pas thirrjes te MPI_Init perdoren dy procedura te<br />

tjeraMPI:<br />

ku:<br />

MPI_Comm_size (comm,&size)<br />

MPI_Comm_rank (comm,&rank)<br />

– size ~ numri i proceseve paralele<br />

– rank ~ numri identifikues i procesit konkret (duke filluar nga zero)<br />

– comm ~ i ashtuquajturi “communicator”. Ne MPI proceset paralele mund te grupohen dhe<br />

te komunikojne brenda grupeve. Per kete qellim perdoret identifikuesi i communicator. Ne<br />

do te kufizohemi ne rastin klasik me nje communicator MPI_COMM_WORLD.<br />

Me tej, midis thirrjeve te procedurave te fillimit dhe mbarimit te sesionit MPI, programisti mund te<br />

perdore rankun e proceseve per te diferencuar punen qe do te kryejne (duke ndare pjeset<br />

sekuenciale te kodit nga ato paralele); si dhe procedurat e komunikimit midis proceseve per<br />

shkembimin e te dhenave ndermjetese gjate llogaritjeve dhe per te sinkronizuar veprimet midis<br />

proceseve paralele.<br />

Komunikimi Midis Proceseve MPI<br />

Komunikimi midis proceseve behet me nderhyrjen e sistemit te shfrytezimit (dhe middleware nese<br />

eshte edhe ky funskional). Mesazhet nga buffer i aplikimit – dhenesi – depozitohen ne buffer te<br />

sistemit dhe prej andej kapen nga marresi kur ky i fundit therret proceduren perkatese (qe kryen<br />

transferimin nga buffer i sistemit ne ate te aplikimit):<br />

27


Procesi A SISTEMI Procesi B<br />

MPI_Send<br />

(buffer)<br />

buffer<br />

Procedurat tipike te komunikimit midis proceseve kategorizohen sipas tabeles:<br />

bllokuese<br />

jo-bllokuese<br />

asinkrone MPI_Send<br />

MPI_Recv<br />

sinkrone MPI_Ssend<br />

MPI_Recv<br />

asinkrone MPI_Isend<br />

MPI_Irecv<br />

proces – me – proces<br />

(point-to-point)<br />

sinkrone MPI_Issend + MPI_Wait / MPI_Test<br />

MPI_Irecv<br />

(buffer)<br />

MPI_Recv<br />

komunikim ne grup<br />

(collective)<br />

MPI_Bcast<br />

MPI_Scatter<br />

MPI_Gather<br />

MPI_Barrier<br />

MPI_Reduce<br />

Klasifikimi “bllokues / jo-bllokues” ka te beje me cfare ndodh kur nje proces dergon nje mesazh:<br />

“bllokohet” deri sa te transferohet mesazhi ne buffer te sistemit, apo “nuk bllokohet” pavaresisht<br />

nese mesazhi eshte bere ky transferim.<br />

Klasifikimi “asinkron / sinkron” ka te beje me me cfare ndodh kur nje proces dergon nje mesazh:<br />

bllokohet (sinkrone)deri sa te konfirmohet marrja apo vazhdon punen (asinkrone) me te dale<br />

mesazhi nga buffer i vet drejt atij te sistemit. Bllokimi sinkron ben sinkronizim midis proceseve.<br />

Ne kategorine e komunikimeve ne grup MPI_Barrier eshte e dedikuar per sinkronizimin.<br />

Procedurat si MPI_Bcast,MPI_Scatter,MPI_Gather mund te jene sinkronizuese ose jo ne<br />

varesi te librarise MPI konkrete, Pergjithesisht bllokimi he sinkronizimi mund te kene specifika te<br />

vecanta ne librari MPI te dnryshme.<br />

Procedurat e tipit MPI_Send dhe MPI_Recv sherbejne per dergimin dhe marjen e mesazhit nga<br />

nje proces tek nje tjeter. Procedura MPI_Bcast mundeson dergimin e nje mesazhi nga nje proces<br />

tek gjithe proceset e tjere te grupit. Cifti i procedurave MPI_Scatter dhe MPI_Gather<br />

sherbejne per coptimin e nje array (bashkesi te dhenash – vektor, matrice, string etj.) midis<br />

proceseve te grupit, dhe ribashkimin e saj; keto jane procedura tipike per coptimin e te dhenave per<br />

perpunim paralel ne nje grup procesesh paralele. MPI_Reduce bashkon grupe te dhenash duke<br />

28


kryer veprime me elementet korespondues (shiko specifikimin me poshte)<br />

Parametrat e Procedurave ne MPI<br />

Dallojme disa raste komunikimi.<br />

ku:<br />

ku:<br />

ku:<br />

ku:<br />

MPI_Barrier (comm)<br />

– comm ~ communicator<br />

MPI_Bcast (*buffer, count, datatype, root, comm)<br />

– buffer ~ pointer i buffer me te dhena<br />

– count ~ numri i elementeve ne buffer<br />

– datatype ~ tipi i te elementeve ne buffer<br />

– root ~ ranku i procesit dergues<br />

– comm ~ communicator<br />

MPI_Send (&bufer, count, datatype, destination, tag, comm)<br />

– buffer ~ pointer i buffer me te dhena<br />

– count ~ numri i elementeve ne buffer<br />

– datatype ~ tipi i te elementeve ne buffer<br />

– denstination ~ ranku i procesit marres<br />

– tag ~ numer natyral per identifikimin e mesazhit<br />

– comm ~ communicator<br />

MPI_Recv (&buffer,count,datatype,source,tag,comm,&status)<br />

– buffer ~ pointer i buffer me te dhena<br />

– count ~ numri i elementeve ne buffer<br />

– datatype ~ tipi i te elementeve ne buffer<br />

– source ~ ranku i procesit dergues<br />

– tag ~ numer natyral per identifikimin e mesazhit<br />

– comm ~ communicator<br />

– status ~ strukture e perbere nga rank dhe tag {MPI_Status.MPI_SOURCE,<br />

MPI_Status.MPI_TAG)<br />

Procedurat MPI_Scatter, MPI_Gather bazohen tek coptimi i nje bashkesi te dhenash dhe<br />

29


shperndarja e copave ne procese sipas skemes 1 n :<br />

P0 P1 P2 P3 P4<br />

b0 = a0 b0 = a3 b0 = a6 b0 = a9 b0 = a12<br />

b1 = a1 b2 = a4 b1 = a7 b1 = a10 b1 = a13<br />

b2 = a2 b2 = a5 b2 = a8 b2 = a11 b2 = a14<br />

a0<br />

a1<br />

a2<br />

a3<br />

a4<br />

a5<br />

a6<br />

a7<br />

a8<br />

a9<br />

a10<br />

a11<br />

a12<br />

a13<br />

a14<br />

Ndryshe vepron MPI_Reduce:<br />

P0 P1 P2 P3 P4<br />

b0 b0 b0 b0 b0<br />

b1 b2 b1 b1 b1<br />

b2 b2 b2 b2 b2<br />

a0=@b0<br />

a1=@b1<br />

a2=@b2<br />

ku '@' simbolizon kombinimin e gjithe elementeve bi sipas nje veprimi '@', shembull ai = Σ bi<br />

30


ku:<br />

ku:<br />

ku:<br />

MPI_Scatter ( &sendbuf,sendcount,sendtype,<br />

&recvbuf,recvcount,recvtype,root,comm)<br />

– sendbuf ~ pointer i buffer me te dhenat qe dergohen (ex. &A[rank*count])<br />

– sendcount ~ numri i elementeve qe dergohen<br />

– sendtype ~ tipi i te elementeve qe dergohen<br />

– recvbuf ~ pointer i buffer me te dhenat qe merren<br />

– recvcount ~ numri i elementeve qe merren<br />

– recvtype ~ tipi i te elementeve qe merren<br />

– root ~ ranku i procesit dergues<br />

– comm ~ communicator<br />

MPI_Gather ( &sendbuf,sendcount,sendtype,<br />

&recvbuf,recvcount,recvtype,root,comm)<br />

– sendbuf ~ pointer i buffer me te dhenat qe dergohen<br />

– sendcount ~ numri i elementeve qe dergohen<br />

– sendtype ~ tipi i te elementeve qe dergohen<br />

– recvbuf ~ pointer i buffer me te dhenat e plota (ex. &A[0])<br />

– recvcount ~ numri i elementeve qe merren<br />

– recvtype ~ tipi i te elementeve qe merren<br />

– root ~ ranku i procesit marres<br />

– comm ~ communicator<br />

MPI_Reduce (&sendbuf,&recvbuf,count,datatype,oper,root,comm)<br />

– sendbuf ~ pointer i buffer me te dhenat qe dergohen (ex. &A[rank*count])<br />

– recvbuf ~ pointer i buffer me te dhenat qe merren<br />

– count ~ numri i elementeve qe merren<br />

– datatype ~ tipi i te elementeve qe dergohen<br />

– oper ~ tipi i veprimit (MPI_MIN, MPI_MAX, MPI_SUM, MPI_PROD, … )<br />

– root ~ ranku i procesit marres<br />

– comm ~ communicator<br />

Procedura te tjera si MPI_Allgather, MPI_Allreduce kryejne veprimet perkatese por sipas<br />

skemes n n.<br />

MPI_Allgather(&sendbuf,sendcnt,sendtyp,&recbuf,reccnt,rectyp,comm)<br />

MPI_Allreduce (&sendbuf,&recvbuf,count,datatype,oper,comm)<br />

Sic vihet re, ne keto raste mungon ranku i procesit rrenje (root) qe shperndan ose mbledh te dhenat.<br />

Me interes eshte dhe procedura e leximit te ores te sistemit, qe lejon te vleresohet koha e<br />

llogaritjeve (walltime) :<br />

31


double start_time, end_time, exe_time;<br />

start_time = MPI_Wtime();<br />

.<br />

.<br />

.<br />

end_time = MPI_Wtime();<br />

exe_time = end_time – start_time;<br />

Walltime eshte koha nga fillimi i ekzekutimit te nje cope kode deri ne mbarim, duke eprfshire dhe<br />

intervalet e pritjes (koha ne gjendjet GATI dhe PRITJE te procesit). Gjetja e kohet neto te<br />

ekzekutimit, kohes te punes te sistemit per llogari te procesit dhe perqindjen e punes te CPU per<br />

procesin mund te behet (ne sistemet Linux) duke kryer ekzekutimin nepermjet komandes<br />

/usr/bin/time:<br />

(/usr/bin/time ./program … ) 1>time.out 2>time.out<br />

(/usr/bin/time mpirun ./program … ) 1>time.out 2>time.out<br />

rezultati i te ciles ne skedarin tekst “time.out” ka trajten:<br />

ku:<br />

96.15 user 340.36 system 0:08.67 elapsed 5029% CPU<br />

(0avgtext+0avgdata 412352maxresident)k<br />

0inputs+48outputs (0major+2334673minor)pagefaults 0swaps<br />

– user ~ koha neto shumore e ekzekutimit te grupit te proceseve paralele<br />

– system ~ koha neto shumore e punes te sistemit<br />

– elapsed ~ koha nga fillimi i ekzekutimit te programit ne mbarimin e tij e shprehur ne<br />

[[ore:]minuta:]sekonda<br />

– CPU ~ perqindja shumore e punes e cores te CPU per grupin e proceseve paralele<br />

Koha mesatare e nje thread / proces gjendet si raport i kohes “user” me numrin e proceseve.<br />

Perqindja e punes e nje core te CPU gjendet si raport i CPU% me numrin e cores.<br />

32


ZHVILLIMI I PROGRAMEVE <strong>PARALELE</strong><br />

Coptimi dhe Paralelizimi i Algoritmit<br />

Programet paralele ofrojne efektivitetin maksimal ne kohe kur paralelizimi i algoritmit behet ne<br />

perputhje me topologjine e harduerit paralel ku do te ekzekutohet programi. Efektiviteti kushetzohet<br />

nga disa faktore qe lidhen me konkurencen misis proceseve paralele:<br />

– koha e CPU (nese procese me shume se core)<br />

– kapja e BUS per komunikim me njesite e tjera te harduerit<br />

– puna me kujtesen cache per cores qe e kane te perbashket (kapja dhe permbajtja)<br />

– puna me kujtesen e ndare<br />

– puna me kujtesat e jashtme<br />

– puna me kontrolloret e rrjetit<br />

– etj.<br />

Ne parim mund te dallohen kater topologji sistemesh paralele:<br />

1. vektor (linear array) procesoresh<br />

2. Peme binare procesoresh<br />

3. matrice (two-dimensional mesh) procesoresh<br />

4. bashkesi procesoresh me variabla te ndare (shared)<br />

Karaketrizimi i topologjive per nje grup me p procesore behet me parametrat e perkufizuar si:<br />

– diametri ~ me e gjata nga distancat me te shkurtra midis dy procesoreve<br />

– grada maksimale e nyjes (maximum node degree) ~ maksimumi i kanaleve te nder-<br />

komunikimit te nje procesori me procesoret e tjere<br />

– W(p) ~ numri total i veprimeve elementare te kryer nga p procesoret (puna / energjia<br />

kompjuterike)<br />

– T(p) ~ koha e ekzekutimit me p procesore<br />

– T(1) = W(1) dhe T(p) ≤ W(p)<br />

– Pershpejtimi S(p) = T(1) / T(p)<br />

– Eficensa E(p ) = T(1) / (p*T(p))<br />

33


– “bolleku” (redundancy) R(p) = W(p) / W(1)<br />

– Perdorimi U(p) = W(p) / (p*T(p))<br />

– Cilesia Q(p) = T^3(1) / (p*T^2(p)*W(p))<br />

Shembull: shuma e 16 numrave ne topologji paralele binare me 8 procesore:<br />

T(1) = W(1) = 15<br />

W(8) = 15 T(8) = 4 E(8) = 15/(8 × 4) = 47%<br />

S(8) = 15/4 = 3.75 R(8) = 15/15 = 1 Q(8) = 1.76<br />

Eficensa e ulet eshte rezultat i munegses te paralelizimit afer rrenjes te pemes (fig.)<br />

Po te llogariten si veprim elementar edhe transferimet (shigjetat ne figure) merret:<br />

W(8) = 22 T(8) = 7 E(8) = 15/(8*7) = 27%<br />

S(8) = 15/7 = 2.14 R(8) = 22/15 = 1.47 Q(8) = 0.39<br />

34


Topologjia paralele vektor<br />

Shembull i topologjise paralele vektor jepet ne figure:<br />

Diametri i nje vektori prej p procesoresh eshte D = p – 1 dhe shkalla maksimale e nyjeve d = 2.<br />

Krahasuar me topologjine tipike vektor, topologjia e modifikuar “unaze” (ring) ka D = [p/2] .<br />

Topologjia paralele peme binare<br />

Shembull i topologjise paralele binare jepet ne figure (kujto vetite e pemeve “pemet e balancuara”,<br />

“pemet komplete” etj.):<br />

Per topologjine peme binare grada e nyjeve eshte d = 3, ndersa diametri varet nga tipi i pemes:<br />

– pema e komplete D = 2 log2 (p + 1) – 2<br />

– pema e balancuar D = 2⎣log2 p ⎦ | 2⎣log2 p ⎦ – 1 ne varesi te nivelit te gjetheve<br />

35


Topologjia paralele matrice eshte si ne figure (rasti i thjeshte dhe ai toroidal)<br />

Diametri i topologjise matrice me p = r*q procesore eshte D = D = r + q – 2 dhe minimizohet ne<br />

rastin e matricave katrore D = 2 r – 2. Ne rastin e matrices toroidale D = r/2 + q/2, ndersa grada e<br />

nyjeve ne te dy rastet eshte d = 4.<br />

Topologjia me kujtese te ndare mund te modelohet si nje graf i plote (ku cdo nyje lidhet me tere<br />

nyjet e tjera):<br />

36


Ne topologjite graf i plote me p procesore grada e nyjeve eshte d = p – 1 ndersa diametri D = 1.<br />

Me gjithe perparesite teorike, sistemi paralel me topologji graf i plote eshte shume i veshtire per tu<br />

realizuar.<br />

Shembull – renditje ne topologji vektoriale:<br />

37


Hapat per daljen e rezultateve nuk jane paraqitur. Supozohet se sistemi i procesoreve mund te<br />

lexoje/shkruaje nga kujtesa nje vlere ne cdo hap.<br />

Duke supozuar se te dhenat jane neper procesore, mund te perdoret renditja “tek-cift”:<br />

38


Shembull:<br />

renditje ne topologji peme binare<br />

Bobble Sort ne dy faza:<br />

– faza I: cdo nyje mer vlerat me te vogla nga nen-pemet perkatese => minimali ne rrenje (fig)<br />

– faza II: rrenja shperndan elementet sipas rradhes ne nyjet bij te saj …<br />

Ne rastin me te keq te gjithe vlerat duhet te kalojne neper rrenje ~ “gryka e shishes”<br />

39


Shembull:<br />

renditja me “prerje” ( shearsort)<br />

ne topologji matrice:<br />

Renditja kryhet ne (log2r) ⎤ + 1 faza:<br />

1. rrjeshtat renditen ne forme “gjarperi”: cift ne rritje tek ne zbritje<br />

2. kollonat renditen nga lart poshte<br />

3. ne fazen e fundit rrjeshtat rirenditen te pavarur<br />

40


Kompleksiteti i Algoritmeve Paralele<br />

Analiza e kompleksitetit te algoritmeve:<br />

– e sakte: shuma e peshuar e treguesve per numrin e veprimeve te ndryshme<br />

– e perafert: analiza asimptotike => perdoret ne praktike<br />

Percaktimi i relacioneve O, Ω dhe Ɵ per dy funskione f(n) dhe g(n)<br />

• f(n)=O(g(n)) nqs. per n>no => f(n)no => f(n)>c•g(n)<br />

• f(n)=Ɵ(g(n)) nqs. per n>no => c•g(n)


Shembull:<br />

100<br />

90<br />

80<br />

70<br />

60<br />

50<br />

40<br />

30<br />

20<br />

10<br />

0<br />

300000<br />

250000<br />

200000<br />

150000<br />

100000<br />

50000<br />

f(x)<br />

x^2<br />

sqr(x)<br />

0 1 2 3 4 5 6 7 8 9 10<br />

f(x)<br />

x^2<br />

sqr(x)<br />

0<br />

0 100 200 300 400 500 600<br />

100<br />

10<br />

f(x)<br />

x^2<br />

sqr(x)<br />

1<br />

1 10<br />

1000000<br />

100000<br />

10000<br />

1000<br />

100<br />

10<br />

f(x)<br />

x^2<br />

sqr(x)<br />

1<br />

1 10 100<br />

Algoritmi quhet optimal kur kufijte e poshtem dhe te siperm konvergjojne asimptotikisht (shembujt<br />

e mesiperm nuk jane te tille). Ne rast optimaliteti nuk eshte e mundur qe rendi te zvogelohet<br />

asimptotikisht dhe e vetmja gje qe mund te behet eshte ndryshimi i konstanteve (shembull<br />

zvogelimi nga 4•n^2 ne 3•n^2).<br />

Le te jete T(n,p) koha e ekzekutimit te problemit me madhesi n ne nje makine me p procesore.<br />

Konsiderojme matjen e kostos nepermjet numrit te procesoreve. Algoritmi quhet:<br />

• optimal sipas kohes nqs. T(n,p)=g(n,p), ku g(n,p) eshte kufiri i poshtem i kohes<br />

• optimal sipas kosto-kohes nqs. p•T(n,p)=T(n,1) perdorimi=bolleku=1<br />

• eficient sipas kosto-kohes nqs. p•T(n,p)= Ɵ(T(n,1)) perdorimi=bolleku= Ɵ(1)<br />

Verejtje: numri i hapave mund te mos jete proporcional me kohen e ekzekutimit.<br />

42


Klasat e Kompleksitetit<br />

Problemet mund te klasifikohen sipas veshtiresise te zgjidhjes. Duke perdorur kohen e ekzekutimit<br />

ne nje makine me nje procesor (makina deterministike e Turingut), mund te percaktohen klasat:<br />

• Algoritmet me kohe ekzekutimi te kufizuar nga lart nga polinome => klasa P (polinomjale)<br />

Edhe ne rast se polinomi eshte i rendit te larte, mund te ekzistoje mundesia e permiresimit te<br />

algoritmit – algoritmet e klases P quhen edeh “te trajtueshem lehtesisht” (tractable)<br />

• Algoritmet determinsitike me kohe ekzekutimi eksponenciale konsiderohen “te pa-<br />

trajtueshem” (intractable). Nje problem me madhesi n qe kerkon 2^n instruksione, per<br />

n=100 ne nje makine me 1 GIPS kerkon 400 G shekuj. Algoritmet e pa trajtueshem, per te<br />

cilet korrektesia e zgjidhjes mund te verifikohet ne kohe polinomjale, quhen te klases NP<br />

(polinomjale jo-deterministike).<br />

Perpunimi paralel eshte efektiv kruesisht epr problemet e klases P, ndersa nuk eshte i mundur si<br />

rregull per problemet e klases NP.<br />

Ne 1979 Niclaus Pippenger sugjeroi nje nenklase te P te perbere nga algoritmet efektivisht te<br />

paralelizueshem qe mund te zgjidhen ne periudha kohore polinomjale sipas madhesise te problemit<br />

T(p)=O(log k n) duke perdorur jo me shume se nje sasi polinomjale procesoresh p=O(n). Kjo<br />

nenklase njihet si “klasa NC”.<br />

Nje forme e dobet e klases NC percaktohet si teza e paralelizimit kompjuterik:<br />

Cdo gje qe mund te llogaritet me nje makine Turingu duke perdorur hapesire<br />

polinomjalisht te kufizuar ne nje kohe te pakufizuar mund te llogaritet ne nje makine<br />

paralele ne nje kohe polinomjale duke eprdorur nje numer te pakufizuar procesoresh,<br />

dhe anasjelltas.<br />

Modelet e Paralelizimit<br />

– perca dhe sundo<br />

Coptohet problemi me madhesi n ne nen-probleme vogla me madhesi s, duke shpenzuar nje<br />

kohe Td(n)<br />

Nen-problemet zgjidhen vecash ne nje kohe T(s)


Koha totale e llogaritjeve eshte T(n)=Td(n)+T(s)+Tc(n)<br />

– Randomization<br />

Perdorimi i metodave te rastit per vendim-marje ne zgjidhjen e problemit ne “paralel”:<br />

‧ random sampling: coptimi i rastit i grupeve te te dhenave per perpunim paralel<br />

‧ random input: kapje e rastit e te dhenave per te shmangur grupimet e keqija (bad data<br />

patterns)<br />

‧ random searching: kerkimi i rastit i elementeve me karakteristika te caktuara<br />

‧ random control: zgjedhja e rastit e ndonje parametri te algoritmit<br />

‧ thyerja e simetrise: algoritme te caktuara deterministike mund te shfaqim dukuri ciklike<br />

qe shpijen ne deadlock. Rastesia mund te ndihmoje ne daljen nga qorrsokaku.<br />

‧ perafrimi: ne rastin e algortimeve iterative numri i iteracioneve mund te percaktohet<br />

– Rekurenca<br />

“apriori” ne varesi te kohes ne dispozicion, duke ofruar zgjidhje te perafert.<br />

Teoreme: nqs. ƒ(n)=a•ƒ(n/b)+h(n) zgjidhja asimtotike e rekurences eshte:<br />

f(n)= Ɵ( nlog b a ) nqs. h(n)=O(nlog b a­ε )<br />

f(n)= Ɵ( nlog b a•logn) nqs. h(n)=Ɵ(nlog b a )<br />

f(n)= Ɵ(h(n)) nqs. h(n)= Ω( nlog b a+ε )<br />

ku: h(n) eshte koha per coptimin e problemit dhe bashkimin e nen-rezultateve<br />

‧ b eshte numri i nen-problemeve me madhesi n/b<br />

‧ a eshte numri i “blloqeve” (batch) te ekzekutimit 1


Shembull:<br />

Vleresimi i kompleksitetit ne problemin e fushes<br />

gravitacionale:<br />

– problemi direkt – llogaritja e efektit<br />

gravitacional te trupit<br />

– problemi invers – gjetja e trupit nga<br />

efekti gravitacional<br />

– burimi i fushes gravitacionale percaktohet nga nje matrice 3D (NxNxN)<br />

– fusha gravitacionale llogaritet ne nje siperfaqe te perfaqesuar nga matrice 2D (NxN)<br />

– llogaritja e efektit te nje elementi 3D ne nje pike 2D ~ “llogaritje elementare”<br />

– numri i llogaritjeve elementare per efektin e nje elementi 3D ne matricen 2D eshte N^3<br />

– numri i veprimeve elementare per mbulimin e matrices 2D eshte (N^3)(N^2)=N^5<br />

– koha e llogaritjeve eshte e rendit O(N^5)<br />

– per te njejtin problem ne varesi te permasave te matricave efekti i elementit 3D proporcional<br />

me vellimin e tij, invers-proporcional me N^3<br />

– ne problemin invers koha e llogaritjes e efektit te trupit ne siperfaqe eshte O(N^8)<br />

Ne zgjidhjen iterative te problemit invers ne sisteme paralele koha eshte:<br />

45

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!