60
Paralelni programski modeli pthreads MPI/OpenMP Cilk IPP, TBB 1

Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Embed Size (px)

Citation preview

Page 1: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Paralelni programski modeli

pthreadsMPI/OpenMPCilkIPP, TBB

1

Page 2: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

IPPIPP = Integrated Performance Primitives Visoko optimizovane primitive za paralelno

programiranje Mogu se bezbedno pozivati iz TBB niti i Cilk linija

Širok skup primitiva specifičnih za razne domene Obrada signala Obrada slike i videa Male matrice i realistično crtanje Kriptografija

2

Page 3: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Primeri IPP Obrada signala

Filtri, kodovanje govora i audia, kompresija podataka, itd.

Obrada slike i videa Aritmetika i izmena podataka, konverzija boja, prag i

poređenje, morfološke operacije, filtriranje, linearne transformacije, statističke funkcije, geometrija , wavelet transformacije, računarska vizija, kompresija, kodovanje, itd.

Male matrice i realistično crtanje Vektorska i matrična algebra, linearni sistemi, metoda

najmanjih kvadrata, realistično crtanje i obrada 3D podataka, matematičke funkcije za 2D, 3D i 4D vektore, itd.

Kriptografija Simetrične primitve, autentifikacija, javni ključevi, itd.

3

Page 4: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

TBB (Threading Building Blocks)Teme Paralelizacija jednostavnih petlji Paralelizacija složenih petlje (petlje i protočne obrade) Izuzeća: try-catch Kontejneri Međusobno isključivanje niti Atomske operacije Vreme: metoda tick_count::now() Dodela memorije Raspoređivač zadataka

4

Page 5: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Jenostavne petlje: primer (1/2)Neka je bezbedno paralelno primeniti funkciju Foo na sve elemente niza ADa bi paralelizovali sekvencijalno rešenje Formiramo objekat tela

To je klasa čija metoda operator() radi nad delom iteracionog prostora

blocked_range<T> opisuje jednodimenzioni prostor blocked_range2d opisuje dvodimenzioni prostor

5

void SerialApplyFoo( float a[], size_t n ) {for( size_t i=0; i != n; ++i )

Foo(a[i]);}

Page 6: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Jenostavne petlje: primer (2/2)#include "tbb/tbb.h"using namespace tbb;class ApplyFoo {

float *const my_a;public:

void operator()( const blocked_range<size_t>& r ) const {float *a = my_a;for( size_t i=r.begin(); i!=r.end(); ++i )

Foo(a[i]);}ApplyFoo( float a[] ) : my_a(a) {}

};_______________________________________________#include "tbb/tbb.h"void ParallelApplyFoo( float a[], size_t n ) {

parallel_for(blocked_range<size_t>(0,n), ApplyFoo(a));}

6

Page 7: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Jednostavne petljeLambda izrazi (označeni sa [=] ili [&])

Lambda izraz zamenjuje deklaraciju i konstrukciju funkcijskog objekta ApplyFoo

7

#include "tbb/tbb.h"using namespace tbb;#pragma warning( disable: 588) // warning: use of local type …

void ParallelApplyFoo( float* a, size_t n ) {parallel_for( blocked_range<size_t>(0,n),

[=](const blocked_range<size_t>& r) {for(size_t i=r.begin(); i!=r.end(); ++i)

Foo(a[i]);}

);}//Note: [=] capture by value, [&] capture by reference

Page 8: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Jednostavne petljeparallel_for: skraćeni zapis od forfor(auto i=first; i<last; i+=step) f(i) Skraćen zapis: parallel_for(first,last,step,f)

Ako se f(i) mogu pozivati paralelno; step je opcion element

8

#include "tbb/tbb.h"using namespace tbb;#pragma warning(disable: 588)

void ParallelApplyFoo(float a[], size_t n) {parallel_for(size_t(0), n, [=](size_t i) {Foo(a[i]);});

}

Page 9: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Jednostavne petljeKontrolisana podela iteracionog prostora

Kontrola podele pomoću partitioner i grainsize Zadati simple_partitioner() unutar parallel_for blocked_range<T>(begin,end,grainsize)

Podrazumevani grainsize (G) je 1 simple_partitioner garantuje G/2 ≤ chunksize ≤ G Postoje još auto_partitioner i affinity_partitioner

9

#include "tbb/tbb.h"

void ParallelApplyFoo( float a[], size_t n ) {parallel_for(blocked_range<size_t>(0,n,G), ApplyFoo(a),

simple_partitioner());}

