Programování bez vláken. OpenMP

Podobné dokumenty
Paralení programování pro vícejádrové stroje s použitím OpenMP. B4B36PDV Paralelní a distribuované výpočty

Vícevláknové programování na CPU: POSIX vlákna a OpenMP I. Šimeček

Paralelní výpočetní jádro matematického modelu elektrostatického zvlákňování

Paralelní a distribuované výpočty (B4B36PDV)

Paralelní programování

Jakub Čermák Microsoft Student Partner

Ústav technické matematiky FS ( Ústav technické matematiky FS ) / 35

Úvod do OpenMP. Jiří Fürst

Vláknové programování část V

Vlákna a přístup ke sdílené paměti. B4B36PDV Paralelní a distribuované výpočty

Paralelní a distribuované výpočty (B4B36PDV)

Procesy a vlákna (Processes and Threads)

Úvod do GPGPU J. Sloup, I. Šimeček

Vlákno (anglicky: thread) v informatice označuje vlákno výpočtu neboli samostatný výpočetní tok, tedy posloupnost po sobě jdoucích operací.

Obsah. Kapitola 1 Hardware, procesory a vlákna Prohlídka útrob počítače...20 Motivace pro vícejádrové procesory...21

Paralelní a asynchronní programování. Zdeněk Jurka

Matematika v programovacích

Paralelní a distribuované výpočty (B4B36PDV)

Pokročilé architektury počítačů

IRAE 07/08 Přednáška č. 7. Začátek (head)

Paralelní architektury se sdílenou pamětí

Pokročilé architektury počítačů

Vláknové programování část I

C++ 0x aka C++11. Základním kamenem je třída std::thread

Šablonové metaprogramování v C++ Miroslav Virius KSI FJFI ČVUT

Obecné výpočty na GPU v jazyce CUDA. Jiří Filipovič

Více o konstruktorech a destruktorech

OPS Paralelní systémy, seznam pojmů, klasifikace

1. Zpracování událostí na pozadí aplikace

Management procesu I Mgr. Josef Horálek

Paralelní architektury se sdílenou pamětí

Statické proměnné a metody. Tomáš Pitner, upravil Marek Šabo

Paralelní programování

Preprocesor. Karel Richta a kol. katedra počítačů FEL ČVUT v Praze. Karel Richta, Martin Hořeňovský, Aleš Hrabalík, 2016

Vlákno odlehčený proces kód vlákna, zásobník privátní ostatní sdíleno s dalšími vlákny téhož procesu

Správa procesoru. Petr Krajča. Katedra informatiky Univerzita Palackého v Olomouci. 11. březen, 2011

Principy operačních systémů. Lekce 5: Multiprogramming a multitasking, vlákna

2) Napište algoritmus pro vložení položky na konec dvousměrného seznamu. 3) Napište algoritmus pro vyhledání položky v binárním stromu.

IB109 Návrh a implementace paralelních systémů. Organizace kurzu a úvod. RNDr. Jiří Barnat, Ph.D.

Pokročilé programování v jazyce C pro chemiky (C3220) Statické proměnné a metody, šablony v C++

Konstruktory a destruktory

Úvod Seznámení s předmětem Co je.net Vlastnosti.NET Konec. Programování v C# Úvodní slovo 1 / 25

Ukázka zkouškové písemka OSY

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

11. Přehled prog. jazyků

8 Třídy, objekty, metody, předávání argumentů metod

PREPROCESOR POKRAČOVÁNÍ

Algoritmizace a programování

Paralelní grafové algoritmy

CUDA J. Sloup a I. Šimeček

Základní komunikační operace

ZOS 9. cvičení, ukázky kódu. Pavel Bžoch

Pokročilé programování v jazyce C pro chemiky (C3220) Operátory new a delete, virtuální metody

Úvod do B4B36PDV. Organizace předmětu a seznámení se s paralelizací. B4B36PDV Paralelní a distribuované výpočty

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Programování v jazyce C a C++

IUJCE 07/08 Přednáška č. 6

Správa procesoru. Petr Krajča. Katedra informatiky Univerzita Palackého v Olomouci. Petr Krajča (UP) KMI/YOS: Přednáška III. 7. listopad, / 23

Programování v C++ 2, 4. cvičení

Příklad aplikace Klient/Server s Boss/Worker modelem (informativní)

Zápis programu v jazyce C#

SUPERPOČÍTAČE DANIEL LANGR ČVUT FIT / VZLÚ

Debugging. Testování. I když vypadá kód bez chyby, stejně ho nechte testovat víc než dostatečně dlouho za různých podmínek.

