Threading Building Blocks

61
Threading Building Blocks

description

Threading Building Blocks. Σύνοψη. Γενικά για TBBs Tasks Parallel for Εσωτερική λειτουργία βιβλιοθήκης Task graphs . Σύνοψη. Γενικά για TBBs Tasks Parallel for Εσωτερική λειτουργία βιβλιοθήκης Task graphs . Τι είναι τα TBBs;. - PowerPoint PPT Presentation

Transcript of Threading Building Blocks

Page 1: Threading Building Blocks

Threading Building Blocks

Page 2: Threading Building Blocks

Σύνοψη Γενικά για TBBs Tasks Parallel for Εσωτερική λειτουργία βιβλιοθήκης Task graphs

Page 3: Threading Building Blocks

Σύνοψη Γενικά για TBBs Tasks Parallel for Εσωτερική λειτουργία βιβλιοθήκης Task graphs

Page 4: Threading Building Blocks

Τι είναι τα TBBs; C++ template library για αποδοτικό και εύκολο

παράλληλο προγραμματισμό σε πλατφόρμες μοιραζόμενης μνήμης

Αναπτύσσεται από την Intel από το 2004 (open-source από το 2007)

Δεν είναι καινούρια γλώσσα ή επέκταση Μεταφέρσιμη στους περισσότερους C++

compilers, λειτουργικά συστήματα και αρχιτεκτονικές

Page 5: Threading Building Blocks

Βασικά χαρακτηριστικά1. Ο προγραμματιστής ορίζει tasks αντί για

threads– επικεντρώνεται στην έκφραση του παραλληλισμού

στην εφαρμογή (σε υψηλότερο ή χαμηλότερο επίπεδο)– η βιβλιοθήκη είναι υπεύθυνη για την υλοποίησή του

• διάσπαση συνολικής δουλειάς σε επιμέρους εργασίες• δρομολόγηση εργασιών στους επεξεργαστές• συγχρονισμός• ισοκατανομή φορτίου• διαχείριση πόρων συστήματος και εσωτερικών

μηχανισμών

Page 6: Threading Building Blocks

Βασικά χαρακτηριστικά2. Σχεδιασμένη για κλιμακωσιμότητα

– η συνολική δουλειά σπάει σε πολλά μικρά κομμάτια (tasks), συνήθως πολύ περισσότερα από τον αριθμό των επεξεργαστών («parallel slack»)

– εξασφαλίζεται ότι θα υπάρχει πάντα διαθέσιμη δουλειά για κάθε επιπλέον επεξεργαστή που προστίθεται

– ο μηχανισμός για load balancing εξασφαλίζει την κλιμακώσιμη απόδοση

Page 7: Threading Building Blocks

Βασικά χαρακτηριστικά3. Εκμεταλλεύεται τη δύναμη και την ευελιξία του

γενικευμένου προγραμματισμού (generic programming)– παρέχει ένα πλούσιο σύνολο από παραμετροποιήσιμα

(templated), «ready to use» παράλληλα αλγοριθμικά μοτίβα και δομές• αντίστοιχα με την C++ STL για τα σειριακά προγράμματα

– δεν απαιτεί ειδική υποστήριξη από μεταγλωττιστή

Page 8: Threading Building Blocks

8

TBB 4.0 Components

Synchronization primitivesatomicmutexrecursive_mutexspin_mutex, spin_rw_mutexqueuing_mutex, queuing_rw_mutex

Generic Parallel Algorithmsparallel_for parallel_reduceparallel_scanparallel_do pipeline, parallel_pipeline, parallel_sortparallel_invoke

Concurrent containersconcurrent_unordered_map, concurrent_unordered_set, concurrent_hash_map,concurrent_queue, concurrent_bounded_queue, concurrent_priority_queueconcurrent_vector

Raw taskingtasktask_grouptask_listtask_scheduler_observer

Memory allocationtbb_allocatorcache_aligned_allocatorscalable_allocator

Flow Graphgraphfunction_nodebroadcast_node…

Page 9: Threading Building Blocks

9

TBB 4.0 Components

Synchronization primitivesatomicmutexrecursive_mutexspin_mutex, spin_rw_mutexqueuing_mutex, queuing_rw_mutex