Page 10: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Jednostavne petljePodešavanje kvanta podele (grainsize)

Pravilo: grainsize iteracija traje 100.000 ciklusa Eksperiment: od 100.000 polovljenjem do optimuma Suviše mali grainsize može redukovati paralelizam Bolje malo veći, nego malo manji grainsize

Primer: a[i]=b[i]*c preko milion indeksa

10

Page 11: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Jednostavne petljeŠirina propusnog opsega i bliskost pri baferovanju

Malo ubrzanje zbog nedovoljnog propusnog opsega između procesora i memorije Prestruktuirati radi boljeg iskorišćenja bafera (cache) Ili, iskoristiti affinity_partitioner, kada

Obradu čine par operacija po pristupu podatku Podaci nad kojima petlja radi staju u bafer (cache) Petlja ili slična petlja se izvodi nad istim podacima Postoji više od 2 jezgra (hardware threads) u CPU

11

Page 12: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Jednostavne petljePrimer korišćenja affinity_partitioner (ap)

ap živi preko iteracija petlje To se postiže deklaracijom da je static Ap dodeljuje iteraciju niti koja ju je ranije izvršavala

12

#include "tbb/tbb.h"

void ParallelApplyFoo( float a[], size_t n ) {static affinity_partitioner ap;parallel_for(blocked_range<size_t>(0,n), ApplyFoo(a), ap);

}

void TimeStepFoo( float a[], size_t n, int steps ) {for( int t=0; t<steps; ++t )

ParallelApplyFoo( a, n );}

Page 13: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Jednostavne petljeKorist od bliskosti pri baferovanju

Zavisi od relativnog odnosa veličine skupa podataka i bafera Primer: A[i]+=B[i] u opsegu [0,N)

Za malo N dominira paralelno raspoređivanje, što rezultuje u malom ubrzanju

Za preveliko N skup podatak je prevelik da bi mogao biti prenešen u baferu preko iteracija petlje

13

20

10

010^4 10^5 10^6 10^7 10^8

N

Saffinity_partitionerauto_partitioner

Page 14: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Jednostavne petljeparallel_reduce (1/2)

Ako su iteracije nezavisne, gornja petlja se može paralelizovati sa parallel_reduce

14

float SerialSumFoo( float a[], size_t n ) {float sum = 0;for( size_t i=0; i!=n; ++i )

sum += Foo(a[i]);return sum;

}

float ParallelSumFoo( const float a[], size_t n ) {SumFoo sf(a);parallel_reduce( blocked_range<size_t>(0,n), sf );return sf.my_sum;

}

Page 15: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Jednostavne petljeparallel_reduce (2/2)

15

class SumFoo {float* my_a;

public:float my_sum;void operator()( const blocked_range<size_t>& r ) {

float *a = my_a;float sum = my_sum;size_t end = r.end();for( size_t i=r.begin(); i!=end; ++i )

sum += Foo(a[i]);my_sum = sum;

}SumFoo( SumFoo& x, split ) : my_a(x.my_a), my_sum(0) {}void join( const SumFoo& y ) {my_sum+=y.my_sum;}SumFoo(float a[] ) : my_a(a), my_sum(0) {}

};

Page 16: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Jednostavne petljeIzvršenje parallel_reduce-a

Kada je nit radnik (worker) raspoloživa Poziva se konstruktor razdvajanja

Pravi se podzadatak za nit radnika Nakon završetka podzadatka poziva se join radi akumuliranja

njegovog rezultata

16

Page 17: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Složene petljeparallel_do (1/2)

parallel_do se koristi ako iteracioni prostor nije poznat unapred Primer: povezana lista

U principu je bolje koristiti dinamičke nizove; liste su serijske Ima smisla ako obrada jednog elementa liste uključuje

nekoliko hiljada instrukcija Recimo da hoćemo da paralelizujmo ovaj sekvencijalan kod

17

void SerialApplyFooToList( const std::list<Item>& list ) {for( std::list<Item>::const_iterator i=list.begin() i!=list.end();

++i )Foo(*i);

}

Page 18: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Složene petljeparallel_do (2/2)

Nikada dve niti ne konkurišu za isti iterator Dva načina da se skalabilno dođe do više posla

Korišćenjem iteratora sa slučajnim pristupom Dodavanjem posla sa feeder.add(item)

feeder je drugi argument od funkcije operator() tipa parallel_do_feeder<Item>& 18

class ApplyFoo {public:

void operator()( Item& item ) const {Foo(item);

}};

