Paralelní architektury se sdílenou pamětí

Podobné dokumenty
Paralelní architektury se sdílenou pamětí

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

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

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

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

Úvod do OpenMP. Jiří Fürst

Pokročilé architektury počítačů

Přehled paralelních architektur. Dělení paralelních architektur Flynnova taxonomie Komunikační modely paralelních architektur

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

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

Paralelní architektury - úvod

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

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

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

Architektura Intel Atom

Paralelní architektury - úvod

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

Mezipaměti počítače. L2 cache. L3 cache

Pokročilé architektury počítačů

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

Operační systémy. Jednoduché stránkování. Virtuální paměť. Příklad: jednoduché stránkování. Virtuální paměť se stránkování. Memory Management Unit

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

Paralelní programování

OpenMP (Open Specification for Multi Processing)

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

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

Martin Flusser. Faculty of Nuclear Sciences and Physical Engineering Czech Technical University in Prague. October 17, 2016

Sběrnicová struktura PC Procesory PC funkce, vlastnosti Interní počítačové paměti PC

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme:

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

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

Cvičení předmětu MI-PAR P. Tvrdík, I. Šimeček, M. Šoch

Procesy a vlákna (Processes and Threads)

Technické prostředky počítačové techniky

Sběrnicová struktura PC Procesory PC funkce, vlastnosti Interní počítačové paměti PC

Operační systémy. Cvičení 3: Programování v C pod Unixem

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

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

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

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

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

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme:

Šablony, kontejnery a iterátory

PROGRAMOVÁNÍ V C++ CVIČENÍ

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

Systém adresace paměti

Standardní algoritmy vyhledávací.

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

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

Intel (2) Intel (1) Intel (3) Intel (4) Intel (6) Intel (5) Nezřetězené zpracování instrukcí:

PROCESOR. Typy procesorů

Programování inženýrských aplikací

Hlavní využití počítačů

Výkonnost mikroprocesoru ovlivňují nejvíce dvě hlediska - architektura mikroprocesoru a tzv. taktovací frekvence procesoru.

Operační systémy. Přednáška 8: Správa paměti II

Úvod do jazyka C. Ing. Jan Fikejz (KST, FEI) Fakulta elektrotechniky a informatiky Katedra softwarových technologií

Faculty of Nuclear Sciences and Physical Engineering Czech Technical University in Prague

Přidělování paměti II Mgr. Josef Horálek

Funkční objekty v C++.

Operační systémy. Správa paměti (SP) Požadavky na SP. Spojování a zavedení programu. Spojování programu (linking) Zavádění programu (loading)

Hardware - komponenty počítačů Von Neumannova koncepce počítače. Von Neumannova koncepce počítače

Polymorfismus. Časová náročnost lekce: 3 hodiny Datum ukončení a splnění lekce: 30.března

Operační systémy. Přednáška 1: Úvod

Identifikátor materiálu: ICT-1-08

Správné vytvoření a otevření textového souboru pro čtení a zápis představuje

Operační systémy. Přednáška 4: Komunikace mezi procesy

Úvod do architektur personálních počítačů

2.8 Procesory. Střední průmyslová škola strojnická Vsetín. Ing. Martin Baričák. Název šablony Název DUMu. Předmět Druh učebního materiálu

Gymnázium a Střední odborná škola, Rokycany, Mládežníků 1115

Faculty of Nuclear Sciences and Physical Engineering Czech Technical University in Prague

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

Procesor Intel Pentium (1) Procesor Intel Pentium (3) Procesor Intel Pentium Pro (1) Procesor Intel Pentium (2)

Faculty of Nuclear Sciences and Physical Engineering Czech Technical University in Prague

Semestrální práce KIV/PC Řešení kolizí frekvencí sítě vysílačů Zdeněk Bečvář A14B0466P 10. ledna 2016

IUJCE Přednáška č. 11. další prvky globální proměnné, řízení viditelnosti proměnných, funkcí

Základy programování. Úloha: Eratosthenovo síto. Autor: Josef Hrabal Číslo: HRA0031 Datum: Předmět: ZAP

Operační systémy. Přednáška 7: Správa paměti I

Koncepce (větších) programů. Základy programování 2 Tomáš Kühr

Algoritmizace a programování

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

Základy informatiky. 2. Přednáška HW. Lenka Carr Motyčková. February 22, 2011 Základy informatiky 2

Příkazy preprocesoru - Před překladem kódu překladačem mu předpřipraví kód preprocesor - Preprocesor vypouští nadbytečné (prázdné) mezery a řádky -

Konstruktory a destruktory

Blue Gene Vysoká škola báňská-technická univerzita Ostrava. Blue Gene. Karel Chrastina. Úvod. Blue Gene L. Blue Gene P.

Motivace. Software. Literatura a odkazy

Roman Výtisk, VYT027

Programování bez vláken. OpenMP

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

Pavel Procházka. 3. prosince 2014

Paměti. Paměť je zařízení, které slouží k ukládání programů a dat, s nimiž počítač pracuje

Šablony, kontejnery a iterátory

VÝUKOVÝ MATERIÁL. 3. ročník učebního oboru Elektrikář Přílohy. bez příloh. Identifikační údaje školy

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

Základy programování (IZP)

Paralelní programování

09. Memory management. ZOS 2006, L.Pešička

ARCHITEKTURA PROCESORŮ

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

Část 2 POROVNÁNÍ VÝKONNOSTI A POUŽITELNOSTI ARCHITEKTUR V TYPICKÝCH APLIKACÍCH

Transkript:

Paralelní architektury se sdílenou pamětí Multiprocesory Multiprocesory se sdílenou pamětí SMP architektury Přístup do paměti OpenMP

