Threading Building Blocks

Σχετικά έγγραφα
Παράλληλος Προγραμματισμός με τα reading Building Blocks

Σύνοψη. Γενικά για TBBs. Γενικευμένος προγραμματισμός και templates parallel_for Εσωτερική λειτουργία βιβλιοθήκης

Τεχνολογίες Υλοποίησης Αλγορίθµων

Τεχνολογίες Υλοποίησης Αλγορίθµων

1 Επισκόπηση. 2 Cilk. 3 Threading Building Blocks 4 UPC. 5 Charm++ 2 1/2015 Συστήματα Παράλληλης Επεξεργασίας

Standard Template Library (STL) C++ library

Δομές Δεδομένων Standard Template Library (STL) 23/3/2017 ΜΠΟΜΠΟΤΑΣ ΑΓΟΡΑΚΗΣ

Προχωρημένα Θέματα ΠΡΟΧΩΡΗΜΕΝΑ ΘΕΜΑΤΑ. Γεώργιος Παπαϊωάννου ( )

Standard Template Library (STL)

Προγραμματισμός Ι. Κλάσεις και Αντικείμενα. Δημήτρης Μιχαήλ. Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

ΠΑΝΕΠΙΣΤΗΜΙΟ ΠΑΤΡΩΝ ΣΧΟΛΗ ΘΕΤΙΚΩΝ ΕΠΙΣΤΗΜΩΝ ΤΜΗΜΑ ΜΑΘΗΜΑΤΙΚΩΝ ΙΠΛΩΜΑΤΙΚΗ ΕΡΓΑΣΙΑ

Τεχνολογίες Υλοποίησης Αλγορίθµων

Προγραμματισμός Ι. Δείκτες. Δημήτρης Μιχαήλ. Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Cilk: Φιλοσοφία και Χρήση

ΣΧΕΔΙΟΤΥΠΑ (TEMPLATES)

Η πολυνηματική γλώσσα προγραμματισμού Cilk

Προγραμματισμός Ι. Δυναμική Διαχείριση Μνήμης. Δημήτρης Μιχαήλ. Ακ. Έτος Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Εισαγωγή στον Προγραμματισμό

Boost - Boost Graph Library C++ library

ΒΑΣΙΚΟΙ ΤΥΠΟΙ ΚΑΙ ΠΙΝΑΚΕΣ

Κλήση Συναρτήσεων ΚΛΗΣΗ ΣΥΝΑΡΤΗΣΕΩΝ. Γεώργιος Παπαϊωάννου ( )

Αντικειμενοστραφής Προγραμματισμός

alpha Language age (3/5) alpha Language Φροντιστήριο Syntax Directed Translation and

Η Γλώσσα Προγραµµατισµού C++ (The C++ Programming Language) Ιστοσελίδα του µαθήµατος. Περιεχόµενα. ηµήτριος Κατσαρός, Ph.D.

Προγραμματισμός Ι. Εισαγωγή στην C++ Δημήτρης Μιχαήλ. Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Εισαγωγή στον Προγραμματισμό

Προαπαιτούμενες Ασκήσεις 5 ου Εργαστηρίου. Dose stoixeio (integer) : 25 Found stoixeio in position 7 Dose stoixeio (integer) :94 Value not found

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κλάσεις και Αντικείμενα Αναφορές

Δομές Δεδομένων. Λουκάς Γεωργιάδης.

Δομημένος Προγραμματισμός

Εισαγωγή στον Προγραμματισμό

Δομές Δεδομένων & Αλγόριθμοι

Οντοκεντρικός Προγραμματισμός

Γλώσσα Προγραμματισμού C++ Εισαγωγή - Μια πρώτη ματιά

ΚΥΠΡΙΑΚΗ ΕΤΑΙΡΕΙΑ ΠΛΗΡΟΦΟΡΙΚΗΣ CYPRUS COMPUTER SOCIETY ΠΑΓΚΥΠΡΙΟΣ ΜΑΘΗΤΙΚΟΣ ΔΙΑΓΩΝΙΣΜΟΣ ΠΛΗΡΟΦΟΡΙΚΗΣ 19/5/2007