void ParallelApplyFooToList( const std::list<Item>& list ) {parallel_do( list.begin(), list.end(), ApplyFoo() );

}

Page 19: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Složene petljeprotočna obrada (1/3)

TBB realizuje mustru protočne obrade Apstrakcije: pipeline i filter Primer: kvadriranje brojeva u datoteci

Stepeni protočne obrade: čitaj iz dat., kvadriraj, piši u dat. Blok podataka (4000 znakova) predstavljen klasom TextSlice

19

class TextSlice {char* logical_end, physical_end;static TextSlice* allocate( size_t max_size ) {

// +1 leaves room for a terminating null character.TextSlice* t = (TextSlice*)tbb::tbb_allocator<char>().allocate(

sizeof(TextSlice)+max_size+1 );t->logical_end = t->begin();t->physical_end = t->begin()+max_size;return t;

} ...

Page 20: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Složene petljeprotočna obrada (2/3)

Kod za pravljenje i izvršenje protočne obrade TextSlice objekti se prosleđuju putem pokazivača

20

void RunPipeline( int ntoken, FILE* input_file, FILE* output_file ) {tbb::parallel_pipeline(

ntoken,tbb::make_filter<void,TextSlice*>(

tbb::filter::serial_in_order, MyInputFunc(input_file) )&

tbb::make_filter<TextSlice*,TextSlice*>(tbb::filter::parallel, MyTransformFunc() )

&tbb::make_filter<TextSlice*,void>(

tbb::filter::serial_in_order, MyOutputFunc(output_file) ) );}

Page 21: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Složene petljeprotočna obrada (3/3)

Parametar ntoken kotroliše nivo paralelizma serial_in_order filter obrađuje znakove serijski parallel filter može obrađivati više znakova u paraleli Potencijalan problem: gde čuvati znake u srednjem stepenu

Ne dolazi do izražaja jer je broj znakova ograničen

ntoken specificira max br. znakova koji su u protočnoj obradi Drugi parametar specificira niz filtara make_filter<inputType,outputType>(mode,functor) Filtri se spajaju pomoću operatora & serial_out_of_order filter ne održava originalni redosled Prvi filtar ima spec param tbb::flow_control& fc

Zaustavljanje protočne obrade fc.stop();

21

Page 22: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Složene petljekružni baferi

Koriste se između filtara protočne obrade Dva serial_in_order filtra se mogu povezati kružnim

baferom veličine ntoken Kada se dođe do kraja, početak bafera je slobodan

Propusnost protočne obrade ograničena Brojem znakova N koji se istovremeno obrađuju

Malo N, mali paralelizam; preveliki N, previše resursa

Najsporiji filtar je usko grlo protočne obrade U TextSlice primeru U-I radnje ograničavaju ubrzanje

Veličina prozora može ograničiti propusnost Prevelik prozor – podaci ne mogu da stanu u bafer (cache)

22

Page 23: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Složene petljenelinearne protočne obrade

Mogu se transformisati u linearne Propusnost ostaje ista, jer je usko grlo ostalo isto Kašnjenje se povećava

Npr.: kašnjenje 3 filtra se povećava na kašnjenje 5 filtara Dobar kompromis između jednostavnosti i performanse

23

A

B

C

D

E

A

B

C

D

E

Page 24: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

KontejneriOmogućavaju istovremen pristup za više niti Zaštita STL kontejnera semaforima ograničava

paralelizam, odnosno ubrzanje TBB koristi dve metode

Fino zaključavanje (fine-grained locking) samo onih delova kontejnera koji se moraju zaključati

Tehnike bez zaključavanja – niti uračunavaju i popravljaju efekte drugih niti koje ih ometaju

Primitive kontejnera za paralelni pristup su duže nego kod klasičnih STL kontejnera Treba ih koristiti samo ako se isplati dodatni paralelizam koji

one omogućavaju

24

Page 25: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Kontejnericoncurrent_hash_map (1/3)

concurrent_hash_map<Key, T, HashCompare > HashCompare je tip koji određuje kako se računa ključ i kako

se dva ključa porede

25

// Structure that defines hashing and comparison operationsstruct MyHashCompare {

static size_t hash( const string& x ) {size_t h = 0;for( const char* s = x.c_str(); *s; ++s )

h = (h*17)^*s;return h;

}// ! True if strings are equalstatic bool equal( const string& x, const string& y ) {

return x==y;}

};

Page 26: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Kontejnericoncurrent_hash_map (2/3)

Mapa StringTable preslikava string na ceo broj Funkcijski objekat Tally broji pojave stringa

26