Paralelní a distribuované výpočty (B4B36PDV)

Architektury paralelních počítačů I.

Paralelní programování

Dynamika objektů. Karel Richta a kol. katedra počítačů FEL ČVUT v Praze

Programování v C++ 3, 3. cvičení

Paralelní a distribuované výpočty (B4B36PDV)

Objektové programování

Obsah. Předmluva 13 Zpětná vazba od čtenářů 14 Zdrojové kódy ke knize 15 Errata 15

Přidělování CPU Mgr. Josef Horálek

Paralelní programování

Martin Lísal. Úvod do MPI

Přednáška 1. Katedra počítačových systémů FIT, České vysoké učení technické v Praze Jan Trdlička, 2012

Funkční objekty v C++.

Programování v jazyce C pro chemiky (C2160) 3. Příkaz switch, příkaz cyklu for, operátory ++ a --, pole

Paralelní algoritmy --- Parallel Algorithms

PB161 Programování v jazyce C++ Přednáška 4

x86 assembler and inline assembler in GCC

TG Motion verze 4 Modul Virtuální PLC návod k obsluze

Mělká a hluboká kopie

Pokročilé programování v jazyce C pro chemiky (C3220) Třídy v C++

Paralelní architektury se sdílenou pamětí typu NUMA. NUMA architektury

1 Nejkratší cesta grafem

Šablony, kontejnery a iterátory

Datové typy v Javě. Tomáš Pitner, upravil Marek Šabo

přetížení operátorů (o)

Dynamické datové struktury I.

1. Programování proti rozhraní

Algoritmizace a programování

Implementace numerických metod v jazyce C a Python

Optimalizace pomocí icc/gcc - vektorizace

Využijte plný výkon procesorů s více jádry v LabVIEW 8.5

Cvičení 9 - Monitory. monitor m; var proměnné... procedure p; begin... end; begin inicializace; end;

Dynamicky vázané metody. Pozdní vazba, virtuální metody

Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

int => unsigned int => long => unsigned long => float => double => long double - tj. bude-li:

Základní operace. Prefix sum. Segmentovaný prefix-sum

Transkript:

Programování bez vláken Tradiční přístup je vytvoření vícevláknového programu, kde se řekne, co má které vlákno dělat Ale jde to i jinak, lze vytvořit program tak, že se řekne, co se má udělat paralelně OpenMP, Intel Thread Building Blocks, MS Concurrency Runtime OpenMP Open Multi-Processing Idea je, že se vezme sériový program a za použití speciálních knihoven se pomocí direktiv překladače řekne, co se má provádět paralelně Např. pokud se překladač vyvolá s direktivou openmp, program se přeloží jako paralelní, bez ní jako sériový #pragma omp parallel { for (int i=0; i<10; i++) { DoSomething(); Pokud se provádí paralelní výpočet, obvykle je nutná nějaká sdílená/redukční/uzamykaná proměnná Překladač se je může pokusit uhodnout, ale to se vždy nemusí podařit správně o Je lepší mu to prozradit pomocí speciálních direktiv o shared, private, reduction, default To samé platí i pro synchronizaci a plánování Strana 1 (celkem 12)

Lze použít i direktivu if, která spustí výpočet paralelně pouze tehdy, je-li daná podmínka splněna o Např. pokud je počet prvků pole k součtu dostatečně velký, aby se vyplatilo sečíst je paralelně Výhodou je, že se dá doparalelizovat sekvenční program, aniž by se do něho muselo nějak výrazně zasahovat o Např. výpočet statistiky //#pragma omp parallel for // reduction (+:localavgdiff, localavgabsdiff) // private(diff) shared(localmaxabsdiff) #pragma omp parallel { floattype sublocalmaxabsdiff = 0.0; //so that we do not need to declare localmaxabsdiff //as shared, thus intruducing wait penalty #pragma omp for nowait reduction (+:localavgdiff, localavgabsdiff) private(diff) for (i=0; i<cnt; i++) { diff = leftbuf[i].y-rightbuf[i].y; localavgdiff += diff; diff = fabs(diff); localavgabsdiff += diff; #ifdef _MSC_VER sublocalmaxabsdiff = max(sublocalmaxabsdiff, diff); #else sublocalmaxabsdiff = fmax(sublocalmaxabsdiff, diff); #endif //for #pragma omp critical (localmaxabsdiff) Strana 2 (celkem 12)