Ερώτημα Α 1. Να γράψετε τις εντολές που πραγματοποιούν τα ακόλουθα:

ΟΝΤΟΚΕΝΤΡΙΚΟΣ ΠΡΟΓΡ/ΣΜΟΣ C++

Δομές Δεδομένων Boost C++ Libraries. 23/3/2017 ΜΠΟΜΠΟΤΑΣ ΑΓΟΡΑΚΗΣ

Αντικειµενοστρεφής Προγραµµατισµός

Προγραμματισμός Υπολογιστών με C++ Φύλλο Διαγωνίσματος Ακαδημαϊκό εξάμηνο: Χειμερινό

ΕΡΓΑΣΤΗΡΙΟ 1 - ΣΗΜΕΙΩΣΕΙΣ

The Simply Typed Lambda Calculus

Αντικειμενοστρεφής Προγραμματισμός

ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ

ΕΠΛ232 Προγραμματιστικές Τεχνικές και Εργαλεία Δείκτες και Συναρτήσεις (Κεφάλαιο 11, KNK-2ED)

Εισαγωγή σε αντικειμενοστραφή concepts. Και λίγη C#

Διάλεξη 3: Προγραμματισμός σε JAVA I. Διδάσκων: Παναγιώτης Ανδρέου

Διάλεξη 5: Δείκτες και Συναρτήσεις

Computing. Νοέμβριος Έκδοση 1.0

Αντικειμενοστραφείς Γλώσσες Προγραμματισμού C++ / ROOT

Προηγµένα Θέµατα Τεχνολογιών Υλοποίησης Αλγορίθµων

Προγραμματισμός Η/Υ (ΤΛ2007 )

Συλλογές ΣΥΛΛΟΓΕΣ. Γεώργιος Παπαϊωάννου ( )

Cilk: Φιλοσοφία και Χρήση

Στοιχειώδης προγραμματισμός σε C++

Δομημένος Προγραμματισμός (ΤΛ1006)

Εικονική Μνήμη (Virtual Memory) Προγραμματισμός II 1

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

Δομημένος Προγραμματισμός (ΤΛ1006)

Ανάπτυξη και Σχεδίαση Λογισμικού