// A concurrent hash table that maps strings to ints.typedef concurrent_hash_map<string,int,MyHashCompare>

StringTable;// Function object for counting occurrences of strings.struct Tally {

StringTable& table;Tally( StringTable& table_ ) : table(table_) {}void operator()( const blocked_range<string*> range ) const {

for( string* p=range.begin(); p!=range.end(); ++p ) {StringTable::accessor a;table.insert( a, *p );a->second += 1;

}}

};

Page 27: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Kontejnericoncurrent_hash_map (3/3)

Pokazivač za pristup elementu mape accessor – radi upisa (zaključava element) const_accessor – radi čitanja (dopušteno više u paraleli) accessor i const_accessor su argumenti za metode find i

insert određuju da li je pristup radi ažuriranja ili radi čitanja

Po povratku (const_)accessor traje do njegovog uništenja Kako ograničava paralelizam, poželjno je što pre ga uništiti

Ovo se može uraditi sa: a.release();

27

Page 28: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Kontejnericoncurrent_vector

concurrent_vector<T>, gde je T dinamički niz Metode: push_back, grow_by, grow_to_at_least Nužno je sinhronizovati konstruisanje i pristup elementima Operacije nad concurrent_vector su duže nego nad vector

Koristiti ga samo ako dobijeni paralelizam daje ubrzanje

Važno: metoda clear nije bezbedna za paralelno korišćenje

Čekanje elementa v[i], koji dodaje druga nit Čekaj dok je i<v.size() Čekaj da v[i] bude konstruisan

Koristiti concurrent_vector sa zero_allocator-om koji dodeljene postavlja na 0

Konstruktor elementa postavlja zastavicu tipa atomic u elementu, kao zadnju akciju pri konstruisanju

28

Page 29: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Kontejnericoncurrent_queue

concurrent_queue<T,Alloc >, red vrednosti tipa T Osnove operacije: push i try_pop (ispitaj i izvadi, atomski) U programu sa jednom niti red je FIFO struktura Za više niti, red odraža redosled po redosledu ubacivanja Red je neograničen i neblokirajući (nema wait metodu)

concurrent_bounded_queue<T,Alloc > Ograničen red: varijanta sa blokiranjem Operacije: push, pop, try_push, size Metoda size vraća broje nepreuzetih elemenata reda

Može biti manja od nule

Veličina se postavlja metodom set_capacity (inicijalno je red neograničen) Kod ograničenog push je blokirajući; sporiji od neograničenog

29

Page 30: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

KontejneriNedostaci redova

Pre upotrebe redova razmotriti parallel_do i protočnu obradu, koji su obično efikasniji Red je usko grlo, zbog održavanja FIFO redosleda Nit koja treba da preuzme element može čekati

besposlena na redu Red je pasivna struktura; ubačen element se može

“ohladiti” u baferu Još gore, ako element preuzima nit u drugom jezgru, on i sve

što referencira mora se prebaciti u bafer tog jezgra

Nasuprot tome, parallel_do optimizuje upotrebu niti radnika da rade nešto drugo dok čekaju element i da održavaju elemente vrućima u baferu (cache)

30

Page 31: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Međusobno isključivanje nitiRealizuje se pomoću mutex i locks mutex je objekat, koji nit može zaključati, prethodno

dobijenim ključem Samo jedna nit može imati ključ, ostale moraju čekati Najjednostavniji mutex je spin_mutex

Adekvatan ako se ključ drži samo nekoliko instrukcija Primer: FreeListMutex štiti deljenu promenljivu FreeList

Grupisanje iskaza u blok može izgledati neobično – uloga je da se skrati vreme života ključa

31

Page 32: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Međusobno isključivanje nitiPrimer upotrebe spin_mutex-aNode* FreeList;typedef spin_mutex FreeListMutexType;FreeListMutexType FreeListMutex;

Node* AllocateNode() {Node* n;{

// constructor locks the listFreeListMutexType::scoped_lock lock(FreeListMutex);n = FreeList;if( n )

FreeList = n->next;} // descructor unlocks the listif( !n )

n = new Node();return n;

}

32

Page 33: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Međusobno isključivanje nitiAlternativan primer upotrebe spin_mutex-a

Metode acquire i release OO sprega – otključavanje u slučaju izuzeća Mutex tipa M ima ključ tipa M::scoped_lock

33

Node* AllocateNode() {Node* n;FreeListMutexType::scoped_lock lock;lock.acquire(FreeListMutex);n = FreeList;if( n )

FreeList = n->next;lock.release();if( !n )

n = new Node();return n;

}