localmaxabsdiff = max(localmaxabsdiff, sublocalmaxabsdiff); //pragma omp parallel if (cnt) { //if to avoid division by zero floattype tmp; tmp = valuescnt; tmp = 1.0/tmp; (*stats).avgabsdiff = localavgabsdiff*tmp; (*stats).avgdiff = localavgdiff*tmp; (*stats).maxabsdiff = localmaxabsdiff; Strana 3 (celkem 12)

Intel Thread Building Blocks Open Source, podpora více platforem o Stejně jako OpenMP Ačkoliv si je TBB vědoma vláken poskytovaných OS, myšlenka je takový, že programátor už s vlákny nepracuje Namísto vláken specifikuje úlohy, tasks, a jejich návaznosti Důvodem je mj. redukce efektu cache-cooling o Uvažujeme tradičních m vláken na n procesorů, kde m > n o Jak vlákno běží, jeho pracovní data se dostávají do cache procesoru (tzv. hot data) o Jak se vlákna přepínají, do cache procesoru se dostávají pracovní data nového vlákna a pracovní data předchozích vláken jsou z cache odstraňována o Takže až takové vlákna přijde opět na řadu, každý cache-miss ho bude stát stovky cyklů čekání, než se jeho pracovní data znovu nahrají do cache (protože byly tzv. cooled) o S TBB programátor nepíše vlákna, ale úlohy o Vlákna poskytuje TBB tak, aby m<=n o Vlákno TBB pracuje na jedné úloze, dokud není dokončena => redukuje efekt cache-cooling o Tradiční vlákna ani thread-pool nic takového neumí! =>tradiční vlákna jsou dobrá na GUI a I/O, ale ne na výpočty Strana 4 (celkem 12)

Task Stealing je způsob plánování úloh http://software.intel.com/sites/products/documentation/doclib/tbb_sa/ help/tbb_userguide/how_task_scheduling_works.htm Úlohy A, B, C vytvořily podúlohy, na které čekají Úloha D běží Úlohy E, F, G ještě neběží Nejhlouběji zanořené úlohy jsou nejvíce cache-hot Breadth-first co nejdříve rozbalí celý strom, takže maximalizuje paralelismus Depth-first zase udržuje omezený počet uzlů stromu Takže je to v praxi kompromis, protože počet procesorových jader je omezený Na každý procesor je zásobník úloh Pokud jeden procesor dokončí svůj zásobník, může zkusit ukrást cool data z vrcholu zásobníku jiného procesoru Aneb FIFO ani priority nejsou vždy ta nejlepší strategie Strana 5 (celkem 12)

TBB vykonává úlohy paralelně, jak nejlépe to se současným know-how jde o Obsahuje různé další optimalizace v jakém pořadí úlohy vykonávat o Lze si napsat vlastní plánovač Stejně jako STL, i TBB intenzivně používá C++ šablony o Tj. nelze ji použít v C jako OpenMP Základní konstrukce TBB jsou o parallel_for, parallel_reduce, parallel_scan o parallel_while, parallel_do,pipeline, parallel_sort o paralelní kontainery, které jsou v STL o mutex, spin_mutex, queuing_mutex, spin_rw_mutex, queuing_rw_mutex, recursive mutex o fetch_and_add, fetch_and_increment, fetch_and_decrement, compare_and_swap, fetch_and_store TBB dokáže použít vlastní paměťový manažer, který je optimalizovaný na paradigma výpočtu úloh TBB je náročnější se naučit, ale zase se to vyplatí na výkonu, pokud se začíná psát nová aplikace, než např. paralelizovat s OpenMP o Navíc TBB se nespoléhá na direktivy pro překladač, takže podmínka if OpenMP se dá realizovat libovolně složitá, nebo se dají udělat konstrukce, který by šli s OpenMP udělat jen velmi obtížně např. cancellation výpočtu v OpenMP není Strana 6 (celkem 12)