Multiprocesorové architektury I. Multiprocesor se skládá z několika plnohodnotných procesorů sdíleného adresového prostoru stejné adresy u dvou různých CPU ukazují na stejné místo v adr. prostoru Dělí se na systémy s fyzicky sdílenou pamětí systémy s fyzicky distribuovanou pamětí

Multiprocesorové systémy se sdílenou pamětí I. CPU CPU CPU CPU CPU CPU CPU CPU M M M M M M M M Interconnection network (= BUS) Global RAM I/O

Multiprocesorové systémy se sdílenou pamětí II. Mainframe IBM S360 Model 65 1965 zřejmě první dvouprocesorový systém

Multiprocesorové systémy se sdílenou pamětí II. tyto systémy jsou odvozeny z jednoprocesorového systému pouhým přidáním dalších CPU propojených sběrnicí (BUS) všechny procesory jsou rovnocenné odtud název - symmetric multiprocessor - SMP přístup do globální paměti je vždy stejně rychlý odtud název - uniform memory acces multiprocessor - UMA Příkladem SMP jsou dnes běžné vícejádrové PC.

SMP architektury ukážeme si některé současné microarchitektury založené na architektuře se sdílenou pamětí Intel Nehalem a Haswell AMD-FX MIC Intel Xeon Phi

SMP architektury Intel Nehalem Zdroj: http://www.ni.com/white-paper/11266/en/

SMP architektury Intel Haswell a chipset X99 Zdroj: http://www.anandtech.com/show/8557/ x99-motherboard-roundup-asus-x99-deluxe-gigabyte-x99-ud7-ud5-asrock-x99-ws-msi-x99s-sli-plus-intel-haswell-e/ 8

SMP architektury Intel Haswell Die

SMP architektury Intel Haswell 8 Core

SMP architektury AMD FX-990 Zdroj: http://www.anandtech.com/show/5714/ 990fx-motherboard-roundup-with-thuban-and-bulldozer-a-second-wind-for-asus-gigabyte-msi-and-biostar

SMP architektury AMD Bulldozer 8 Core Zdroj: http://www.anandtech.com/show/2881/2 architektura Bulldozer nemá všechna jádra plnohodnotná, ale každá dvojice jader sdílí jednotky pro výpočty s pohyblivou desetinnou čárkou

SMP architektury AMD Bulldozer 8 Core

SMP architektury AMD Bulldozer 8 Core Die

SMP architektury MIC Intel Xeon Phi (MIC = Many Integrated Cores)

SMP architektury MIC Intel Xeon Phi Die

SMP architektury jde o urychlovač výpočtů v HPC podobný grafickým urychlovačům má vlastní pamět o velikosti až 16 GB obsahuje až 61 jader podobných Pentiu P5 efektivně dokáže zpracovávat až 244 vláken podporuje instrukce AVX současná architektura nese název Knights Corner připravuje se nástupce zvaný Knights Landing 72 jader Intel Atom až 384 GB DDR4 RAM a 8-16 GB stacked 3D MCDRAM rozšířená sada instrukcí AVX512F (=AVX3.1)

SMP architektury přístup do paměti již víme, že pamět ové moduly jsou až 200x pomalejší než processor i jedno jádro tak dokáže plně vytížit pamět ový subsystém pro efektivní využití více jader je (až na výjimky) nezbytné optimalizovat přístupy do paměti vše se nyní výrazně komplikuje tzv. cache coherence problémem

SMP architektury přístup do paměti Cache coherence problem RAM X 7 Cache Cache CPU A CPU B

SMP architektury přístup do paměti CPU A načítá proměnnou X RAM X 7 7 CPU A CPU B

SMP architektury přístup do paměti CPU B načítá proměnnou X RAM X 7 7 7 CPU A CPU B

SMP architektury přístup do paměti CPU B zapisuje 2 do X, což se neprojevuje v cache procesoru A RAM X 2 7 2 CPU A CPU B

SMP architektury přístup do paměti Cache coherence problem je řešen hardwarově. Existují dva způsoby řešení: update protocol invalidate protocol

SMP architektury přístup do paměti Update protocol - X je sdílená proměnná RAM X 7 7 7 CPU A CPU B

SMP architektury přístup do paměti Procesor B zapisuje 2 do X ve své cache,... RAM X 7 7 2 CPU A CPU B

SMP architektury přístup do paměti... současně mění hodnotu X i v RAM... RAM X 2 2 2 CPU A CPU B

SMP architektury přístup do paměti... a v cache procesoru A. RAM X 2 2 2 CPU A CPU B

SMP architektury přístup do paměti Nevýhody update protokolu: pokud procesor A načte proměnnou X jen jednou na začátku, a potom s ní pracuje pouze procesor B, zbytečně pokaždé posílá novou hodnotu

SMP architektury přístup do paměti Nevýhody update protokolu: pokud procesor A načte proměnnou X jen jednou na začátku, a potom s ní pracuje pouze procesor B, zbytečně pokaždé posílá novou hodnotu V současnosti se častěji používá invalidate protokol. Nazývá se také MESI protocol podle stavů cache lines: 1. Modified 2. Exclusive proměnná není sdílena více procesory 3. Shared 4. Invalid

SMP architektury přístup do paměti Invalidate protocol - X je sdílená proměnná, tj. označená jako SHARED RAM X 7 7 7 CPU A CPU B

SMP architektury přístup do paměti Procesor B zapisuje 2 do X ve své cache a označuje X jako MODIFIED,... RAM X 7 7 2 CPU A CPU B

SMP architektury přístup do paměti... současně označuje hodnotu X v RAM za neplatnou - INVALID... RAM X 7 7 2 CPU A CPU B

SMP architektury přístup do paměti... a stejně tak označí i hodnotu X v cache procesoru B. RAM X 7 7 2 CPU A CPU B