Page 34: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Međusobno isključivanje nitiAtributi i vrste mutex-a

Atributi mutex-a Scalable/Non-scalable, Fair/Unfair, Recursive/Non-recursive,

Yield/Block (yield – upošljeno čekanje)

Vrste mutex-a spin_mutex

Non-scalable, unfair, non-recursive, yield (“vrti se”, spins)

queuing_mutex Scalable, fair, non-recursive, yield (spins)

spin_rw_mutex i queuing_rw_mutex Kao prethodni + podrška za ključeve čitača (readers)

mutex i recursive_mutex su omotači oko OS primitiva CRITICAL_SECTION na OS Windows

null_mutex and null_rw_mutex – ne rade ništa

34

Page 35: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Međusobno isključivanje nitiMutex-i čitača-pisača

Mutex-i su potrebni ako bar jedna nit piše u objekat Više čitača mogu dobiti ulaz u zaštićeni deo koda Mutex-i sa _rw_ u imenu razlikuju ključeve

Ključevi za čitanje i upis Razlikuju se po dodatnom parametru (tipa bool) scoped_lock

konstruktora: false – čitanje, true – upis (podrazumevano) Ključ za čitanje se može podići na nivo za pisanje

Metoda upgrade_to_writer U sl. primeru vektor se mora ponovo pretražiti, pošto

upgrade_to_writer može privremeno osloboditi ključ inače bi moglo doći do međusobnog blokiranja (deadlock) upgrade_to_writer vraća true, ako je oslobodila ključ

35

Page 36: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Međusobno isključivanje nitiPrimer mutex-i čitača-pisača

Pretpostavka: ključevi se dodaju na kraj i ne brišu se Dovoljno pretražiti elemente nakon onih originalno pretraženih

36

std::vector<string> MyVector;typedef spin_rw_mutex MyVectorMutexType;MyVectorMutexType MyVectorMutex;

void AddKeyIfMissing( const string& key ) {// Obtain a reader lock on MyVectorMutexMyVectorMutexType::scoped_lock

lock(MyVectorMutex,/*is_writer=*/false);size_t n = MyVector.size();for( size_t i=0; i<n; ++i )

if( MyVector[i]==key ) return;if( !MyVectorMutex.upgrade_to_writer() )

// Check if key was added while lock was temporarily releasedfor( int i=n; i<MyVector.size(); ++i )

if(MyVector[i]==key ) return;vector.push_back(key);

}

Page 37: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Međusobno isključivanje nitiPatologije ključeva

Međusobno blokiranje (deadlock); nastaje ako Postoji krug niti Svaka nit drži bar jedan ključ i čeka na mutex, koji je

zaključala druga nit Ni jedna nit ne želi da oslobodi svoje ključeve

Pravljenje konvoja (convoying) OS prekine nit koja drži ključ Druge niti moraju da sačekaju da prekinuta oslobodi ključ Kod fair mutex-a, još gore, čekaju nastavak prekinute

Izbegavanje konvoja Min vreme držanja ključa Koristiti atomske operacije umesto ključeva

37

Page 38: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Atomske operacijeDefinicija (1/2)

Druge niti vide atomske operacije kao trenutne Brže su od operacija sa ključevima Prednost: nema međusobnog zaključavanja niti konvoja Nedostatak: rade ograničen skup operacija Klasa atomic<T> implementira atomske operacije

Primer: referentno brojanje: akcija ako x==0 Sekvencijalno: --x; if(x==0) action() U sl. više niti, x postaje deljena promenljiva Smanjenje x i provera da li je 0 mora se uraditi neprekidivo x deklarisati kao atomic<int> i napisati if(--x==0) action()

Metod atomic<int>::operator-- dejstvuje atomatski

38

Page 39: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Atomske operacijeDefinicija (2/2)

atomic<T>, T int, enum ili pokazivač Pet osnovnih operacija nad x tipa atomic<T>

= x, pročitaj x x =, upiši vredost u x i vrati tu vrednost x.fetch_and_store(y), uradi x=y i vrati staru vrednost od x x.fetch_and_add(y), uradi x+=y i vrati staru vrednost od x x.compare_and_swap(y,z), ako je x==z, uradi x=y. Uvek

vrati staru vrednost od x

39

atomic<unsigned> counter;unsigned GetUniqueInteger() {

// return different int, until counter wraps aroundreturn counter.fetch_and_add(1);

}

Page 40: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Atomske operacijecompare_and_swap

