LEKSIONE PER SISTEMET E SHPERNDARA DHE PARALELE
LEKSIONE PER SISTEMET E SHPERNDARA DHE PARALELE
LEKSIONE PER SISTEMET E SHPERNDARA DHE PARALELE
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