SMP architektury přístup do paměti Nakonec je X MODIFIED v cache CPU B a INVALID v RAM a cache CPU A. RAM X 7 7 2 CPU A CPU B

SMP architektury přístup do paměti CPU A načítá X ze své cache a vidí ji označenou jako INVALID. RAM X 7 7 2 CPU A CPU B

SMP architektury přístup do paměti CPU A se tedy dotazuje CPU B, které má X označenou jako MODIFIED. RAM X 7 7 2 CPU A CPU B

SMP architektury přístup do paměti CPU B kopíruje hodnotu X do RAM... RAM X 2 7 2 CPU A CPU B

SMP architektury přístup do paměti... a do cache CPU A. RAM X 2 2 2 CPU A CPU B

SMP architektury přístup do paměti Proměnná X je nakonec všude označena jako sdílená - SHARED. RAM X 2 2 2 CPU A CPU B

SMP architektury přístup do paměti Nevýhody invalidate protokolu - tzv. false sharing: protokoly update/invalidate se ve skutečnosti vždy vztahují na celou cache line dva procesory mohou měnit dvě různé proměnné uložené ve stejné cache line (přitom každý jednu a tu samou), např. dvě vlákna ukládají mezivýsledky do sdíleného pole systém to nepozná a stejně se pokaždé provádí update režie spojená s invalidate protokolem je tu zbytečná update protokol je v takové situaci lepší

SMP architektury přístup do paměti Snoopy cache system každý procesor odposlouchává všechnu komunikaci tj. i ostatních CPU podle toho pak nastavuje stavy SHARE, INVALID a MODIFIED u sdílených proměnných

SMP architektury přístup do paměti Příklad: provedeme stejný test, který jsme dělali pro sekvenční architektury nyní ale využijeme více vláken Pro připomenutí: 1 template < i nt Size > 2 class ArrayElement 3 { 4 ArrayElement next ; 5 long in t data [ Size ] ; 6 } všechny prvky seznamu se alokují jako velké pole následně se propojí bud sekvenčně nebo náhodně

SMP architektury přístup do paměti Test budeme provádět na následujících systémech: AMD Phenom 2 X6 1075T 6 jader 6 x 64 kb L1 cache 6 x 512 kb L2 cache 1 x 6 MB L3 cache sdílená všemi jádry Intel i7 3770K 4 jádra + hypethreading = 8 vláken 4 x 32 kb L1 cache 4 x 256 kb L2 cache 8 MB L3 cache sdílená AMD Opteron 6172 x2 dvouprocesorovy systém s až 24 vlákny každé CPU má 12 jader 12 x 128 kb L1 cache 12 x 512 kb L2 cache 1 x 12 MB L3 cache sdílená

SMP architektury přístup do paměti velikost Size nastavíme na 1 nejprve budeme testovat náhodný přístup do paměti při N vláknech vytvoříme N disjunktních stejně dlouhých spojových seznamů i-tý seznam začíná na i-tém prvku pole a je zakončen nulovým ukazatelem seznamy procházíme opakovaně

SMP architektury náhodný přístup do paměti CPU tics/element 300 250 200 150 100 50 1 2 3 4 5 6 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Bandwidth in GB/sec 75 70 65 60 55 50 45 40 35 30 25 20 15 10 5 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB 1 2 3 4 5 6 Array size Array size CPU tics/element 300 250 200 150 100 1 2 3 4 5 6 Bandwidth in GB/sec 15 10 5 1 2 3 4 5 6 50 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size Obrázek : Vícevláknové náhodné čtení (nahoře) a zapisování (dole) na AMD Phenom 2 X6 1075T - až 6 vláken.

SMP architektury náhodný přístup do paměti CPU tics/element 250 200 150 100 50 1 2 3 4 5 6 7 8 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Bandwidth in GB/sec 110 105 100 95 90 85 80 75 70 65 60 55 50 45 40 35 30 25 20 15 10 5 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB 1 2 3 4 5 6 7 8 Array size Array size CPU tics/element 250 200 150 100 1 2 3 4 5 6 7 8 Bandwidth in GB/sec 10 5 1 2 3 4 5 6 7 8 50 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size Obrázek : Vícevláknové náhodné čtení (nahoře) a zapisování (dole) na Intel i7 3770K s čtyřmi jádry a hyperthreadingem - až 8 vláken.

SMP architektury náhodný přístup do paměti CPU tics/element 200 150 100 50 1 2 4 8 12 16 20 24 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Bandwidth in GB/sec 90 1 85 2 80 4 75 8 70 12 65 16 60 20 24 55 50 45 40 35 30 25 20 15 10 5 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size Array size CPU tics/element 200 150 100 50 1 2 4 8 12 16 20 24 Bandwidth in GB/sec 25 20 15 10 5 1 2 4 8 12 16 20 24 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size Obrázek : Vícevláknové náhodné čtení (nahoře) a zapisování (dole) na 2x AMD Opteron 6172 s dvanácti jádry - až 24 vláken.

SMP architektury sekvenční přístup do paměti dále provedeme test sekvenčního přístupu porovnáme dva způsoby: vlákna prochází pole na přeskáčku při N vláknech bude i-té vlákno procházet prvky i + jn, pro j = 1, 2,... každé vlákno prochází svůj blok při N vláknech rozdělíme celé pole na N disjunktních stejně velkých souvislých bloků a každé vlákno prochází jeden blok pole procházíme opakovaně