compare_and_swap je osnova operacija za mnoge neblokirajuće algoritme Koristan idiom: ažuriranje globalx, zavisno od stare vrednosti Upozorenje: neke niti iteriraju, dok im druge ne zasmetaju

40

atomic<int> globalx;int UpdateX() { // Update x and return old value of x.

do {// Read globalXoldx = globalx;// Compute new valuenewx = ...expression involving oldx....// Store new value if another thread has not changed globalX.

} while( globalx.compare_and_swap(newx,oldx)!=oldx );return oldx;

}

Page 41: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Atomske operacijeABA problem

Prethodni idiom ne radi ispravno ako: Nit pročita vrednost A iz globalx Druga nit izmeni globalx od A na B na A Prva nit ne može da detektuje ovu promenu

Problem slabe memorijske konzistentnosi HW može promeniti redosleda operacija nad mem.

lokacijama radi povećanja efikasnosti Rešenje: arg. acquire/release za čitanje/upis objekata Primer: refcount.fetch_and_add<release>(-1);

Upis u deljeni objekat se mora završiti pre nego dođe do smanjenja refcount-a

41

Page 42: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Dodela memorije scalable_allocator<T> rešava problem skalabilnosti

Problem skalabilnosti se pojavljuje kada više niti dele zajednički memorijski bazen

Konvencionalan allocator: ekskluzivan pristup mem. bazenu scalable_allocator<T>: više niti istovremeno dobija objekte

tipa T

cache_aligned_allocator<T> rešava lažno deljenje linije bafera (cache) Nastaje kad dve niti pristupaju različitim rečima u liniji bafera Kad jedno jezgro promeni liniju, pa je promeni drugo jezgro,

linija se iz prvog prebacuje u drugo – nekoliko stotina taktova

Rešenje: cache_aligned_allocator<T> - garantuje da objekti koje napravi neće deliti istu liniju bafera

42

Page 43: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Raspoređivač zadatakaRealizuje paralelne aptrakcije visokog niova Nudi API, koji se može direktno koristiti Moguće je relizovati svoje apstrakcije visokog nivoa Treba koristiti logičke zadatke; prednosti:

Poklapanje paralelizma sa resursima, brže dizanje i spuštanje sistema, efikasniji redosled evaluacije, bolje uravnoteženje opterećenja, i razmišljanje na višem nivou

Programske niti se preslikavaju na fizička jezgra Krajnjosti pretplate: nedovoljna i prevelika Prevelika pretplata: dovodi do pada performanse zbog

deljenja vremena (time slicing) Raspoređivač pokušava da ima jednu nit na jednom jezgru

43

Page 44: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Raspoređivač zadatakaTBB zadaci

Zadaci su puno “lakši” od niti (brže se pokreću) Na OS Linux 18 puta, a na Windows više od 100 puta Zato što nit ima svoje registre, stek, ID Zadatak (task) u TBB je mala rutina

TTB zadaci jedan drugog ne istiskuju (preemption)

TBB raspoređivač je efikasan zato što nije pravedan On poseduje info o zadacima, tako da može da žrtvuje

pravednost za efikasnost Zadatak se pokreće tek kad može da učini koristan napredak

Raspoređivač uravnotežuje opterećenje (load balancing) Dovoljno je napraviti puno malih zadataka

Pri programiranju na nivou niti, programer sam rešava problem uravnoteženja opterećenja, koji nije trivijalan

44

Page 45: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Raspoređivač zadatakaPrimer: n-ti Fibonačijev niz (1/3)

Dat je serijski kod i paralelna verzija sa zadacima Veliki br. zadataka se najčešće prave mustrom rekurzivnog

zadataka

45

long SerialFib( long n ) {if( n<2 ) return n;else return SerialFib(n-1)+SerialFib(n-2);

}

long ParallelFib( long n ) {long sum;FibTask& a = *new(task::allocate_root()) FibTask(n,&sum);task::spawn_root_and_wait(a);return sum;

}

Page 46: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Raspoređivač zadatakaPrimer: n-ti Fibonačijev niz (2/3)

Funkcija ParallelFib 1. Dodeljuje prostor za zadatak, koristeći overloaded new

operator i metodu task::allocate_root (nema predaka) 2. Konstruiše zadatak konstruktorom FibTask(n,&sum) 3. Pokreće ga i čeka sa task::spawn_root_and_wait

Stvarni posao obavlja klasa FibTask

46