Generic Parallel Algorithmsparallel_for parallel_reduceparallel_scanparallel_do pipeline, parallel_pipeline, parallel_sortparallel_invoke

Concurrent containersconcurrent_unordered_map, concurrent_unordered_set, concurrent_hash_map,concurrent_queue, concurrent_bounded_queue, concurrent_priority_queueconcurrent_vector

Raw taskingtasktask_grouptask_listtask_scheduler_observer

Memory allocationtbb_allocatorcache_aligned_allocatorscalable_allocator

Flow Graphgraphfunction_nodebroadcast_node…

Page 10: Threading Building Blocks

Σύνοψη Γενικά για TBBs Tasks Parallel for Εσωτερική λειτουργία βιβλιοθήκης Task graphs

Page 11: Threading Building Blocks

Tasks Εκφράζουν μια στοιχειώδη ανεξάρτητη εργασία

στο πρόγραμμα του χρήστη– πολύ πιο lightweight από τα native threads του

λειτουργικού

Δυνατότητα άμεσης χρήσης των tasks από τον προγραμματιστή – δημιουργία αυθαίρετα πολύπλοκων γράφων εργασιών

scheduler

tasks

parallel algorithms

Page 12: Threading Building Blocks

Προγραμματιστικό μοντέλο Όπως και στη Cilk, δύο βασικές λειτουργίες για

την περιγραφή ενός task graph– spawn: δημιουργία εργασίας– wait: συγχρονισμός εργασιών

Page 13: Threading Building Blocks

Μέθοδος 1task groups + Lambdas

long ParallelFib(long n) { if ( n < 16 ) return SerialFib(n); else { int x, y; tbb::task_group g; g.run( [&]{ x = ParallelFib(n-1); } ); g.run( [&]{ y = ParallelFib(n-2); } ); g.wait(); return x+y; }}

Page 14: Threading Building Blocks

Μέθοδος 2task objects

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

long n, sum;

FibTask& r = *new ( allocate_root())FibTask(n,&sum);

spawn_root_and_wait(r);

cout << sum;

class FibTask: public task { const long n; long *const sum; FibTask(long n_,long* sum_) { n=n_; sum=sum_; } 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(3); spawn(b); spawn(a); wait_for_all(); *sum = x+y; } return NULL; }};

Page 15: Threading Building Blocks

Μέθοδος 2task objects

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

class FibTask: public task { const long n; long *const sum; FibTask(long n_,long* sum_) { n=n_; sum=sum_; } 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(3); spawn(b); spawn(a); wait_for_all(); *sum = x+y; } return NULL; }};

each user-defined task must extend tbb::task

and implement execute()

long n, sum;

FibTask& r = *new ( allocate_root())FibTask(n,&sum);

spawn_root_and_wait(r);

cout << sum;

Page 16: Threading Building Blocks

long n, sum;

FibTask& r = *new ( allocate_root())FibTask(n,&sum);

spawn_root_and_wait(r);

cout << sum;

Μέθοδος 2task objects

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

class FibTask: public task { const long n; long *const sum; FibTask(long n_,long* sum_) { n=n_; sum=sum_; } 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(3); spawn(b); spawn(a); wait_for_all(); *sum = x+y; } return NULL; }};

allocate root task (has no parent)

spawn it, and wait here

Page 17: Threading Building Blocks

long n, sum;

FibTask& r = *new ( allocate_root())FibTask(n,&sum);

spawn_root_and_wait(r);

cout << sum;

Μέθοδος 2task objects

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

class FibTask: public task { const long n; long *const sum; FibTask(long n_,long* sum_) { n=n_; sum=sum_; } 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(3); spawn(b); spawn(a); wait_for_all(); *sum = x+y; } return NULL; }};

if n small enough, execute task serially

otherwise create and run two tasks

Page 18: Threading Building Blocks

long n, sum;

FibTask& r = *new ( allocate_root())FibTask(n,&sum);

spawn_root_and_wait(r);

cout << sum;

Μέθοδος 2task objects

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

class FibTask: public task { const long n; long *const sum; FibTask(long n_,long* sum_) { n=n_; sum=sum_; } 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(3); spawn(b); spawn(a); wait_for_all(); *sum = x+y; } return NULL; }};

allocate child tasks

how many children should I wait for?2 (+1 implicit...)