SMP architektury sekvenční přístup do paměti CPU tics/element 25 20 15 10 5 1 2 3 4 5 6 Bandwidth in GB/sec 80 70 60 50 40 30 20 1 2 3 4 5 6 10 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size CPU tics/element 15 10 5 1 2 3 4 5 6 Bandwidth in GB/sec 80 70 60 50 40 30 20 1 2 3 4 5 6 10 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size Obrázek : Vícevláknové sekvenční čtení na AMD Phenom 2 X6 1075T - až 6 vláken. Nahoře je procházení vlákny na přeskáčku dole prochází každé vlákno svůj blok.

SMP architektury sekvenční přístup do paměti CPU tics/element 55 50 45 40 35 30 25 20 15 1 2 3 4 5 6 Bandwidth in GB/sec 20 10 1 2 3 4 5 6 10 5 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size CPU tics/element 20 15 10 5 1 2 3 4 5 6 Bandwidth in GB/sec 80 70 60 50 40 30 20 1 2 3 4 5 6 10 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size Obrázek : Vícevláknové sekvenční zapisování na AMD Phenom 2 X6 1075T - až 6 vláken. Nahoře je procházení vlákny na přeskáčku dole prochází každé vlákno svůj blok.

SMP architektury sekvenční přístup do paměti CPU tics/element 10 5 1 2 3 4 5 6 7 8 Bandwidth in GB/sec 110 100 90 80 70 60 50 40 30 1 2 3 4 5 6 7 8 20 10 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size CPU tics/element 5 1 2 3 4 5 6 7 8 Bandwidth in GB/sec 120 110 100 90 80 70 60 50 40 1 2 3 4 5 6 7 8 30 20 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size 10 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size Obrázek : Vícevláknové sekvenční čtení na Intel i7 3770K s čtyřmi jádry a hyperthreadingem - až 8 vláken. Nahoře je procházení vlákny na přeskáčku dole prochází každé vlákno svůj blok.

SMP architektury sekvenční přístup do paměti CPU tics/element 20 15 10 5 1 2 3 4 5 6 7 8 Bandwidth in GB/sec 20 10 1 2 3 4 5 6 7 8 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size CPU tics/element 10 5 1 2 3 4 5 6 7 8 Bandwidth in GB/sec 70 60 50 40 30 20 1 2 3 4 5 6 7 8 10 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size Obrázek : Vícevláknové sekvenční zapisování na Intel i7 3770K s čtyřmi jádry a hyperthreadingem - až 8 vláken. Nahoře je procházení vlákny na přeskáčku dole prochází každé vlákno svůj blok.

SMP architektury sekvenční přístup do paměti CPU tics/element 35 30 25 20 15 10 1 2 4 8 12 16 20 24 Bandwidth in GB/sec 120 110 100 90 80 70 60 50 40 30 1 2 4 8 12 16 20 24 5 20 10 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size Array size CPU tics/element 10 5 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB 1 2 4 8 12 16 20 24 Bandwidth in GB/sec 270 260 250 240 230 220 210 200 190 180 170 160 150 140 130 120 110 100 90 80 70 60 50 40 30 20 10 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB 1 2 4 8 12 16 20 24 Array size Array size Obrázek : Vícevláknové sekvenční čtení na 2x AMD Opteron 6172 s dvanácti jádry - až 24 vláken. Nahoře je procházení vlákny na přeskáčku dole prochází každé vlákno svůj blok.

SMP architektury sekvenční přístup do paměti CPU tics/element 40 35 30 25 20 15 10 1 2 4 8 12 16 20 24 Bandwidth in GB/sec 30 20 10 1 2 4 8 12 16 20 24 5 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB Array size Array size CPU tics/element 25 20 15 10 5 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB 1 2 4 8 12 16 20 24 Bandwidth in GB/sec 260 250 240 230 220 210 200 190 180 170 160 150 140 130 120 110 100 90 80 70 60 50 40 30 20 10 0 1 kb 4 kb 16 kb 64 kb 256 kb 1 MB 4 MB 16 MB 64 MB 1 2 4 8 12 16 20 24 Array size Array size Obrázek : Vícevláknové sekvenční zapisování na 2x AMD Opteron 6172 s dvanácti jádry - až 24 vláken. Nahoře je procházení vlákny na přeskáčku dole prochází každé vlákno svůj blok.

Programování systémů se sdílenou pamětí opět vidíme, že sekvenční přístup je mnohem efektivnější než náhodný je výhodnější, když má každé vlákno svůj vlastní blok paměti, odpadá tak náročné řešení cache coherence problému zapisování do paměti může být výrazně pomalejší než čtení, obzvlášt, když vlákna přistupují do stejné oblasti v paměti

Programování systémů se sdílenou pamětí Programy pro architektury se sdílenou pamětí spouštějí několik souběžných vláken. Standardy: POSIX - standard pro manipulaci s vlákny OpenMP - standard pro podporu vláken na úrovni překladače u gcc překladače je pro zapnutí podpory OpenMP potřeba použít přepínač -fopenmp linkeru je potřeba předat -lgomp

OpenMP - základní direktiva OpenMP využívá direktivy preprocesoru. #pragma omp directive [clause list] Direktiva parallel způsobí, že následující blok instrukcí bude zpracován více vlákny. #pragma omp parallel [clause list] {... }

OpenMP - identifikace vláken Funkce pro identifikaci vláken: omp_get_num_threads() - vrací počet vláken omp_get_thread_num() - vrací celočíselný identifikátor vlákna