class FibTask: public task {public:

const long n;long* const sum;FibTask( long n_, long* sum_ ) :

n(n_), sum(sum_){}

//nastavak na drugom slajdu

Page 47: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Raspoređivač zadatakaPrimer: n-ti Fibonačijev niz (3/3)task* execute() { // Overrides virtual function task::execute

if( n<CutOff ) {*sum = SerialFib(n);

} else {long x, y;FibTask& a = *new( allocate_child() ) FibTask(n-1,&x);FibTask& b = *new( allocate_child() ) FibTask(n-2,&y);// Set ref_count to "two children plus one for the wait".set_ref_count(3);// Start b running.spawn( b );// Start a running and wait for all children (a and b).spawn_and_wait_for_all(a);// Do the sum*sum = x+y;

}return NULL; // pointer to next task to run

}47

Page 48: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Raspoređivač zadatakaGraf zadataka

Raspoređivač obrađuje graf zadataka Usmeren graf, svaki čvor je zadatak Svaki zadatak pokazuje na naslednika, koji ga čeka

Adresa naslednika se dobija sa task::parent()

Svaki zadatak ima refcount br. zadataka čiji je on naslednik dodaje se 1 za eksplicitno čekanje (wait)

Pimer grafa zadataka iz primera Fibonačijev niz A, B i C su izmrestili svoje potomke i čekaju ih D se izvršava, još nije izmrestio potomke E, F i G čekaju na izvršenje

48

Page 49: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Raspoređivač zadatakaPrimer grafa zadataka (Fibonačijev niz)

49

refcount=2

refcount=3 refcount=?

refcount=3 refcount=?

refcount=? refcount=?

zadatak A

zadatak B

zadatak C

zadatak D

zadatak G

zadatak F

zadatak E

Page 50: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Raspoređivač zadatakaAlgoritam raspoređivača (1/3)

Minimizira memorijske zahteve i komunikaciju niti Balansira izvršenje u dubinu i u širinu

(depth-first vs breadth-first)

Izvršenje u dubinu je najbolje za serijsko izvršenje Radi dok je bafer vruć. D je najnoviji, za njega je bafer

sigurno vruć; zatim nastavlja C, koji je noviji od A i B. Minimizira prostor. Kod izvršenja u širinu, koegzistira eksp.

br. zadataka. Kod izvršenja u dubinu, linearan, jer se ostali smeštaju na stek (E, F i G iz primera).

Iako izvršenje u širinu ima problem sa potrošnjom memorije, ono maksimizira paralelizam Koristiti dovoljno paralelizma, da jezgra budu upošljena

50

Page 51: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Raspoređivač zadatakaAlgoritam raspoređivača (2/3)

Hibrid izvršenja u dubinu i u širinu Svako jezgro ima svoj red sa dva kraja (deque)

Unutra su zadaci koji čekaju izvršenje

Kad zadatak izmresti naslednika, gurne ga na dno reda U primeru G je najstariji, a E najmlađi

Jezgro bira sledeći zadatak za izvršenje Onaj koji vrati metoda execute, ako nije NULL Onaj sa dna svog reda, ako nije prazan Krade zadatak sa vrha reda drugog slučajno izabranog jezgra

51

Page 52: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Raspoređivač zadatakaAlgoritam raspoređivača (3/3)

Tri uslova da jezgro gurne zadatak na dno reda Eksplicitno izmrešćen zadatak Zadatak označen za ponovno izvršenje

Metoda task::recycle_to_reexecute

Nakon izvršenja zadnjeg prethodnika refcount naslednika postaje 0 i jezgro gura naslednika na dno svog reda

Strategija: “Radi u dubinu, preuzimaj u širinu” “breadth-first theft and depth-first work” Izvršenje u širinu ide samo do potrebnog paralelizma Izvršenje u dubinu održava operativnu efikasnost, jednom

kada ima dovoljno posla

52

Page 53: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Raspoređivač zadatakaKorisne tehnike: pregled

Tehnike Rekurzivan lanac reakcija (Recursive Chain Reaction) Prosleđivanje nastavka (Continuation Passing) Zaobilaženje raspoređivača (Scheduler Bypass) Ponovna upotreba (Recycling) Prazni zadaci (Empty tasks) Opšti aciklični grafovi zadataka

53

Page 54: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Raspoređivač zadatakaKorisne tehnike (1/7)

Rekurzivan lanac reakcija Najbolja performansa za grafove u obliku stabala zadataka

Direktno stvaranje N zadataka O(N), kroz stablo O(lg(N))

Iteracioni prostor petlje se sa parallel_for može preslikati na binarno stablo zadataka

Prosleđivanje nastavka Predak uobičajeno čeka na svoje potomke

metoda spawn_and_wait_for_all

Ali, predak može da preda svoje potomke zadatku nastavka (continuation task) Besposleno jezgro može da preuzme (ukrade) zadatak

nastavka

54

Page 55: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Raspoređivač zadatakaKorisne tehnike (2/7)

allocate_continuation sličan allocate_child Usmerava successor od this na c, i postavlja successor od this

na NULL

55

} else {FibContinuation& c =

*new( allocate_continuation() ) FibContinuation(sum);FibTask& a = *new( c.allocate_child() ) FibTask(n-2,&c.x);FibTask& b = *new( c.allocate_child() ) FibTask(n-1,&c.y);// Set ref_count to "two children plus one for the wait".c.set_ref_count(2); // 2 instead of 3!!!spawn( b );spawn( a );return NULL;

}