spawn tasks (indicate them as “ready to execute”)

ok, now really wait for children to complete

merge their results and store into *sum

Page 19: Threading Building Blocks

Σύνοψη Γενικά για TBBs Tasks Parallel for Εσωτερική λειτουργία βιβλιοθήκης Task graphs

Page 20: Threading Building Blocks

TBB: Αρχικοποίηση Για την χρήση οποιουδήποτε παράλληλου

αλγόριθμου της βιβλιοθήκης, απαιτείται η δημιουργία ενός αντικειμένου task_scheduler_init

#include <tbb/task_scheduler_init.h>#define NPROCS 4

int main(){ tbb::task_scheduler_init init(NPROCS); …}

Page 21: Threading Building Blocks

Παραλληλοποίηση for-loop Υπόθεση: εφαρμογή συνάρτησης Foo() σε κάθε

στοιχείο ενός πίνακα Σειριακός κώδικας

Παράλληλος κώδικας

float a[100];for ( int i=0; i!=100; ++i ) Foo(a[i]);

tbb::parallel_for( tbb::blocked_range<size_t>(0,100), [=](const tbb::blocked_range<size_t>& r) { for ( size_t i = r.begin(); i != r.end(); ++i ) Foo(a[i]); } );

δημιουργία (ανώνυμου) αντικειμένου για την περιγραφή του αρχικού χώρου επαναλήψεων

ανώνυμη συνάρτηση (Lambda expression) που περιγράφει τι δουλειά θα γίνεται σε έναν οποιονδήποτε υποχώρο επαναλήψεων του loop

Page 22: Threading Building Blocks

Παραλληλοποίηση for-loop

δήλωση:

η parallel_for αναλαμβάνει:– να διασπάσει το αρχικό range σε πολλά μικρότερα– να εφαρμόσει παράλληλα την ανώνυμη συνάρτηση σε

καθένα από αυτά

template <typename Range, typename Body>void parallel_for(const Range& R, const Body& B );

η βιβλιοθήκη παρέχει τις κλάσεις blocked_range, blocked_range2d, blocked_range3d

Page 23: Threading Building Blocks

Chunking και loop partitionersparallel_for( blocked_range<size_t>(0,n,G), [](){…}, ,some_partitioner())

Chunking: το μέγεθος των ranges στο οποίο σταματά η αναδρομική διάσπαση– optional argument στον constructor του blocked_range

Partitioners– optional argument στην parallel_for1. simple_partitioner

• recursive binary splitting, εγγυάται ότι ⎡G/2⎤ ≤ chunksize ≤ G2. affinity_partitioner

• αναθέτει τα ranges με τρόπο ώστε να μεγιστοποιείται το cache locality 3. auto_partitioner (default)

• επιλέγει αυτόματα το grainsize με βάση ευριστική μέθοδο• προσπαθεί να ελαχιστοποιήσει το range splitting σε σημείο που να εξασφαλίζεται

καλό load balancing

Page 24: Threading Building Blocks

Σύνοψη Γενικά για TBBs Tasks Parallel for Εσωτερική λειτουργία βιβλιοθήκης Task graphs

Page 25: Threading Building Blocks

Λειτουργία parallel_for0 N

P0 P1 P2 P3

A

A

αναδρομική διάσπαση του range, μέχρι να γίνει ≤ GrainSize

worker threads με double-ended queues

bottom (youngest task)

top (oldest task)

σε κάθε εκτέλεση της αναδρομής ένα range διασπάται σε 2 subranges

δημιουργούνται 2 νέα tasks που τοποθετούνται στη βάση της ουράς

κάθε worker παίρνει το task από τη βάση της τοπικής του ουράς και το εκτελεί

αν δεν βρει, τότε κλέβει κάποιο από την κορυφή της ουράς ενός τυχαίου worker

Page 26: Threading Building Blocks

Λειτουργία parallel_for0 N

P0 P1 P2 P3

A

A

Page 27: Threading Building Blocks

Λειτουργία parallel_for0 N

P0 P1 P2 P3

A

A

Page 28: Threading Building Blocks

Λειτουργία parallel_for0 N

P0 P1 P2 P3

B

N/2 N

A

B

A

Page 29: Threading Building Blocks

Λειτουργία parallel_for0 N

P0 P1 P2 P3

C