OpenMP - Hello 1 1 #include <omp. h> 2 #include < s t d l i b. h> 3 #include <iostream > 4 5 i n t main ( i n t argc, char argv ) 6 { 7 #pragma omp p a r a l l e l 8 { 9 std : : cout << "Hello from thread number " 10 << omp_get_thread_num ( ) << " of " 11 << omp_get_num_threads ( ) << " threads." 12 << std : : endl ; 13 } 14 return EXIT_SUCCESS ; 15 } Výstup: 1 Hello from thread number Hello from thread number 04 of 12 threads. Hello from thread nu of 2 Hello from thread number 3 of 12 threads. 3 Hello from thread number 5 of 12 threads. 4 Hello from thread number 11 of 12 threads. 5 Hello from thread number 1 of 12 threads. 6 10 of 12 threads. 7 Hello from thread number 2 of 12 threads. 8 Hello from thread number 6 of 12 threads. 9 12 threads. 10 Hello from thread number 9 of 12 threads. 11 Hello from thread number 8 of 12 threads. 12 Hello from thread number 7 of 12 threads.

Kritické bloky výstupy na konzoli mohou být chaotické je potřeba zařídit, aby současně nerpovádělo výpis více vláken to lze pomocí kritické sekce

Kritické bloky Kritické bloky obsahují kód, který může současně provádět jen jedno vlákno. #pragma omp critical [(name)]

Bloky pro jedno vlákno #pragma omp single {... } Tento blok bude zpracován jen jedním (prvním) vláknem. Pokud není uvedeno nowait, ostatní vlákna čekají na konci bloku. #pragma omp master {... } Tento blok bude zpracován jen vláknem s ID = 0, ostatní vlákna nečekají.

OpenMP - Hello s kritickou sekcí 1 std : : cout << std : : endl << "Now with critical section:" << std : : endl ; 2 #pragma omp p a r a l l e l 3 { 4 #pragma omp c r i t i c a l 5 std : : cout << "Hello from thread number " 6 << omp_get_thread_num ( ) << " of " 7 << omp_get_num_threads ( ) << " threads." 8 << std : : endl ; 9 } Výstup: 1 Now with c r i t i c a l s e c t i o n : 2 Hello from thread number 0 of 12 threads. 3 Hello from thread number 9 of 12 threads. 4 Hello from thread number 10 of 12 threads. 5 Hello from thread number 5 of 12 threads. 6 Hello from thread number 8 of 12 threads. 7 Hello from thread number 2 of 12 threads. 8 Hello from thread number 1 of 12 threads. 9 Hello from thread number 3 of 12 threads. 10 Hello from thread number 4 of 12 threads. 11 Hello from thread number 7 of 12 threads. 12 Hello from thread number 6 of 12 threads. 13 Hello from thread number 11 of 12 threads.

OpenMP - Hello se single sekcí 1 std : : cout << std : : endl << "Now with single section:" << std : : endl ; 2 #pragma omp p a r a l l e l 3 { 4 #pragma omp s i n g l e 5 std : : cout << "Hello from thread number " 6 << omp_get_thread_num ( ) << " of " 7 << omp_get_num_threads ( ) << " threads." 8 << std : : endl ; 9 } Výstup: 1 Now w ith s i n g l e s e c t i o n : 2 Hello from thread number 10 of 12 threads.

OpenMP - Hello se master sekcí 1 std : : cout << std : : endl << "Now with master section:" << std : : endl ; 2 #pragma omp p a r a l l e l 3 { 4 #pragma omp master 5 std : : cout << "Hello from thread number " 6 << omp_get_thread_num ( ) << " of " 7 << omp_get_num_threads ( ) << " threads." 8 << std : : endl ; 9 } Výstup: 1 Now w ith master s e c t i o n : 2 Hello from thread number 0 of 12 threads.

OpenMP - 2x Hello s kritickou sekcí 1 std : : cout << std : : endl << "Now two greetings:" << std : : endl ; 2 #pragma omp p a r a l l e l 3 { 4 #pragma omp c r i t i c a l ( p r i n t ) 5 std : : cout << "Hello number ONE from thread number " 6 << omp_get_thread_num ( ) << " of " 7 << omp_get_num_threads ( ) << " threads." 8 << std : : endl ; 9 10 #pragma omp c r i t i c a l ( p r i n t ) 11 std : : cout << "Hello number TWO from thread number " 12 << omp_get_thread_num ( ) << " of " 13 << omp_get_num_threads ( ) << " threads." 14 << std : : endl ; 15 16 } Výstup: 1 Now two greetings : 2 Hello number ONE from thread number 0 of 12 threads. 3 Hello number TWO from thread number 0 of 12 threads. 4 Hello number ONE from thread number 3 of 12 threads. 5 Hello number TWO from thread number 3 of 12 threads. 6 Hello number ONE from thread number 9 of 12 threads. 7 Hello number ONE from thread number 11 of 12 threads. 8 Hello number TWO from thread number 11 of 12 threads. 9 Hello number TWO from thread number 9 of 12 threads. 10 Hello number ONE from thread number 4 of 12 threads. 11 Hello number TWO from thread number 4 of 12 threads. 12 Hello number ONE from thread number 7 of 12 threads. 13 Hello number TWO from thread number 7 of 12 threads. 14 Hello number ONE from thread number 5 of 12 threads. 15...