Page 56: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Raspoređivač zadatakaKorisne tehnike (3/7)

Zaobilaženje raspoređivača Direktno se specificira sledeći zadatak za izvršenje Prosleđivanje nastavka obično otvara prostor za zaobilaženje

raspoređivača Npr. Rešenje ispod izbegava nepotrebno manipulisanje

stekom, kao i neželjeno preuzimanje zadatka od drugog jezgra

56

...FibTask& a = *new( c.allocate_child() ) FibTask(n-2,&c.x);FibTask& b = *new( c.allocate_child() ) FibTask(n-1,&c.y);// Set ref_count to "two children".c.set_ref_count(2);spawn( b );spawn( a );return &a; // instead of the return NULL;...

Page 57: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Raspoređivač zadatakaKorisne tehnike (4/7)

Ponovna upotreba (zadatka) Izbegava oslobađanje i (ponovnu) dodelu zadatka Ako se u prethodnom rešenju zadatak “a” zameni predkom

Umesto potomka “a” koristi se ponovno upotrebljen this Brišu se const atributi i return &a zameni sa retun this Dodaje se poziv recycle_as_child_of(c);

Označava da this ne treba obrisati po završetku execute Postavlja naslednika od this na c (continuation task)

57

Page 58: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Raspoređivač zadatakaKorisne tehnike (5/7)

Prazni zadaci, empty_task Neki put je samo potreban zadatak koji čeka potomke Primer u parallel_for.h, metoda start_for::execute

Pravi dva potomka i koristi prazan zadatak koji ih čeka, gornji parallel_for čeka na prazan zadatak

Opšti aciklični grafovi zadataka Do sada razmatrana stabla gde svaki zadatak ima jednog

naslednika task::parent() Moguće su složenije strukture, npr. svaki zadatak zavisi od

zadatka od gore i s leva

58

Page 59: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Raspoređivač zadatakaKorisne tehnike (6/7)const int M=3, N=4;class DagTask: public tbb::task {public:

const int i, j;double input[2]; // input[0] = sum from above, input[1] = sum from leftdouble sum;// successor[0] = successor below, successor[1] = successor to rightDagTask* successor[2];DagTask( int i_, int j_ ) : i(i_), j(j_) { input[0] = input[1] = 0; }task* execute() {

__TBB_ASSERT( ref_count()==0, NULL );sum = i==0 && j==0 ? 1 : input[0]+input[1];for( int k=0; k<2; ++k )

if( DagTask* t = successor[k] ) {t->input[k] = sum;if( t->decrement_ref_count()==0 )

spawn( *t );}

return NULL;}

}; 59

Page 60: Paralelni programski modeli - Odsek za računarsku tehniku ... Paralelni programski... · Kriptografija 2. Primeri IPP

Raspoređivač zadatakaKorisne tehnike (7/7)double BuildAndEvaluateDAG() {

DagTask* x[M][N];for( int i=M; --i>=0; )

for( int j=N; --j>=0; ) {x[i][j] = new( tbb::task::allocate_root() ) DagTask(i,j);x[i][j]->successor[0] = i+1<M ? x[i+1][j] : NULL;x[i][j]->successor[1] = j+1<N ? x[i][j+1] : NULL;x[i][j]->set_ref_count((i>0)+(j>0));

}// Add extra reference to last taskx[M-1][N-1]->increment_ref_count();// Wait for all but last task to complete.x[M-1][N-1]->spawn_and_wait_for_all(*x[0][0]);// Last task is not executed implicitly, so execute it explicitly.x[M-1][N-1]->execute();double result = x[M-1][N-1]->sum;// Destroy last task.task::destroy(*x[M-1][N-1]);return result;

}60