Η εντολή if-else. Η απλή μορφή της εντολής if είναι η ακόλουθη: if (συνθήκη) { Η γενική μορφή της εντολής ifelse. εντολή_1; εντολή_2;..

Συναρτήσεις και Πίνακες

Προγραμματισμός Η/Υ (ΤΛ2007 )

Αντικειμενοστρεφής Προγραμματισμός

Εισαγωγή στη γλώσσα προγραμματισμού JAVA. Δομές Δεδομένων Διδάσκων: Π.Α. Μήτκας Τομέας Ηλεκτρονικής και Υπολογιστών

ΟΝΤΟΚΕΝΤΡΙΚΟΣ ΠΡΟΓΡ/ΣΜΟΣ C++

Β. Εισαγωγή στον Προγραμματισμό Η/Υ με την JavaScript

Στοίβες - Ουρές. Στοίβα (stack) Γιάννης Θεοδωρίδης, Νίκος Πελέκης, Άγγελος Πικράκης Τµήµα Πληροφορικής

Οντοκεντρικός Προγραμματισμός

Πληροφορική 2. Γλώσσες Προγραμματισμού

Απλές Δοµές Δεδοµένων Στην ενότητα αυτή θα γνωρίσουµε ορισµένες απλές Δοµές Δεδοµένων και θα τις χρησιµοποιήσουµε για την αποδοτική επίλυση του προβλή

Προγραμματισμός Η/Υ 1 (Εργαστήριο)

Ονοματεπώνυμο και ΑΜ: Είχα παραδώσει εργασίες τα εξής ακαδημαϊκά έτη: Διάρκεια: 2,5 ώρες, κλειστά βιβλία και σημειώσεις ΚΑΛΗ ΕΠΙΤΥΧΙΑ!

Αντικειμενοστρεφής Προγραμματισμός

Τύποι Δεδομένων και Απλές Δομές Δεδομένων. Παύλος Εφραιμίδης V1.0 ( )

Δομημένος Προγραμματισμός (ΤΛ1006)

Λογισµικό (Software SW) Γλώσσες

Προγραμματισμός Υπολογιστών με C++ Φύλλο Διαγωνίσματος Ακαδημαϊκό εξάμηνο: Χειμερινό

Dynamic types, Lambda calculus machines Section and Practice Problems Apr 21 22, 2016

Στόχοι και αντικείμενο ενότητας. Εκφράσεις. Η έννοια του τελεστή. #2.. Εισαγωγή στη C (Μέρος Δεύτερο) Η έννοια του Τελεστή

ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΥΠΡΟΥ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ EPL035: ΔΟΜΕΣ ΔΕΔΟΜΕΝΩΝ ΚΑΙ ΑΛΓΟΡΙΘΜΟΙ

Οντοκεντρικός Προγραμματισμός

ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΥΠΡΟΥ - ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ ΕΠΛ 133: ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΕΦΗΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΕΡΓΑΣΤΗΡΙΟ 3 Javadoc Tutorial

ΑΦAΙΡΕΤΙΚΟΣ (ή ΑΦΗΡΗΜΕΝΟΣ) ΤΥΠΟΣ ΔΕΔΟΜΕΝΩΝ (ΑΤΔ) (Abstract Data Type-ADT) - σύνολο δεδομένων (data, objects) - σύνολο πράξεων στα δεδομένα

Προγραμματισμός Υπολογιστών με C++

Practice Exam 2. Conceptual Questions. 1. State a Basic identity and then verify it. (a) Identity: Solution: One identity is csc(θ) = 1

Δομές Δεδομένων & Αλγόριθμοι

Εντολές εισόδου - εξόδου. Εισαγωγή στη C++

Δομές Δεδομένων (Data Structures)

Παράλληλη Επεξεργασία

8. Μέθοδοι (Methods)

Προγραμματισμός Η/Υ (ΤΛ2007 )

Lab 1: C/C++ Pointers and time.h. Panayiotis Charalambous 1

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

12. ΑΛΦΑΡΙΘΜΗΤΙΚΑ. υο είδη αλφαριθµητικών Τα αλφαριθµητικά της C πίνακες τύπου char Ta αντικείµενα της κλάσης string

Μάθημα 21: Ουρές (Queues)

Ενδεικτικές Λύσεις σε Επιλεγμένα Θέματα της C++

Εισαγωγή στην πληροφορική

Διάλεξη 14: Δομές Δεδομένων ΙΙI (Λίστες και Παραδείγματα)

Instruction Execution Times

Transcript:

Threading Building Blocks

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

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

Τι είναι τα TBBs; C++ template library για αποδοτικό και εύκολο παράλληλο προγραμματισμό σε πλατφόρμες μοιραζόμενης μνήμης Αναπτύσσεται από την Intel από το 2004 (open-source από το 2007) Δεν είναι καινούρια γλώσσα ή επέκταση Μεταφέρσιμη στους περισσότερους C++ compilers, λειτουργικά συστήματα και αρχιτεκτονικές

Βασικά χαρακτηριστικά 1. Ο προγραμματιστής ορίζει tasks αντί για threads επικεντρώνεται στην έκφραση του παραλληλισμού στην εφαρμογή (σε υψηλότερο ή χαμηλότερο επίπεδο) η βιβλιοθήκη είναι υπεύθυνη για την υλοποίησή του διάσπαση συνολικής δουλειάς σε επιμέρους εργασίες δρομολόγηση εργασιών στους επεξεργαστές συγχρονισμός ισοκατανομή φορτίου διαχείριση πόρων συστήματος και εσωτερικών μηχανισμών

Βασικά χαρακτηριστικά 2. Σχεδιασμένη για κλιμακωσιμότητα η συνολική δουλειά σπάει σε πολλά μικρά κομμάτια (tasks), συνήθως πολύ περισσότερα από τον αριθμό των επεξεργαστών («parallel slack») εξασφαλίζεται ότι θα υπάρχει πάντα διαθέσιμη δουλειά για κάθε επιπλέον επεξεργαστή που προστίθεται ο μηχανισμός για load balancing εξασφαλίζει την κλιμακώσιμη απόδοση

Βασικά χαρακτηριστικά 3. Εκμεταλλεύεται τη δύναμη και την ευελιξία του γενικευμένου προγραμματισμού (generic programming) παρέχει ένα πλούσιο σύνολο από παραμετροποιήσιμα (templated), «ready to use» παράλληλα αλγοριθμικά μοτίβα και δομές αντίστοιχα με την C++ STL για τα σειριακά προγράμματα δεν απαιτεί ειδική υποστήριξη από μεταγλωττιστή

Generic Parallel Algorithms parallel_for parallel_reduce parallel_scan parallel_do pipeline, parallel_pipeline, parallel_sort parallel_invoke Synchronization primitives atomic mutex recursive_mutex spin_mutex, spin_rw_mutex queuing_mutex, queuing_rw_mutex TBB 4.0 Components Concurrent containers concurrent_unordered_map, concurrent_unordered_set, concurrent_hash_map, concurrent_queue, concurrent_bounded_queue, concurrent_priority_queue concurrent_vector Raw tasking task task_group task_list task_scheduler_observer Flow Graph graph function_node broadcast_node Memory allocation tbb_allocator cache_aligned_allocator scalable_allocator 8

Generic Parallel Algorithms parallel_for parallel_reduce parallel_scan parallel_do pipeline, parallel_pipeline, parallel_sort parallel_invoke Synchronization primitives atomic mutex recursive_mutex spin_mutex, spin_rw_mutex queuing_mutex, queuing_rw_mutex TBB 4.0 Components Concurrent containers concurrent_unordered_map, concurrent_unordered_set, concurrent_hash_map, concurrent_queue, concurrent_bounded_queue, concurrent_priority_queue concurrent_vector Raw tasking task task_group task_list task_scheduler_observer Flow Graph graph function_node broadcast_node Memory allocation tbb_allocator cache_aligned_allocator scalable_allocator 9

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

Tasks Εκφράζουν μια στοιχειώδη ανεξάρτητη εργασία στο πρόγραμμα του χρήστη πολύ πιο lightweight από τα native threads του λειτουργικού (user-level, small-sized, non-preemptible, short-lived) parallel algorithms tasks scheduler Δυνατότητα άμεσης χρήσης των tasks από τον προγραμματιστή δημιουργία αυθαίρετα πολύπλοκων γράφων εργασιών

Προγραμματιστικό μοντέλο Όπως και στη Cilk, δύο βασικές λειτουργίες για την περιγραφή ενός task graph spawn: δημιουργία εργασίας wait: συγχρονισμός εργασιών

Μέθοδος 1 task 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;

Μέθοδος 2 task objects long SerialFib(long n) { if (n < 2) return n; else return SerialFib(n-1) + SerialFib(n-2); long n, 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); FibTask& r = *new ( allocate_root())fibtask(n,&sum); spawn_root_and_wait(r); cout << sum; ; set_ref_count(3); spawn(b); spawn(a); wait_for_all(); *sum = x+y; return NULL;

Μέθοδος 2 task objects long SerialFib(long n) { if (n < 2) return n; else return SerialFib(n-1) + SerialFib(n-2); long n, sum; each user-defined task must extend tbb::task class FibTask: public task { const long n; long *const sum; FibTask(long n_,long* sum_) { n=n_; sum=sum_; and implement execute() 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); FibTask& r = *new ( allocate_root())fibtask(n,&sum); spawn_root_and_wait(r); cout << sum; ; set_ref_count(3); spawn(b); spawn(a); wait_for_all(); *sum = x+y; return NULL;

Μέθοδος 2 task objects long SerialFib(long n) { if (n < 2) return n; else return SerialFib(n-1) + SerialFib(n-2); long n, sum; allocate root task (has no parent) 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); FibTask& r = *new ( allocate_root())fibtask(n,&sum); spawn_root_and_wait(r); cout << sum; spawn it, and wait here ; set_ref_count(3); spawn(b); spawn(a); wait_for_all(); *sum = x+y; return NULL;

Μέθοδος 2 task objects long SerialFib(long n) { if (n < 2) return n; else return SerialFib(n-1) task serially + SerialFib(n-2); long n, sum; if n small enough, execute otherwise create and run two tasks 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); FibTask& r = *new ( allocate_root())fibtask(n,&sum); spawn_root_and_wait(r); cout << sum; ; set_ref_count(3); spawn(b); spawn(a); wait_for_all(); *sum = x+y; return NULL;

Μέθοδος 2 task 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; allocate child tasks spawn tasks (indicate them as ready to execute ) 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; merge their results and store into *sum how many children should I wait for? 2 (+1 implicit...) ok, now really wait for children to complete

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

TBB: Αρχικοποίηση Για την χρήση οποιουδήποτε παράλληλου αλγόριθμου της βιβλιοθήκης, απαιτείται η δημιουργία ενός αντικειμένου task_scheduler_init #include <tbb/task_scheduler_init.h> #define NPROCS 4 int main() { tbb::task_scheduler_init init(nprocs);

Παραλληλοποίηση 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

Παραλληλοποίηση for-loop δήλωση: template <typename Range, typename Body> void parallel_for(const Range& R, const Body& B ); η parallel_for αναλαμβάνει: να διασπάσει το αρχικό range σε πολλά μικρότερα η βιβλιοθήκη παρέχει τις κλάσεις blocked_range, blocked_range2d, blocked_range3d να εφαρμόσει παράλληλα την ανώνυμη συνάρτηση σε καθένα από αυτά

Chunking και loop partitioners parallel_for( blocked_range<size_t>(0,n,g), [](){,,some_partitioner()) Chunking: το μέγεθος των ranges στο οποίο σταματά η αναδρομική διάσπαση optional argument στον constructor του blocked_range Partitioners optional argument στην parallel_for 1. simple_partitioner recursive binary splitting, εγγυάται ότι G/2 chunksize G 2. affinity_partitioner αναθέτει τα ranges με τρόπο ώστε να μεγιστοποιείται το cache locality 3. auto_partitioner (default) επιλέγει αυτόματα το grainsize με βάση ευριστική μέθοδο προσπαθεί να ελαχιστοποιήσει το range splitting σε σημείο που να εξασφαλίζεται καλό load balancing

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

Λειτουργία parallel_for 0 N A top (oldest task) αναδρομική διάσπαση του range, μέχρι να γίνει GrainSize bottom (youngest task) σε κάθε εκτέλεση της αναδρομής ένα range διασπάται σε 2 subranges δημιουργούνται 2 νέα tasks που τοποθετούνται στη βάση της ουράς κάθε worker παίρνει το task από τη βάση της τοπικής του ουράς και το εκτελεί αν δεν βρει, τότε κλέβει κάποιο από την κορυφή της ουράς ενός τυχαίου worker A P0 P1 P2 P3 worker threads με double-ended queues

Λειτουργία parallel_for 0 N A A P0 P1 P2 P3

Λειτουργία parallel_for 0 N A A P0 P1 P2 P3

Λειτουργία parallel_for 0 N A N/2 N B B A P0 P1 P2 P3

Λειτουργία parallel_for 0 N A 0 N/2 C N/2 N B B C A P0 P1 P2 P3

Λειτουργία parallel_for 0 N A 0 N/2 C N/2 N B B C P0 P1 P2 P3

Λειτουργία parallel_for 0 N A 0 N/2 C D B B D C P0 P1 P2 P3

Λειτουργία parallel_for 0 N A 0 N/2 C 0 N/4 E D B B D E C P0 P1 P2 P3

Λειτουργία parallel_for 0 N A 0 N/2 C 0 N/4 E D B B D E C P0 P1 P2 P3

Λειτουργία parallel_for 0 N A 0 N/2 C 0 N/4 E D B D E B C P0 P1 P2 P3

Λειτουργία parallel_for 0 N A 0 N/2 C B 0 N/4 E D D B E P0 P1 P2 P3

Λειτουργία parallel_for 0 - N A 0 - N/2 C 0 - N/4 E D B D F B E P0 P1 P2 P3 F

Λειτουργία parallel_for 0 - N A 0 - N/2 C B D F 0 - N/4 E D G B E P0 P1 P2 P3 0 - N/8 G F

Λειτουργία parallel_for 0 - N A 0 - N/2 C B D F 0 - N/4 E D G B E P0 P1 P2 P3 0 - N/8 G F

Λειτουργία parallel_for 0 - N A 0 - N/2 C B F 0 - N/4 E D G B D E P0 P1 P2 P3 0 - N/8 G F

Βασικοί μηχανισμοί Work stealing εξασφαλίζει ισοκατανομή φορτίου Recursive splitting επιτρέπει την επεξεργασία πάνω σε αυθαίρετα μικρά κομμάτια και τη βέλτιστη εκμετάλλευση της cache

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

Generic task graph

Generic task graph nested task 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();

Generic task graph flow 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();

Generic task graph task objects + reference counts A[i][j] = do_work(a[i-1][j], A[i][j-1])

Generic task graph task objects + reference counts 0 1 1 1 1 1 2 2 2 2 1 2 2 2 2 1 2 2 2 2 class MeshTask: public task { public: const int i,j; //coordinates MeshTask *south,*east; task* execute() { double north_val = (i==0)? 0 : A[i-1][j]; double west_val = (j==0)? 0 : A[i][j-1]; A[i][j] = do_work(north_val, west_val); MeshTask* Mesh[4][5]; //for all tasks in Mesh: // allocate // initialize south,east pointers // set reference counters //wait for all but last task to complete Mesh[3][4]->spawn_and_wait_for_all(*Mesh[0][0]); //execute last task Mesh[3][4]->execute(); //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(*east); return NULL;

Resources Home http://www.threadingbuildingblocks.org/ Documentation: https://www.threadingbuildingblocks.org/documentatio n/ Forum: http://software.intel.com/en-us/forums/intel-threadingbuilding-blocks/

ΤΕΛΟΣ

Extra slides

Lambda Expressions C++11 feels like a new language [B. Stroustrup] Δυνατότητα in-place ορισμού συναρτήσεων στο σημείο που χρησιμοποιούνται αντί των function objects o compiler δημιουργεί μοναδικό, ανώνυμο function object για κάθε lambda expression char s[]="hello World!"; int nup = 0; //modified by the lambda for_each( s, s+sizeof(s), [&nup] (char c) { if (isupper(c)) nup++; ); cout << nup << " uppercase letters in: "<< s << endl; gcc 4.5 or newer

Lambda Syntax [capture_mode] (formal_parameters) -> return_type {body [&] by-reference [=] by-value [] no capture Can omit if there are no parameters and return type is implicit. Can omit if return type is void or code is return expr; Examples [&](float x) {sum+=x; []{return rand(); [&]{return *p++; [=](float x) {return a*x+b; [](float x, float y)->float { if(x<y) return x; else return y; 51

Γενικευμένος Προγραμματισμός «... 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] Σκοπός η ανάπυξη λογισμικού ώστε να είναι επαναχρησιμοποιήσιμο με απλό και αποδοτικό τρόπο

Templates Επιτρέπουν την παραμετροποίηση τύπων σε συναρτήσεις και κλάσεις Παράδειγμα templated συνάρτησης template<typename T> void swap(t & x, T & y) { T tmp = x; x = y; y = tmp; float f1,f2; String s1,s2; Ελάχιστες απαιτήσεις για τον Τ 1. copy constructor T(const T&) 2. assignment operator void T::operator=(const T&); 3. destructor ~T() swap(f1,f2); //template instantiation: swap floats swap(s1,s2); //template instantiation: swap strings

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=int pair<string,int> x; x.first = abc ; x.second = 42;

C++ Standard Template Library (STL) Ένα από τα πλέον επιτυχημένα παραδείγματα γενικευμένου προγραμματισμού Παρέχει ένα σύνολο από: Δομές δεδομένων vector, list, deque, set, map, stack, Iterators input, output, random access, bidirectional, Αλγόριθμοι for_each, sort, binary_search, find, count, οι καλύτεροι δυνατοί αλγόριθμοι και δομές γραμμένοι με τον πιο γενικό τρόπο instantiation ανάλογα με την περίπτωση κατά τη μεταγλώττιση

Παράδειγμα: πλήθος εμφανίσεων μιας τιμής σε ένα vector vector<int> v; vector<int>::iterator b = v.begin(), e = v.end(); long c = count( b, e, 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; γενικευμένη υλοποίηση χωρίς να υστερεί σε απόδοση

Function objects ( Functors ) Κλάσεις στις οποίες έχει υπερφορτωθεί ο τελεστής () Έχουν την λειτουργικότητα συναρτήσεων στην ουσία είναι σαν δείκτες σε συναρτήσεις επιπλέον πλεονεκτήματα (π.χ. αποθήκευση state) Σε αυτά στηρίζεται η λειτουργία των TBBs παράλληλα αλγοριθμικά μοτίβα υλοποιημένα σαν template functions κώδικας χρήστη υλοποιημένος σαν function object

Παράδειγμα functor 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 { Functor float& acc; float* src; public: Accumulate(float& acc_, float* src_) : acc(acc_), src(src_) (0) { void operator()( int i ) { acc += src[i]; ; 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. 58

Παραλληλοποίηση for-loop tbb::parallel_for χωρίζει τον αρχικό χώρο επαναλήψεων σε μικρότερα κομμάτια και τα εκτελεί παράλληλα template function 1 ο βήμα: χρειάζεται να δώσουμε μια περιγραφή για το τι δουλειά θα γίνεται σε έναν οποιονδήποτε υποχώρο επαναλήψεων του loop γράφουμε το σώμα του loop στον operator() ενός function object ο operator() είναι παραμετροποιημένος με βάση έναν υποχώρο class ApplyFoo { blocked_range<t>: κλάση float *const my_a; που εκφράζει 1D γραμμικό public: range πάνω στον τύπο Τ 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]);

Παραλληλοποίηση for-loop 2 ο βήμα: κλήση parallel_for float a[100]; parallel_for( blocked_range<int>(0,100), ApplyFoo(a) ); δημιουργία (ανώνυμου) αντικειμένου για την περιγραφή του αρχικού χώρου επαναλήψεων η parallel_for αναλαμβάνει: δημιουργία function object να διασπάσει το αρχικό range σε πολλά μικρότερα να εφαρμόσει παράλληλα το function object σε καθένα από αυτά

Δήλωση parallel_for template <typename Range, typename Body> void parallel_for(const Range& R, const Body& B ); Απαιτήσεις για το Body B B::B( const F& ) B::~B() void B::operator() (Range& subrange) const Copy constructor Destructor Apply B to subrange Απαιτήσεις για το Range R R(const R&) Copy a range R::~R() Destroy a range bool 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 η βιβλιοθήκη παρέχει τις κλάσεις blocked_range, blocked_range2d, blocked_range3d

Πιθανές σειρές εκτέλεσης των tasks Depth-first - Απαιτεί λίγο χώρο - Καλή τοπικότητα αναφορών - Μηδενικός παραλληλισμός Breadth-first - Απαιτεί πολύ χώρο - Κακή τοπικότητα αναφορών - Μέγιστος παραλληλισμός

Work depth-first, steal breadth-first Εξισορροπεί καλύτερα τις προηγούμενες απαιτήσεις Το κλέψιμο από την κορυφή εξασφαλίζει: - μεγάλο κομμάτι δουλειάς καλή περαιτέρω κατανομή φορτίου - LRU δεδομένα του θύματος στον «κλέφτη», τα MRU παραμένουν στο «θύμα» L2 Δεύτερη καλύτερη επιλογή L1 victim thread