OpenMP - 2x Hello s kritickou sekcí a bariérou 1 std : : cout << std : : endl << "Now two greetings:" << std : : endl ; 2 #pragma omp p a r a l l e l 3 { 4 #pragma omp c r i t i c a l ( p r i n t ) 5 std : : cout << "Hello number ONE from thread number " 6 << omp_get_thread_num ( ) << " of " 7 << omp_get_num_threads ( ) << " threads." 8 << std : : endl ; 9 #pragma omp b a r r i e r 10 #pragma omp c r i t i c a l ( p r i n t ) 11 std : : cout << "Hello number TWO from thread number " 12 << omp_get_thread_num ( ) << " of " 13 << omp_get_num_threads ( ) << " threads." 14 << std : : endl ; 15 16 } Výstup: 1... and now two g r e e t i n g s with b a r r i e r : 2 Hello number ONE from thread number 11 of 12 threads. 3 Hello number ONE from thread number 3 of 12 threads. 4 Hello number ONE from thread number 8 of 12 threads. 5 Hello number ONE from thread number 6 of 12 threads. 6 Hello number ONE from thread number 4 of 12 threads. 7 Hello number ONE from thread number 7 of 12 threads. 8 Hello number ONE from thread number 0 of 12 threads. 9 Hello number ONE from thread number 5 of 12 threads. 10 Hello number ONE from thread number 9 of 12 threads. 11 Hello number ONE from thread number 10 of 12 threads. 12 Hello number ONE from thread number 1 of 12 threads. 13 Hello number ONE from thread number 2 of 12 threads. 14 Hello number TWO from thread number 8 of 12 threads. 15 Hello number TWO from thread number 3 of 12 threads. 16 Hello number TWO from thread number 9 of 12 threads. 17 Hello number TWO from thread number 0 of 12 threads. 18...

OpenMP - bariéra do kódu je potřeba vložit bariéru to je bod v programu, kde na sebe všechna vlánka počkají až když každé z vláken dosáhne bariery, mohou vlákna pokračovat dále

OpenMP - proměnné Přístup více CPU do paměti rozlišujeme dva typy proměnných soukromé (private) - jsou přístupné jen jednomu procesoru sdílené (shared) - může k nim přistupovat více procesorů Ošetření sdílených proměnných multiprocesor se sdílenou pamětí neumožňuje, aby současně přistupovalo více procesorů na stejné místo v paměti pokud se tak stane výsledek je nepředvídatelný většinou je nutné se této situaci vyhnout dobře napsaným kódem

OpenMP - proměnné Pomocí [clause list] lze udat: podmínku (pouze jednu) paralelizace: if(... ) počet vláken: num_threads( integer expression ) zacházení s daty private( variable list ) Určuje lokální proměnné = každé vlákno má svou vlastní kopii. firstprivate( variable list ) Stejně jako private, ale u všech kopii se nastaví hodnota, kterou měla proměnná před rozvětvením běhu programu na vlákna. shared( variable list ) Tyto proměnné budou sdílené mezi vlákny. reduction( operator:variable list ) Dané proměnné budou mít lokální kopie a nakonec se provede redukce pomocí asociativní operace: +,*,&,,&&,.

Příklady #pragma omp parallel if( is_parallel == true ) num_threads(8) private(a) firstprivate(b) {... } #pragma omp parallel if( size > 1000 ) num_threads( MIN( size/1000+1,8) ) reduction(+:sum) {... }