Např. chceme-li spustit na pozadí několik výpočetně náročných úloh paralelně tbb::task* CMasterCalculationTBBLogic::execute() { tbb::task_list list; for (int i=gaifirst; i<=gailast; i++) list.push_back(*new(allocate_child()) CTask(i)); set_ref_count(gailast-gaifirst+2); //počet úloh +1 spawn_and_wait_for_all(list); return NULL; //non-null by byla úloha, která by měla //být spuštěna jako další/závislá na téhle Když bychom např. násobili vektor class CMulVect { floattype *ma, *mb; int mlen; public: floattype mproduct; CMulVect(floattype *a, floattype *b, int len) : ma(a), mb(b), mlen(len), mproduct(0.0) { CMulVect(CMulVect& x, tbb::split) : ma(x.ma), mb(x.mb), mlen(x.mlen), mproduct(0.0) { void join(const CMulVect& y) { mproduct += y.mproduct; void operator()( const tbb::blocked_range<size_t>& r ) { int r_end = r.end(); //Taken from Intel's tutorial on TBB //by declaring these variables, we make it //obvious to the compiler that they //can be held in registers instead in memory Strana 7 (celkem 12)

// => speedup floattype *a = ma; floattype *b = mb; floattype sum = 0.0; for (int i=r.begin(); i!=r_end; ++i) sum += a[i]*b[i]; ; mproduct += sum; floattype MulVect(floattype *a, floattype *b, int len) { floattype result = 0.0; //Jsou data tak velká, aby se je vůbec //vyplatilo počítat paralelně? if (len<=rmserialthreshold) { for (int i=0; i<len; i++) result += a[i]*b[i]; else { CMulVect mul(a, b, len); tbb::parallel_reduce( tbb::blocked_range<size_t>(0,len), mul); result = mul.mproduct; return result; U redukčních operací je třeba při inicializaci mezivýsledku rozlišovat mezi konstruktorem a funkčním operátorem () o Konstruktory jsou dva Normální, který bere parametry výpočtu A split konstruktor, který bere referenci na druhý objekt a na tbb::split Strana 8 (celkem 12)

o V konstruktorech se vždy inicializují dílčí mezivýsledky celé operace o Návrhově to totiž může svádět k tomu, aby se mezivýsledek inicializoval v těle funkčního operátoru o Jenže funkční operátor se může volat několikrát na stejné instanci, a pak by to dávalo špatné výsledky Případová studie použití TBB Uvažujme výpočetně náročnou aplikaci nad rozsáhlými daty s GUI Jedno vlákno bude obsluhovat GUI Jedno vlákno bude obsluhovat I/O o Naivní přístup je jedno vlákno pro zápis a jedno pro čtení o Lepší je jenom jedno vlákno a použití asynchronních I/O operací OS si je uspořádá sám pro lepší výkon Např. disky mají Native Command Queuing o Ale co s výpočetní částí? Určitě v tom bude alespoň jedno vlákno, aby výpočet běžel na pozadí a GUI bylo responsive Přístup s psaním vláken by znamenal postarat se o Vytváření a rušení vláken, což je další režie pro OS o Jejich správnou synchronizaci, což je náročné, jakmile se program stává složitější o Výkonnostně je rozdíl, jestli se synchronizuje v kernel-mode, nebo v user-mode address space o Výkonnostně hraje roli, zda se k datům přistupuje ze stejného procesoru thread affinity Strana 9 (celkem 12)

o Optimální počet vláken odpovídá počtu procesorových jader v systému, což ale není přístup, který je vždy možný při psaní vláken Např. počet vláken může odpovídat tomu, jaká je metoda výpočtu problém škálovatelnosti S TBB se taková vlákna nahradí úlohami S TBB o O výše uvedené problémy se TBB postará o Programátor napíše jedno vlákno, ve kterém pak spustí výpočet úloh TBB o Nicméně programátor si stále musí být vědom toho, jak se píší paralelní programy s vlákny, aby mohl správně používat synchronizační primitiva TBB Optimálně se naprogramují pouze úlohy s tím, že každá úloha po dokončení vrátí další úlohu, která se má vykonat jako navazující Jako bariéra na dokončení více úloh se pak použije task list Úlohy však mohou sdílet proměnné, a proto je třeba znát teorii o psaní vláken Aby byla představa, že 2 úlohy mohou, ale i nemusí, běžet paralelně, např. když se má správně použít mutex, podmínka... Strana 10 (celkem 12)

Concurrency Runtime Proprietární technologie MS Ideově podobná TBB, je to novější knihovna Jenže TBB běží nejen pod Windows a výkonově nezaostává Spuštění více úloh void Task1() { void Task2() { void Main() { task_group tg; tg.run(&task1); tg.run(&task2); tg.wait(); Výpočet součtu sum o http://msdn.microsoft.com/enus/magazine/ee309514.aspx combinable<int> localsums; parallel_for_each(myvec.begin(), myvec.end(), [&localsums] (int element) { SomeFineGrainComputation(element); localsums.local() += element; ); Strana 11 (celkem 12)

Násobení matic o http://msdn.microsoft.com/enus/library/dd728073.aspx void parallel_matrix_multiply(double** m1, double** m2, double** result, size_t size) { parallel_for (size_t(0), size, [&](size_t i) { for (size_t j = 0; j < size; j++) { double temp = 0; for (int k = 0; k < size; k++) { temp += m1[i][k] * m2[k][j]; result[i][j] = temp; ); Strana 12 (celkem 12)