0 N/2 N/2 N

B

A

C B

A

Page 30: Threading Building Blocks

Λειτουργία parallel_for0 N

P0 P1 P2 P3

B

0 N/2 N/2 N

A

C B

C

Page 31: Threading Building Blocks

Λειτουργία parallel_for0 N

P0 P1 P2 P3

D

0 N/2

B

A

C B

D

C

Page 32: Threading Building Blocks

Λειτουργία parallel_for0 N

P0 P1 P2 P3

E

0 N/2

D

A

C B

0 N/4 E D

B

C

Page 33: Threading Building Blocks

Λειτουργία parallel_for0 N

P0 P1 P2 P3

E

0 N/2

D

A

C B

0 N/4 E D

B

C

Page 34: Threading Building Blocks

Λειτουργία parallel_for0 N

P0 P1 P2 P3

E B

0 N/2

D

A

C B

0 N/4 E D

C

Page 35: Threading Building Blocks

Λειτουργία parallel_for0 N

P0 P1 P2 P3

D B

0 N/2

A

C B

0 N/4 E D

E

Page 36: Threading Building Blocks

Λειτουργία parallel_for0 - N

P0 P1 P2 P3

F B

0 - N/2

D

A

C B

0 - N/4 E D

F

E

Page 37: Threading Building Blocks

Λειτουργία parallel_for0 - N

P0 P1 P2 P3

G B

0 - N/2

F

A

C B

0 - N/4 E D

0 -

N/8

G F

D

E

Page 38: Threading Building Blocks

Λειτουργία parallel_for0 - N

P0 P1 P2 P3

G B

0 - N/2

F

A

C B

0 - N/4 E D

0 -

N/8

G F

D

E

Page 39: Threading Building Blocks

Λειτουργία parallel_for0 - N

P0 P1 P2 P3

G B

0 - N/2

F

A

C B

0 - N/4 E D

0 -

N/8

G F

E

D

Page 40: Threading Building Blocks

Βασικοί μηχανισμοί Work stealing

– εξασφαλίζει ισοκατανομή φορτίου

Recursive splitting– επιτρέπει την επεξεργασία πάνω σε αυθαίρετα μικρά

κομμάτια και τη βέλτιστη εκμετάλλευση της cache

Page 41: Threading Building Blocks

Σύνοψη Γενικά για TBBs Tasks Parallel for Εσωτερική λειτουργία βιβλιοθήκης Task graphs

Page 42: Threading Building Blocks

Generic task graphtask groups

S();task_group g;g.run( [&]{ C(); E(); } );g.run( [&]{ task_group g1; g1.run( [&]{A();} ); g1.run( [&]{B();} ); g1.wait(); D(); });g.wait();F();

Page 43: Threading Building Blocks

Generic task graphflow graph graph g;

broadcast_node <continue_msg > s;

continue_node <continue_msg > a(g,A());continue_node <continue_msg > b(g,B());continue_node <continue_msg > c(g,C());continue_node <continue_msg > d(g,D());continue_node <continue_msg > e(g,E());continue_node <continue_msg > f(g,F());make_edge(s,a);make_edge(s,b);make_edge(s,c);make_edge(a,d);make_edge(b,d);make_edge(c,e);make_edge(d,f);make_edge(e,f);

S();s.try_put(continue_msg()); //fire!g.wait_for_all();

Page 44: Threading Building Blocks

Generic task graphtask objects + reference counts