OpenMP - proměnné 1 i n t main ( i n t argc, char argv ) 2 { 3 i n t shared_int ( 1 ), p r i v a t e _ i n t ( 1 ), f i r s t p r i v a t e _ i n t ( 1 ) ; 4 #pragma omp p a r a l l e l shared ( shared_int ), private ( p r i v a t e _ i n t ), 5 f i r s t p r i v a t e ( f i r s t p r i v a t e _ i n t ) 6 { 7 #pragma omp c r i t i c a l 8 std : : cout << "Variables of thread " 9 << omp_get_thread_num ( ) << " are" 10 << " shared_int = " << shared_int 11 << " private_int = " << p r i v a t e _ i n t 12 << " firstprivate_int = " << f i r s t p r i v a t e _ i n t 13 << std : : endl ; 14 #pragma omp b a r r i e r 15 shared_int ++; 16 p r i v a t e _ i n t ++; 17 f i r s t p r i v a t e _ i n t ++; 18 #pragma omp b a r r i e r 19 #pragma omp s i n g l e 20 std : : cout << "=======================================" << std : : endl ; 21 #pragma omp c r i t i c a l 22 std : : cout << "Variables of thread " 23 << omp_get_thread_num ( ) << " are" 24 << " shared_int = " << shared_int 25 << " private_int = " << p r i v a t e _ i n t 26 << " firstprivate_int = " << f i r s t p r i v a t e _ i n t 27 << std : : endl ; 28 } 29 return EXIT_SUCCESS ; 30 }

OpenMP - proměnné Výstup: 1 Variables of thread 0 are shared_int = 1 p r i v a t e _ i n t = 0 f i r s t p r i v a t e _ i n t = 1 2 Variables of thread 4 are shared_int = 1 p r i v a t e _ i n t = 0 f i r s t p r i v a t e _ i n t = 1 3 Variables of thread 6 are shared_int = 1 p r i v a t e _ i n t = 0 f i r s t p r i v a t e _ i n t = 1 4 Variables of thread 2 are shared_int = 1 p r i v a t e _ i n t = 0 f i r s t p r i v a t e _ i n t = 1 5 Variables of thread 7 are shared_int = 1 p r i v a t e _ i n t = 0 f i r s t p r i v a t e _ i n t = 1 6 Variables of thread 3 are shared_int = 1 p r i v a t e _ i n t = 0 f i r s t p r i v a t e _ i n t = 1 7 Variables of thread 8 are shared_int = 1 p r i v a t e _ i n t = 0 f i r s t p r i v a t e _ i n t = 1 8 Variables of thread 10 are shared_int = 1 p r i v a t e _ i n t = 0 f i r s t p r i v a t e _ i n t = 1 9 Variables of thread 9 are shared_int = 1 p r i v a t e _ i n t = 0 f i r s t p r i v a t e _ i n t = 1 10 Variables of thread 1 are shared_int = 1 p r i v a t e _ i n t = 0 f i r s t p r i v a t e _ i n t = 1 11 Variables of thread 11 are shared_int = 1 p r i v a t e _ i n t = 0 f i r s t p r i v a t e _ i n t = 1 12 Variables of thread 5 are shared_int = 1 p r i v a t e _ i n t = 0 f i r s t p r i v a t e _ i n t = 1 13 ======================================= 14 Variables of thread 0 are shared_int = 6 p r i v a t e _ i n t = 1 f i r s t p r i v a t e _ i n t = 2 15 Variables of thread 8 are shared_int = 6 p r i v a t e _ i n t = 1 f i r s t p r i v a t e _ i n t = 2 16 Variables of thread 9 are shared_int = 6 p r i v a t e _ i n t = 1 f i r s t p r i v a t e _ i n t = 2 17 Variables of thread 2 are shared_int = 6 p r i v a t e _ i n t = 1 f i r s t p r i v a t e _ i n t = 2 18 Variables of thread 1 are shared_int = 6 p r i v a t e _ i n t = 1 f i r s t p r i v a t e _ i n t = 2 19 Variables of thread 10 are shared_int = 6 p r i v a t e _ i n t = 1 f i r s t p r i v a t e _ i n t = 2 20 Variables of thread 11 are shared_int = 6 p r i v a t e _ i n t = 1 f i r s t p r i v a t e _ i n t = 2 21 Variables of thread 3 are shared_int = 6 p r i v a t e _ i n t = 1 f i r s t p r i v a t e _ i n t = 2 22 Variables of thread 5 are shared_int = 6 p r i v a t e _ i n t = 1 f i r s t p r i v a t e _ i n t = 2 23 Variables of thread 7 are shared_int = 6 p r i v a t e _ i n t = 1 f i r s t p r i v a t e _ i n t = 2 24 Variables of thread 4 are shared_int = 6 p r i v a t e _ i n t = 1 f i r s t p r i v a t e _ i n t = 2 25 Variables of thread 6 are shared_int = 6 p r i v a t e _ i n t = 1 f i r s t p r i v a t e _ i n t = 2 Kde je chyba?

OpenMP - proměnné 1 i n t main ( i n t argc, char argv ) 2 { 3 i n t shared_int ( 1 ), p r i v a t e _ i n t ( 1 ), f i r s t p r i v a t e _ i n t ( 1 ) ; 4 #pragma omp p a r a l l e l shared ( shared_int ), private ( p r i v a t e _ i n t ), 5 f i r s t p r i v a t e ( f i r s t p r i v a t e _ i n t ) 6 { 7 #pragma omp c r i t i c a l 8 std : : cout << "Variables of thread " 9 << omp_get_thread_num ( ) << " are" 10 << " shared_int = " << shared_int 11 << " private_int = " << p r i v a t e _ i n t 12 << " firstprivate_int = " << f i r s t p r i v a t e _ i n t 13 << std : : endl ; 14 #pragma omp b a r r i e r 15 #pragma omp c r i t i c a l 16 shared_int ++; 17 p r i v a t e _ i n t ++; 18 f i r s t p r i v a t e _ i n t ++; 19 #pragma omp b a r r i e r 20 #pragma omp s i n g l e 21 std : : cout << "=======================================" << std : : endl ; 22 #pragma omp c r i t i c a l 23 std : : cout << "Variables of thread " 24 << omp_get_thread_num ( ) << " are" 25 << " shared_int = " << shared_int 26 << " private_int = " << p r i v a t e _ i n t 27 << " firstprivate_int = " << f i r s t p r i v a t e _ i n t 28 << std : : endl ; 29 } 30 return EXIT_SUCCESS ; 31 }

OpenMP - proměnné 1 i n t main ( i n t argc, char argv ) 2 { 3 i n t shared_int ( 1 ), p r i v a t e _ i n t ( 1 ), f i r s t p r i v a t e _ i n t ( 1 ) ; 4 #pragma omp p a r a l l e l shared ( shared_int ), private ( p r i v a t e _ i n t ), 5 f i r s t p r i v a t e ( f i r s t p r i v a t e _ i n t ) 6 { 7 #pragma omp c r i t i c a l 8 std : : cout << "Variables of thread " 9 << omp_get_thread_num ( ) << " are" 10 << " shared_int = " << shared_int 11 << " private_int = " << p r i v a t e _ i n t 12 << " firstprivate_int = " << f i r s t p r i v a t e _ i n t 13 << std : : endl ; 14 #pragma omp b a r r i e r 15 #pragma omp atomic 16 shared_int ++; 17 p r i v a t e _ i n t ++; 18 f i r s t p r i v a t e _ i n t ++; 19 #pragma omp b a r r i e r 20 #pragma omp s i n g l e 21 std : : cout << "=======================================" << std : : endl ; 22 #pragma omp c r i t i c a l 23 std : : cout << "Variables of thread " 24 << omp_get_thread_num ( ) << " are" 25 << " shared_int = " << shared_int 26 << " private_int = " << p r i v a t e _ i n t 27 << " firstprivate_int = " << f i r s t p r i v a t e _ i n t 28 << std : : endl ; 29 } 30 return EXIT_SUCCESS ; 31 }

OpenMP - atomické instrukce pragma atomic způsobí použití atomických instrukcí pro přístup do paměti není to tak obecné jako kritická sekce, ale je to efektivnější Atomické instrukce jde o instrukce procesoru, jejichž zpracování nemůže přerušit jiné vlákno

OpenMP - určení souběžných úloh Po spuštění více vláken je nutné říci, co mají jednotlivá vlákna provádět. všechna vlákna provádějí stejnou úlohu = dělí se o for cyklus každé vlákno provádí jinou úlohu = zpracovávají sekce (sections) různého kódu

OpenMP - paralelizace for cyklů #pragma omp for[clause list] Klauzule pro ošetření proměnných: private firstprivate reduction lastprivate = hodnota proměnné je nastavena v posledním průběhu for cyklu

OpenMP - paralelizace for cyklů Klausule pro rozdělení iterací mezi vlákny - schedule schedule( schedulling_class[,parameter]) Třídy: static dynamic guided runtime

OpenMP - statické přidělování iterací schedule( static[, chunk-size] ) Každé vlákno postupně dostává stejný počet iterací daný pomocí chunk-size. Není-li chunk-size uvedeno, jsou všechny iterace rozděleny na n stejných částí, kde n je počet vláken. Příklad: 128 iterací, 4 vlákna schedule( static ) = 4 32 iterací schedule( static, 16 ) = 8 16 iterací

OpenMP - dynamické přidělování iterací schedule( dynamic[, chunk-size] ) Funguje podobně jako dynamické přidělovaní iterací. Nové iterace jsou ale přidány vláknu, které skončí svou práci jako první. Některá vlákna tak mohou provést více iterací, než ostatní.

OpenMP - řízené přidělování iterací schedule( guided[, chunk-size] ) Příklad: 100 iterací rozdělených po 5 20 kousků pro 16 vláken. guided s každým přidělením nových iterací exponenciálně zmenšuje chunk size. chunk-size udává dolní mez pro počet přidělených iterací.

OpenMP - přidělování iterací určené za chodu programu schedule(runtime) Podle systémové proměnné OMP_SCHEDULE se určí, zda se má použít static, dynamic nebo guided. Vhodné při vývoji programu pro zjištění nejvhodnější volby.

OpenMP - synchronizace mezi jednotlivými for cykly Standardně se nezačíná nový cyklus, dokud všechna vlákna neskončila práci na předchozím cyklu - bariéra mezi cykly. Pokud to není nutné, lze použít klauzuli nowait. #pragma omp parallel { #pragma omp for nowait for( i = 0; i < nmax; i ++ ){... } #pragma omp for for( i = 0; i < mmax; i ++ ){... } }

OpenMP - zpracování různých úloh každým vláknem Provádí se pomocí direktivy omp sections: #pragma omp parallel { #pragma omp sections { #pragma omp section { TaskA(); } #pragma omp section { TaskB(); } } }

OpenMP - zkrácené psaní direktiv Lze psát: #pragma omp parallel for shared(n) #pragma omp parallel sections

OpenMP - vložení direktivy parallel Musí být nastavena systémová proměnná OMP_NESTED = TRUE. #pragma omp parallel for... for( i = 0; i < N; i ++ ) #pragma omp parallel for... for( j = 0; j < N; j ++ ) #pargma omp paralle for... for( k = 0; k < N; k ++ ) #pragma omp parallel for...

OpenMP - kritické bloky Příklad: Částečné úlohy pro jednotlivá vlákna lze distribuovat pomocí centrální struktury (fronty). Přístup k ní pak může mít v daný okamžik jen jedno vlákno.

OpenMP - kritické bloky - příklad #pragma omp parallel sections { #pragma omp section { /* producer thread */ task = producer_task(); #pragma omp critical (task_queu) { insert_into_queu( task ); } } #pragma omp parallel section { /* consumer thread */ #pragma omp critical (task_queu) { task = extract_from_queu(); } } }

Funkce knihovny OpenMP Je nutné použít hlavičkový soubor #include <omp.h> void omp_set_num_threads( int num_threads); int omp_get_num_threads(); int omp_get_thread_num(); int omp_get_num_procs(); int omp_in_paralle();

Systémové proměnné OMP_NUM_THREADS setenv OMP_NUM_THREADS 8 OMP_DYNAMIC umožňuje použití funkci omp_set_num_threads nebo klauzuli num_threads setenv OMP_DYNAMIC TRUE OMP_NESTED OMP_SCHEDULE setenv OMP_SCHEDULE static,4 setenv OMP_SCHEDULE dynamic setenv OMP_SCHEDULE guided

Ošetření dat v OpenMP všechny proměnné, které používá jen jedno vlákno, by měly být označené jako private při častém čtení proměnné nastavené již dříve v programu je vhodné označit ji jako firstprivate přístup všech vláken ke stejným datům je vhodné provádět pomocí lokálních proměnných (vzhledem k vláknu) a nakonec použít redukci přistupují-li vlákna k různým částem velkého bloku dat, je dobré je předem explicitně rozdělit zbývající typ proměnných již musí být zřejmě sdílen

OpenMP - skalární součin Ukázka paralelizace skalárního součinu: 1 double scalarproductsequential ( const double v1, 2 const double v2, 3 const i n t size ) 4 { 5 double res ( 0.0 ) ; 6 for ( i n t i = 0; i < size ; i ++ ) 7 res += v1 [ i ] v2 [ i ] ; 8 return res ; 9 } 10 11 double s c a l a r P r o d u c t P a r a l l e l ( const double v1, 12 const double v2, 13 const i n t size ) 14 { 15 double res ( 0.0 ) ; 16 #pragma omp p a r a l l e l for r e d u c t i o n ( + : res ), 17 schedule ( s t a t i c ), 18 f i r s t p r i v a t e ( v1, v2 ) 19 for ( i n t i = 0; i < size ; i ++ ) 20 res += v1 [ i ] v2 [ i ] ; 21 return res ; 22 }

OpenMP - skalární součin 4 1 2 4 6 3 1 2 4 8 3 12 16 Parallel speed-up 2 Parallel speed-up 2 1 1 0 256 1k 4k 16k 64k 256k 1M 4M 16M 64M 256M 0 256 1k 4k 16k 64k 256k 1M 4M 16M 64M 256M Array size Array size Obrázek : Paralelní urychlení získané při výpočtu skalárního součinu na Intel i7 5820K (2x6 vlaken) a 2x Intel Xeon E5 2630 (2x2x8 vláken).