class MeshTask: public task { public: const int i,j; //coordinates MeshTask *south,*east;

task* execute() { double north = (i==0) ? 0 : A[i-1][j]; double west = (j==0) ? 0 : A[i][j-1];

A[i][j] = do_work(north, west);

//if there is south neighbor if(south!=NULL) if (!south->decrement_ref_count()) spawn(*south);

//if there is east neighbor if(east!=NULL) if (!east->decrement_ref_count()) spawn(*south); return NULL; }}

0 1 1 1 1

1 2 2 2 2

1 2 2 2 2

1 2 2 2 2

MeshTask* Mesh[4][5];

//for all tasks in Mesh:// allocate // initialize south,east pointers// set reference counters

//wait for all but last task to completeMesh[3][4]->spawn_and_wait_for_all(*Mesh[0][0]);

//execute last taskMesh[3][4]->execute();

Page 45: Threading Building Blocks

Resources Home

– http://threadingbuildingblocks.org/ Latest stable release (4.0):

– https://threadingbuildingblocks.org/file.php?fid=77– use sources

Documentation: – https://threadingbuildingblocks.org/documentation.php– Getting Started– Tutorial– Reference

Intel Software Network blogs: – http://software.intel.com/en-us/blogs/tag/tbb/

Forum:–

http://software.intel.com/en-us/forums/intel-threading-building-blocks/

Page 46: Threading Building Blocks

ΤΕΛΟΣ

Page 47: Threading Building Blocks

Extra slides

Page 48: Threading Building Blocks

Lambda Expressions “C++11 feels like a new language” [B. Stroustrup] Δυνατότητα “in-place” ορισμού συναρτήσεων στο

σημείο που χρησιμοποιούνται– αντί των function objects– o compiler δημιουργεί μοναδικό, ανώνυμο function object

για κάθε lambda expression

gcc 4.5 or newer

char s[]="Hello World!";int nup = 0; //modified by the lambdafor_each( s, s+sizeof(s), [&nup] (char c) { if (isupper(c)) nup++; });cout << nup << " uppercase letters in: "<< s << endl;

Page 49: Threading Building Blocks

Lambda Syntax

49

[capture_mode] (formal_parameters) -> return_type {body}

Can omit if there are no parameters and return type is implicit.

Can omit if return type is void or code is “return expr;”

[&] by-reference[=] by-value[] no capture

[&](float x) {sum+=x;}

[&]{return *p++;}

[=](float x) {return a*x+b;}

[]{return rand();}

[](float x, float y)->float { if(x<y) return x; else return y;}

Examples

Page 50: Threading Building Blocks

Γενικευμένος Προγραμματισμός «... deals with finding abstract representations of

efficient algorithms, data structures, and other software concepts, and with their systematic organization» [Czarnecki, Eisenecker – Generative Programming]

«... a style of computer programming in which algorithms are written in terms of to-be-specified-later types that are then instantiated when needed for specific types provided as parameters» [wikipedia]

Σκοπός η ανάπυξη λογισμικού ώστε να είναι επαναχρησιμοποιήσιμο με απλό και αποδοτικό τρόπο

Page 51: Threading Building Blocks

Templates Επιτρέπουν την παραμετροποίηση τύπων σε

συναρτήσεις και κλάσεις Παράδειγμα templated συνάρτησης

template<typename T>void swap(T & x, T & y) { T tmp = x; x = y; y = tmp;}…float f1,f2;String s1,s2;

swap(f1,f2); //template instantiation: swap floatsswap(s1,s2); //template instantiation: swap strings

Ελάχιστες απαιτήσεις για τον Τ1. copy constructor T(const T&)2. assignment operatorvoid T::operator=(const T&);3. destructor ~T()

Page 52: Threading Building Blocks

Templates Παράδειγμα templated κλάσης

template<typename T, typename U>class pair {public: T first; U second;

pair( const T & x, const U & y ) : first(x), second(y) {}};

//compiler instantiates pair with T=string and U=intpair<string,int> x;x.first = “abc”;x.second = 42;

Page 53: Threading Building Blocks

C++ Standard Template Library (STL) Ένα από τα πλέον επιτυχημένα παραδείγματα

γενικευμένου προγραμματισμού Παρέχει ένα σύνολο από:

οι καλύτεροι δυνατοί αλγόριθμοι και δομές γραμμένοι με τον πιο γενικό τρόπο

instantiation ανάλογα με την περίπτωση κατά τη μεταγλώττιση

Δομές δεδομένων

vector, list, deque, set, map, stack, …

Αλγόριθμοι

for_each, sort, binary_search, find, count, …

Iterators

input, output,random access, bidirectional, …

Page 54: Threading Building Blocks

Παράδειγμα: πλήθος εμφανίσεων μιας τιμής σε ένα vectorvector<int> v;vector<int>::iterator b = v.begin(), e = v.end();long c = count( 4);

template<class Iter, class T>long count(Iter first, Iter last, const T& value) { long ret=0; while ( first != last ) if (*first++ == value) ++ret; return ret;}

b, e,

γενικευμένη υλοποίηση χωρίς να υστερεί σε απόδοση

Page 55: Threading Building Blocks

Function objects (“Functors”) Κλάσεις στις οποίες έχει υπερφορτωθεί ο

τελεστής () Έχουν την λειτουργικότητα συναρτήσεων

– στην ουσία είναι σαν δείκτες σε συναρτήσεις– επιπλέον πλεονεκτήματα (π.χ. αποθήκευση state)

Σε αυτά στηρίζεται η λειτουργία των TBBs– παράλληλα αλγοριθμικά μοτίβα υλοποιημένα σαν

template functions– κώδικας χρήστη υλοποιημένος σαν function object

Page 56: Threading Building Blocks

Παράδειγμα functor

56

template<typename I, typename Functor>void ForEach( I lower, I upper, const Functor& f ) { for ( I i=lower; i<upper; ++i ) f(i);}

Template function for iteration

class Accumulate { float& acc; float* src;public: Accumulate(float& acc_, float* src_) : acc(acc_), src(src_) (0) {} void operator()( int i ) { acc += src[i];}};

Functor

float a[4] = {1,3,9,27};float sum = 0.0;Accumulate A(sum,a);ForEach( 0, 4, A );cout << sum;

Pass functor to template function.

Page 57: Threading Building Blocks

Παραλληλοποίηση for-loop tbb::parallel_for

– χωρίζει τον αρχικό χώρο επαναλήψεων σε μικρότερα κομμάτια και τα εκτελεί παράλληλα

– template function 1ο βήμα: χρειάζεται να δώσουμε μια περιγραφή για το τι

δουλειά θα γίνεται σε έναν οποιονδήποτε υποχώρο επαναλήψεων του loop– γράφουμε το σώμα του loop στον operator() ενός function object– ο operator() είναι παραμετροποιημένος με βάση έναν υποχώρο class ApplyFoo { float *const my_a;public: ApplyFoo( float *a ) : my_a(a) {} void operator()( const blocked_range<int>& r ) const { float *a = my_a; for ( int i=r.begin(); i!=r.end(); ++i ) Foo(a[i]);}

blocked_range<T>: κλάση που εκφράζει 1D γραμμικό range πάνω στον τύπο Τ

Page 58: Threading Building Blocks

Παραλληλοποίηση for-loop 2ο βήμα: κλήση parallel_for

η parallel_for αναλαμβάνει:– να διασπάσει το αρχικό range σε πολλά μικρότερα– να εφαρμόσει παράλληλα το function object σε καθένα

από αυτά

float a[100];parallel_for( blocked_range<int>(0,100), ApplyFoo(a) );

δημιουργία (ανώνυμου) αντικειμένου για την περιγραφή του αρχικού χώρου επαναλήψεων

δημιουργία function object

Page 59: Threading Building Blocks

Δήλωση parallel_for

Απαιτήσεις για το Body B

Απαιτήσεις για το Range R

template <typename Range, typename Body>void parallel_for(const Range& R, const Body& B );

R(const R&) Copy a rangeR::~R() Destroy a rangebool R::empty() const Is range empty?bool R::is_divisible() const Can range be split?R::R (R& r, split) Split r into two subranges

B::B( const F& ) Copy constructorB::~B() Destructorvoid B::operator() (Range& subrange) const

Apply B to subrange

η βιβλιοθήκη παρέχει τις κλάσεις blocked_range, blocked_range2d, blocked_range3d

Page 60: Threading Building Blocks

Πιθανές σειρές εκτέλεσης των tasks

Depth-first- Απαιτεί λίγο χώρο- Καλή τοπικότητα

αναφορών- Μηδενικός

παραλληλισμός

Breadth-first- Απαιτεί πολύ χώρο- Κακή τοπικότητα

αναφορών- Μέγιστος παραλληλισμός

Page 61: Threading Building Blocks

Work depth-first, steal breadth-first Εξισορροπεί καλύτερα τις προηγούμενες

απαιτήσεις

L1

L2

victim thread

Δεύτερη καλύτερη επιλογή

Το κλέψιμο από την κορυφή εξασφαλίζει:- μεγάλο κομμάτι δουλειάς → καλή περαιτέρω κατανομή φορτίου- LRU δεδομένα του θύματος στον «κλέφτη», τα MRU παραμένουν στο «θύμα»