ŽILINSKÁ UNIVERZITA V ŽILINE FAKULTA RIADENIA A INFORMATIKY

PLATFORMA PRE PODPORU VYUŽITIA VÝPOýTOVÉHO VÝKONU GRAFICKÝCH KARIET V MULTIAGENTOVÝCH SIMULAýNÝCH MODELOCH

Dizertaþná práca

28360020143008

Študijný program: Aplikovaná informatika Pracovisko: Fakulta riadenia a informatiky, Katedra dopravných sietí ŠkoliteĐ: doc. Ing. Norbert Adamko, PhD.

Žilina, 2014 Ing. Miroslav Mintál Poćakovanie

Rád by som sa poćakoval tým, ktorí mi pomáhali poþas štúdia a poskytovali mi cenné rady ku tejto práci. Hlavná vćaka patrí školiteĐovi doc. Ing. Norbertovi Adamkovi, PhD. Tak isto by som chcel poćakovaĢ doc. Ing. ďudmile Jánošíkovej, PhD., za vedenie poþas prvých dvoch rokov štúdia. Ćalej by som rád poćakoval kolegom a priateĐom Ing. Michalov Vargovi, Ing. Anne Kormanovej a Ing. Michalovi Kocifajovi, s ktorými sme poþas nášho spoloþného doktorandského štúdia pracovali na rozširovaní využitia simulácii. Tiež by som sa rád poćakoval mojej rodine, za podporu ktorú mi dávala. Abstrakt

Táto práca sa zaoberá rozšírením agentovej architektúry o možnosti využitia výpoþtového výkonu grafických kariet. Pre užívateĐsky komfortné využívanie grafických kariet je vytvorená platforma. Platforma je založená na aplikaþnom rámci OpenCL, þo jej umožĖuje využiĢ široké spektrum grafických kariet, ale aj iné výpoþtové zariadenia, ako napríklad procesory. V práci sú popísané všetky funkcie poskytované platformou, ako automatická inicializácia najvýkonnejšieho výpoþtového zariadenia, automatické kopírovanie dát medzi operaþnou pamäĢou poþítaþa a grafickej karty, spolu s konverziou typov týchto dát do jazyka používaného v OpenCL alebo generovanie þastí kódu. Poskytnuté sú viaceré sériovo vykonávané algoritmy, ale aj paralelné algoritmy optimalizované pre použitie na grafických kartách. Platforma je integrovaná do vybranej agentovej architektúry, þim rozširuje túto architektúru o jednoduché využitie výpoþtového výkonu grafických kariet. Rozšírením architektúry je umožnené vytváraĢ väþšie a zložitejšie modely, ktoré budú môcĢ byĢ vypoþítané za kratší þas. Použitie a overenie platformy je demonštrované na viacerých príkladoch, vrátane použitia v simulaþnom nástroji PedSim. V tomto nástroji sa navrhnutá platforma používa na urýchlenie spracovania dát pred simuláciou, ako aj na výpoþet pohybu chodcov poþas simulácie. Abstract

This thesis deals with extension of an agent architecture by option to use computational power of graphics cards. A platform is created for user friendly usage of the cards. This platform is based on OpenCL framework that enables it to exploit a wide spectrum of graphics cards as well as another computational devices, such as processors. The thesis describes all functions provided by the platform, such as automatic initialisation of the most powerful computational device, automatic data copying between standard and graphics card memory, data types conversion into programming language employed in OpenCL and code generation. Multiple serial algorithms and some parallel ones optimised for graphics cards are provided. Platform is integrated into chosen agent architecture and widens its capabilities by simple usage of the computational power of graphics cards. This architecture extension allows the user to create bigger and more complex models with shorter computational time. Application and verification of the platform is demonstrated on several examples including simulation tool PedSim. The proposed platform is here utilised to accelerate the data processing before simulation run and to compute the pedestrians’ movement during the simulation run itself. Obsah

1 Ciele práce ...... 12 2 Simulácia a druhy simulácii ...... 14 2.1 Agentovo orientovaná simulácia...... 16 3 Architektúra grafickej karty ...... 18 3.1 Hierarchia pamätí grafickej karty ...... 19 3.2 Usporiadanie vlákien ...... 21 4 Návrh platformy pre využitie GPU na všeobecné výpoēty ...... 23 4.1 Softvérové rámce využívajúce výpoētový výkon GPU ...... 23 4.1.1 CUDA ...... 24 4.1.2 OpenCL ...... 24 4.1.3 DirectCompute ...... 25 4.1.4 Stream ...... 25 4.2 Porovnanie technológii ...... 25 4.3 Návrh vlastnej platformy ...... 27 4.3.1 Inicializácia výpoētového zariadenia ...... 28 4.3.2 Kernel ...... 30 Zadávanie algoritmu pre výpoēet ...... 30 Prenos dát ...... 33 Spustenie výpoētu ...... 37 Zotavenie sa pri chybe v algoritme pre GPU ...... 38 Meranie rýchlosti výpoētu ...... 40 4.3.3 Prístup k OpenCL objektom...... 40 4.3.4 Knižnice poskytované platformou ...... 41 Euklid ...... 41 Prefix scan ...... 41 Triedenie ...... 44 4.3.5 Popis ēastí platformy ...... 47 5 Rozšírenie agentovej architektúry pre využitie výpoētového výkonu grafických kariet ...... 49 5.1 Simulaēné nástroje využívajúce GPU ...... 49 5.1.1 Simulaēné modely implementované priamo pre GPU ...... 49 5.1.2 Simulaēné aplikaēné rámce používajúce GPU ...... 50 5.2 Vybrané agentové architektúry ...... 53 5.2.1 Agentová architektúra ABAsim ...... 54 5.3 Rozšírenie architektúry ABAsim ...... 56 5.3.1 Optimalizácie výpoētu poēas simulácie ...... 58 Zámena operácii za natívne a jednoduchšie pre GPU ...... 58 Optimalizácia využitia pamäte ...... 58 Zmena usporiadania vlákien ...... 58 Použitie rôznych kernelov na dosiahnutie rovnakého výpoētu ...... 59 Optimalizácie podporované platformou...... 59 5.3.2 Interakcia s BDI ...... 60 5.3.3 Popis ēastí platformy umožŸujúce jej použitie v ABAsim ...... 61 6 Praktické použitie a overenie použiteűnosti navrhnutej platformy ...... 63 6.1 Sēítanie vektorov ...... 63 6.2 Násobenie matíc...... 68 6.2.1 Výpoēet dynamických agentov ...... 73 6.3 Výpoēet pohybu chodcov ...... 75 6.4 Automatický výber vhodného kernelu ...... 78 7 Záver ...... 82 8 Príloha ē.1 Programátorská príruēka k platforme ...... 89 8.1 Inicializácia výpoētových zariadení...... 89 8.1.1 Globálne nastavenia ...... 90 8.2 Kernel...... 91 8.3 Prenos dát ...... 94 8.4 Spustenie výpoētu ...... 95 8.5 Výpoēty v simulácii ...... 95 8.6 Použitie platformy ...... 97 Zoznam obrázkov

Obrázok 1: Funkcie agenta (Adamko, 2013) ...... 17 Obrázok 2: Rozdiel medzi CPU a GPU (Nvidia, 2010) ...... 19 Obrázok 3: Hierarchia pamätí grafických kariet (Fabber, 2010) ...... 20 Obrázok 4: Usporiadanie vlákien (Nvidia, 2010) ...... 22 Obrázok 5: Štruktúra kompilovaného kódu...... 32 Obrázok 6: Prenosová rýchlosƛ pamätí grafickej karty ...... 34 Obrázok 7: Zarovnanie záznamov ...... 36 Obrázok 8: Paralelný výpoēet prefix sum (Chen, 2012) ...... 42 Obrázok 9: Iteratívny scan väēších polí (Hurbert, 2007) ...... 43 Obrázok 10: Použitie operácie Scan na redukciu poűa ...... 44 Obrázok 11: Triediaca sieƛ bitonic sortu ...... 45 Obrázok 12: Radix sort pre grafické karty ...... 46 Obrázok 13: Zjednodušený UML diagram Kernelu a jeho závislostí ...... 47 Obrázok 14: Ukážka Sugarscape simulácie(Lynsenko et al., 2008) ...... 51 Obrázok 15: Ukažka simulácie pomocou GPGPU, űavo skutoēnosƛ, pravo simulácia (Richmond et al., 2008b) ...... 52 Obrázok 16: Dvojvrstvový model agentov v architektúre ABAsim (Adamko, 2013) ...... 55 Obrázok 17: Zjednodušený UML diagram tried závislých na simulácii ...... 62 Obrázok 18: Porovnanie ēasov výpoētu sēítavania polí ...... 66 Obrázok 19: Pomer ēasu výpoētu s prenosom dát k samotnému výpoētu ...... 67 Obrázok 20: as výpoētu násobenia matíc pomocou platformy a procesora ...... 70 Obrázok 21: Zrýchlenie výpoētu matice pomocou platformy oproti CPU ...... 72 Obrázok 22: Veűkosƛ matice, pri ktorej platforma je rýchlejšia ako CPU ...... 73 Obrázok 23: Vyhodnocované bunky chodca v Local Cells ...... 76 Obrázok 24: Infraštruktúra použitá pri testovaní Local Cells (Varga a Mintál, 2014) ...... 76 Obrázok 25: Porovnanie ēasov výpoētov Local Cells ...... 77 Obrázok 26: Chodci vykonávaný na grafických kartách (Varga a Mintál, 2014)...... 78 Obrázok 27: as výpoētu rôznych kernelov, toho istého pohybu ...... 79 Obrázok 28: Pravdepodobnosƛ použitia kernelu pre výpoēet pohybu chodca ...... 80 Obrázok 29: Vyhladená pravdepodobnosƛ použitia kernelov ...... 81 Obrázok 30: Ukážkové príklady použitia platformy ...... 97 Obrázok 31: Ukážka meniteűného kódu spúšƛanom na grafických kartách ...... 98 Zoznam tabuliek

Tabuűka 1: Porovnanie hlavných termínov používaných v CUDA a OpenCL ...... 18 Tabuűka 2: Typy zariadení podporované platformou...... 89 Tabuűka 3: Príkazy na identifikovanie vlákna poēas výpoētu...... 92

Zoznam Algoritmov

Algoritmus 1: Sēítanie vektorov pomocou platformy ...... 64 Algoritmus 2: Násobenie matíc pomocou platformy ...... 68 Algoritmus 3: Optimalizovaný kód násobenia matíc implementovaný v platforme ...... 71 Algoritmus 4: Výpoēet pohybu vozíka pomocou platformy ...... 74 Zoznam skratiek a pojmov

ABAsim – Agent based architecture of simulation models

Framework – Aplikaþný rámec

BDI – Belief-Desire-Intention

CPU – Central processing unit

CUDA – Compute Unified Device Architecture

Fallback – Mechanizmus používajúci záložné stratégie, ktoré umožĖujú pokraþovaĢ v þinnosti pri chybe alebo nedostupnosti hlavného zariadenia.

GPU –

HLSL – High-level language

OpenCL – Open Computing Language

OSimPack – Object simulation package

SIMD – Single Instruction Multiple Data

SPMD – Single Program Multiple Data Úvod 10

Úvod

Všade okolo nás existujú javy a udalosti, ktoré je možné modelovaĢ agentmi. Agent reprezentuje objekt, ktorý dokáže samostatne fungovaĢ a kooperovaĢ s inými agentmi tak, aby dosiahol stanovený cieĐ. Pomocou agentov dokážeme modelovaĢ aj zložité správanie a fungovanie sveta okolo nás. Na tento úþel môžeme použiĢ viacerých agentov a vytváraĢ veĐmi zložité multiagentové modely. Takto dokážeme simulovaĢ zložité a Ģažko opísateĐné správanie komplexných systémov.

Existuje veĐké množstvo simulaþných modelov, v ktorých viacerí agenti vykonávajú tú istú þinnosĢ. Napríklad pri simulácii dopravy v mestách, sa každé auto riadi rovnakými pravidlami, pri simulácii mraveniska, každý druh mravca vyhodnocuje situáciu rovnako, alebo pri evakuácii Đudí, každý typ þlovek sa dá modelovaĢ tým istým agentom. Naskytuje sa možnosĢ týchto agentov poþítaĢ paralelne, kećže viacerí agenti vykonávajú rovnakú þinnosĢ. Okrem toho že všetci vykonávajú ten istý algoritmus, je ešte jedna dôležitá þrta týchto agentov pre výpoþet na grafických kartách a to, že týchto agentov je väþšie množstvo. Ak máme úlohu, ktorá sa dá rozdeliĢ na þiastkové výpoþty a každá jej þasĢ je vykonávaná podĐa rovnakého algoritmu, poskytuje sa nám možnosĢ, optimálne využiĢ výpoþtovú silu grafických kariet.

Preto sa v práci zaoberám využitím grafických kariet v multiagentových simulaþných modeloch. Presunutím výpoþtov agenta na grafickú kartu sa dá zrýchliĢ výpoþet simulácie a tým sa nám otvára možnosĢ simulovaĢ modely, ktorých þas výpoþtu bol veĐmi dlhý, alebo vykonaĢ väþší poþet simulácii za rovnaký þas, þím získame presnejšie výsledky. Taktiež môžeme simulovaĢ omnoho zložitejšie modely.

Práca sa skladá z ôsmych kapitol. Prvá kapitola popisuje cieĐ práce a jeho dekompozíciu na þiastkové ciele práce. Nasledujúca kapitola zaþína popisom rôznych druhov simulácií. V ćalšej kapitole je popísaná architektúra grafickej karty. Ćalšia kapitola popisuje analýzu a návrh platformy pre všeobecné využitie výpoþtového výkonu grafických kariet. Piata kapitola opisuje výber architektúry, ktorá je rozšírená o navrhnutú platformu umožĖujúcu využívaĢ grafické karty poþas simulácie. Nasleduje kapitola popisujúca používanie platformy na jednoduchých ukážkach. Predposledná kapitola sa zaoberá Úvod 11 vyhodnotením experimentov. V závere je zhrnutý prínos práce a možnosti ćalšieho rozvoja platformy. Ciele práce 12

1 Ciele práce

Hlavným cieĐom práce je návrh a implementácia platformy, ktorá umožní využitie výpoþtového výkonu grafických kariet v existujúcej agentovej architektúre. Na splnenie tohto cieĐa je potrebné vybraĢ vhodnú agentovú architektúru, ktorá bude rozšírená o využitie výpoþtového výkonu grafických kariet. Potom je nutné vybraĢ vhodný aplikaþný rámec, ktorý bude použitý pre vytvorenie platformy umožĖujúcej využitie výpoþtového výkonu grafických kariet. Následne bude potrebné rozšíriĢ architektúru pre používanie platformy poþas simulácie.

SúþasĢou hlavného cieĐa by mali byĢ nasledujúce þiastkové ciele:

1. Automaticky detegovaĢ podporované grafické karty a získaĢ o nich informácie, ktoré budú slúžiĢ na výber najvýkonnejšej z nich a pre optimálne rozloženie výpoþtu.

2. RozšíriĢ vybranú agentovú architektúru o možnosĢ presunu výpoþtov realizovaných dynamickými agentmi na grafickú kartu.

3. NavrhnúĢ a implementovaĢ podporu pre presun dát potrebných pri výpoþte medzi grafickou kartou a operaþnou pamäĢou poþítaþa.

4. VytvoriĢ algoritmus automatickej alokácie výpoþtov agentov a ich zoskupovania na základe poþtu a vlastností stream procesorov grafických kariet.

5. UmožniĢ vytváraĢ aspoĖ jednoduché simulaþné modely bez nutnosti hlbšieho oboznamovania sa s architektúrou grafickej karty.

6. VytvoriĢ knižnicu algoritmov optimalizovaných pre grafické karty

Po návrhu a implementácii platformy, podĐa predošlých þiastkových cieĐov, bola platforma otestovaná z hĐadiska použiteĐnosti a výkonnosti. Rozhodli sme sa, že pri návrhu platformy preskúmame aj možnosti optimalizácie výpoþtov priamo poþas simulácie. To je vhodné najmä v situáciách, ak je simulácia zložitá a mali by sme k dispozícii viaceré algoritmy pre ten istý výpoþet. Práca bude obsahovaĢ ešte nasledujúce ciele:

1. PreskúmaĢ možnosĢ optimalizácie výpoþtov poþas simulácie pri zložitejších agentoch a v situáciách s meniacim sa poþtom agentov. Ciele práce 13

2. OveriĢ použiteĐnosĢ a efektívnosĢ výslednej platformy vo zvolenej oblasti. Simulácia a druhy simulácii 14

2 Simulácia a druhy simulácii

Definícia simulácie podĐa (Kaviþka et al., 2005) je nasledovná: „Simulácia je výskumná technika, ktorej podstatou je náhrada skúmaného dynamického systému (originálu) jeho simulujúcim systémom (simulaþným modelom), s ktorým sa experimentuje s cieĐom získaĢ informácie o pôvodnom dynamickom systéme.“

Simulácia nachádza uplatnenie v širokom spektre odvetví a þím ćalej, tým sa þastejšie používa. Hlavnou výhodou simulácie je, že nemusíme robiĢ zmeny v skúmanom systéme a aj napriek tomu získame výsledky o tom, ako by sa systém správal za predpokladaných podmienok. To je užitoþné hlavne v prípade, keć potrebujeme testovaĢ hypotézy, ktorých realizácia by mohla zapríþiniĢ ujmu na zdraví, životoch alebo testovanie týchto hypotéz na skúmanom systéme by bolo finanþne veĐmi nároþné.

Nato aby sme získali relevantné výsledky, je nutné dostatoþne poznaĢ skúmaný systém, aby bolo jasné þo je možné zanedbaĢ a ktoré informácie pre modelovanie þinnosti systému sú nutné v þo najpodrobnejšej forme. Zo skúmaného systému sa dá modelovaĢ veĐké množstvo rôznych modelov, podĐa toho þo zanedbáme a na þo sa sústredíme. Model je nutné vytváraĢ podĐa toho, þo chceme skúmaĢ, aby sme nezanedbali podstatné informácie potrebné pre skúmanú oblasĢ. Na modelovaný systém vplývajú rôzne faktory z okolia. Pri simulácii je nutné braĢ do úvahy aj tieto vplyvy, ktoré sa jednotne oznaþujú ako okolie systému.

PodĐa þasového hĐadiska môžeme simuláciu deliĢ na:

x Diskrétna simulácia - mení svoj stav len v diskrétnych okamihoch a to pri ukonþení aktivity. Celá simulácia pozostáva z naplánovaných aktivít a stav simulácie sa medzi týmito aktivitami nemôže zmeniĢ. Ukonþenie diskrétnej aktivity a následná zmena systému sa nazýva udalosĢ.

x Spojitá simulácia - mení svoj stav v krátkych þasových intervaloch poþas celej doby simulácie. Zmeny stavu modelu sú poþítané pomocou diferenciálnych rovníc, ktoré sa rátajú v krátkych krokoch.

x Kombinovaná simulácia – je využívaná keć je nutné þasĢ modelu simulovaĢ diskrétne a þasĢ spojite. Simulácia a druhy simulácii 15

PodĐa metodológie modelovania je možné simuláciu deliĢ na viaceré druhy popísané (Borshchev et al., 2004). Medzi nich patria:

x Systémová dynamika zbavuje model jednotlivých prvkov a model poníma ako ovplyvĖujúce sa toky a vzĢahy medzi nimi, þím sa výrazne odlišuje od ostatných metodológii modelovania. Takúto metódu ako prvý sformuloval Forrester (1968).

x Udalostná simulácia sa dá popísaĢ ako následnosĢ aktivít, ktoré modelujú þinnosti a môžu plánovaĢ ćalšie aktivity. Na základe þasovej existencie aktivity môžeme byĢ aktivita spojitá alebo diskrétna.

x Agentová simulácia reprezentuje prístup, kde základnou jednotkou je agent. Agenti sú autonómni, þiže dokážu pracovaĢ samostatne a plniĢ svoj cieĐ. Pritom sú schopní navzájom kooperovaĢ a týmto spôsobom plniĢ aj spoloþný komplikovanejší cieĐ.

Ćalej je možné simuláciu deliĢ podĐa toho, ako detailne modelujeme modelovaný systém:

x Makroskopická simulácia nerozlišuje entity systému ako jednotlivcov, ale skupiny entít vyjadruje matematickými reprezentáciami (napr. ako prúdy - využíva tzv. tokové modely). Stav modelu makroskopickej simulácie je charakterizovaný hustotou, priepustnosĢou, vyĢažením a pod.

x Mezoskopická simulácia predstavuje stupeĖ medzi makroskopickou a mikroskopickou simuláciou. Mezoskopické modely rozoznávajú jednotlivcov, ale popisujú ich charakteristiky viac všeobecne (napr. rýchlosĢ rozdelením pravdepodobnosti) a interakcie medzi nimi nie sú podrobne sledované.

x Mikroskopická simulácia pristupuje k entitám v simulaþnom modely ako k individuálnym prvkom, ktoré so systémom a ostatnými entitami interagujú. Tento druh simulácie modeluje systém do veĐkých podrobností.

x Hybridná simulácia umožĖuje simulovaĢ modeli pozostávajúce z viacerých þastí, ktoré sú modelované rôznou detailnosĢou. Simulácia a druhy simulácii 16

2.1 Agentovo orientovaná simulácia

Agentovo orientovaná simulácia má viaceré výhody oproti iným prístupom, hlavne pri modelovaní komplexných systémov. PodĐa Mathiasa (2010) je multiagentový systém dynamickým systémom, zloženým z množstva vzájomne interagujúcich, aktívnych a autonómnych prvkov, agentov. Využitie nachádza v rôznych oblastiach, ako napríklad pri simulácii správania sa chodcov, cestnej doprave, migrácii zvierat, alebo simulácii pohybu krvných buniek.

Agenta môžeme podĐa Jenningsa definovaĢ takto: „Agent je zapuzdrený poþítaþový systém, vložený do nejakého prostredia, schopný v tomto systéme pružne a autonómne konaĢ tak, aby naplnil stanovené ciele.“ (Jennings, 2001)

Vlastnosti agentov podĐa Kaviþku (2005) sú nasledovné:

x AutonómnosĢ - agent dokáže pracovaĢ samostatne, bez intervencií z okolia.

x Spoloþenské správanie - dokáže komunikovaĢ s ostatnými agentami pomocou definovaného rozhrania.

x ReaktívnosĢ - dokáže reagovaĢ na okolie.

x IniciatívnosĢ - agent nereaguje len na okolie, ale správa sa proaktívne.

Aby agent mohol spĎĖDĢ všetky tieto vlastnosti, musí sa skladaĢ z viacerých prvkov. V každom agentovi je možné identifikovaĢ viacero prvkov, ktoré sú zodpovedné za funkcie agenta. Ich komplexnosĢ špecifikuje výslednú podobu agenta. Obrázok 1 zobrazuje základné funkcie agenta a vzĢahy medzi nimi. Simulácia a druhy simulácii 17

Obrázok 1: Funkcie agenta (Adamko, 2013) Architektúra grafickej karty 18

3 Architektúra grafickej karty

Grafické karty majú rôzne architektúry, ale z pohĐadu aplikaþných rámcov1 je ich možné popísaĢ jednotným spôsobom. Aplikaþné rámce na využitie ich výpoþtového výkonu sú pomerne nové a pri potrebe využitia plného potenciálu grafických kariet je potrebné pochopiĢ ich architektúru. Pri popise architektúry, z programátorského hĐadiska, sa najviac používajú pojmy z aplikaþných rámcov CUDA, alebo OpenCL. Architektúra grafických kariet je popísaná pomocou pojmov uvedených v tabuĐke 1. TabuĐka obsahuje aj ekvivalentné pojmy v anglickom jazyku, používané v CUDA a OpenCL.

TabuĐka 1: Porovnanie hlavných termínov používaných v CUDA a OpenCL Prvok systému OpenCL CUDA Globálna pamäĢ Global Memory Global Memory Lokálna pamäĢ Local Memory Shared Memory Privátna pamäĢ Private Memory Local Memory Vlákno Work-item Thread Skupina vlákien Work-group Thread-block Usporiadanie skupiny vlákien / NDRange Grid of thread blocks Všetky vlákna jedného výpoþtu

Pre spustenie programu na grafickej karte je nutné, aby kód obsahoval aspoĖ jednu hlavnú funkciu nazývanú kernel. Kernel je typ funkcie, ktorý je možné spustiĢ na grafickej karte pomocou aplikaþného rámca. Túto funkciu budú vykonávaĢ všetky vlákna na ktorých sa spustí výpoþet. Rozdiel medzi výpoþtami jednotlivých vlákien je možné dosiahnuĢ pomocou použitia identifikátorov vlákien. Program môže obsahovaĢ viacero takýchto funkcií a tie môžu byĢ na novších grafických kartách spracovávané paralelne, pri dostaþujúcom poþte výpoþtových jednotiek (Nvidia, 2010).

Základným rozdielom medzi CPU a GPU je poþet paralelne spustiteĐných vlákien, ktoré sa dajú spustiĢ paralelne. PokiaĐ na súþasných procesoroch sú to maximálne desiatky, na najnovších grafických kartách je možné spustiĢ až desiatky tisíc vlákien. Rozdiel je aj akým spôsobom sú spracované a prideĐované inštrukcie. Procesory majú oproti grafickým kartám oveĐa viacej kontrolných jednotiek pripadajúcich na výpoþtové jednotky.

1 Pod aplikaēným rámcom rozumieme anglické pomenovanie framework. Architektúra grafickej karty 19

Na procesoroch sú inštrukcie spracovávané a prideĐované jednou kontrolnou jednotkou pre jednu, alebo iba malý poþet výpoþtových jednotiek. Pri GPU sa urþitému poþtu výpoþtových jednotiek (podĐa architektúry 32 (Nvidia), 64 (AMD)) spracuje a pridelí rovnaká inštrukcia. Tým sa ušetrí miesto na þipe, ktoré by zaberali jednotky spracúvajúce inštrukcie a ostáva viac miesta pre výpoþtové jednotky. Znázornené je to na obrázku 2. K ušetreniu miesta dopomáha aj hierarchická štruktúra pamätí popísaná v ćalšom bloku.

Obrázok 2: Rozdiel medzi CPU a GPU (Nvidia, 2010)

To že viacerým vláknam sa prideĐujú rovnaké inštrukcie programátora neobmedzuje až tak, ako by sa mohlo zdaĢ. Ak budú maĢ vlákna pod jednou jednotkou spracúvajúcou inštrukcie vykonaĢ rôzne inštrukcie, vykonajú sa postupne a výsledky sa uložia pre tie vlákna, ktoré mali vykonaĢ inštrukciu. Tie vlákna, ktoré by kód nemali vykonávaĢ, nebudú modifikovaĢ dáta a kód sa spracuje správne, ale spracuje sa pomalšie v závislosti od poþtu vetvení kódu.

3.1 Hierarchia pamätí grafickej karty

Grafické karty nemajú len jednu pamäĢ, ale hierarchickú štruktúru pamätí znázornenú na obrázku 3. Na tomto obrázku WorkItem znázorĖuje jedno vlákno. Každému vláknu sú pridelené registre a privátna pamäĢ. Táto privátna pamäĢ by sa mala používaĢþo najmenej, kećže v skutoþnosti sa nachádza v pomalej globálnej pamäti. Vlákna v skupine majú prístup k spoloþnej rýchlej lokálnej pamäti. Táto pamäĢ je vhodná, ak všetky vlákna zo skupiny pracujú nad rovnakými údajmi, kećže je malá (rádovo desiatky kB pre všetky vlákna v skupine) a rýchla (dá sa porovnávaĢ s registrami). Globálnu pamäĢ, ktorej veĐkosĢ je väþšinou udávaná pri kúpe grafických kariet, je najpomalšia a najväþšia z pamätí na grafickej karte. Z uvedených faktov vyplýva, že je výhodné do lokálnej pamäti naþítaĢ dáta Architektúra grafickej karty 20 z globálnej pamäti, ak sa v skupine budú tieto dáta intenzívne používaĢ. V globálnej pamäti sa nachádza ešte konštantná a textúrová pamäĢ, ktoré sú prístupné cez vyrovnávaciu pamäĢ pre rýchlejší prístup. Textúrová pamäĢ sa v OpenCL nespomína, pretože tento štandard podporuje aj iné výpoþtové zariadenia okrem grafických kariet, ktoré túto pamäĢ nemusia maĢ. V prípade že pracujeme s grafickou kartou, dá sa k tejto pamäti pristúpiĢ cez funkcie pracujúce s obrázkami.

Obrázok 3: Hierarchia pamätí grafických kariet (Fabber, 2010)

Vlákna majú prístup na þítanie aj zápis do všetkých pamätí, okrem konštantnej a textúrovej pamäte. Z konštantnej pamäte môžu len þítaĢ a pri textúrovej pamäti musí byĢ dopredu dané, þi budú môcĢ len þítaĢ alebo len zapisovaĢ. Pri zápise do lokálnej, alebo do globálnej pamäte, môže dôjsĢ k prepísaniu dát, súþasným zápisom viacerých vlákien do rovnakého pamäĢového priestor. Pre ošetrenie tohto problému, sa pri lokálnej pamäti najþastejšie používa bariérová synchronizácia vlákien v skupine, alebo aj zápis pomocou atomických operácii. Pri globálnej pamäti je možné použiĢ iba atomické operácie. Bariérová synchronizácia medzi všetkými vláknami neexistuje, aby paralelný kód bol vykonávaný rýchlejšie. Tým že neexistuje bariérová synchronizácia medzi všetkými vláknami, môžeme vytváraĢ viac skupín, ako je možné naraz spustiĢ. Skupiny, ktoré nemohli byĢ paralelne Architektúra grafickej karty 21 spustené, budú spracované po dokonþení aktuálne vykonávaných skupín. Kebyže existuje bariérová synchronizácia medzi všetkými vláknami, musel by sa pred synchronizáciou ukladaĢ celý stav skupiny vlákien, ktoré nemohli byĢ paralelne spustené a po synchronizácii sa tento stav obnoviĢ. To by bolo veĐmi nároþné na zdroje aj na þas.

3.2 Usporiadanie vlákien

Vlákno reprezentuje jeden paralelný výpoþet na grafickej karte. Ak chceme spustiĢ výpoþet na grafickej karte, musíme špecifikovaĢ koĐko vlákien sa má spustiĢ. Ak by grafická karta nemala dostatok zdrojov na spustenie požadovaného poþtu vlákien, spustí maximálny poþet a po ich dokonþení spustí ćalšie, až kým sa nevykonajú všetky. Vláknam sú pri spustení priradené globálne identifikátory, ktoré sú používané na ich rozlíšenie, inak by všetky vykonávali rovnaké výpoþty.

Vlákna nemusia byĢ usporiadané len v poli, ale aj do dvojrozmernej, alebo trojrozmernej matice. Vtedy je nutné zadaĢ poþet vlákien v každom rozmere. Dvojrozmerné usporiadanie sa využíva napríklad pri spracovaní obrázkov a trojrozmerné napríklad v medicíne pri voxelových snímkach. Pri viacrozmernom usporiadaní majú vlákna viacprvkové identifikátory, ktoré spoloþne tvoria jednoznaþný identifikátor. Architektúra grafickej karty 22

Obrázok 4: Usporiadanie vlákien (Nvidia, 2010)

Vlákna spúšĢané na grafických kartách tvoria hierarchiu. Všetky vlákna, nad ktorými sa spustí výpoþet, sa skladajú zo skupín vlákien a skupiny sa skladajú z jednotlivých vlákien. Dvojrozmerné usporiadanie vlákien aj skupín je možné vidieĢ na obrázku 4. Skupiny môžu byĢ usporiadané v poli alebo dvojrozmernej matici. Vlákna majú okrem globálnych identifikátorov aj identifikátory v rámci skupiny. Návrh platformy pre využitie GPU na všeobecné výpoēty 23

4 Návrh platformy pre využitie GPU na všeobecné výpoþty

Aby sme mohli rozšíriĢ existujúcu simulaþnú architektúru o výpoþty na grafických kartách, je nutné najprv dokázaĢ využiĢ výpoþtový výkon grafických kariet. Z tohto dôvodu sú v tejto kapitole porovnané aplikaþné rámce umožĖujúce výpoþty na grafických kartách. Za pomoci vybratého rámca je navrhnutá platforma, ktorá umožni jednoduché využitie ich výpoþtového výkonu, bez nutnosti hlbšieho oboznamovania sa s architektúrou grafických kariet. Navrhnutú platformu budeme môcĢ použiĢ na rozšírenie existujúcej agentovej architektúry o využitie výpoþtového výkonu grafických kariet.

4.1 Softvérové rámce využívajúce výpoþtový výkon GPU

Na grafickú kartu sa dá zjednodušene pozeraĢ, ako na procesor s veĐkým množstvom jadier. Pri bližšom pohĐade sa však vo viacerých þastiach líši. V procesoroch má väþšinou každé jadro svoju kontrolnú jednotku, ktorá dekóduje inštrukcie a prideĐuje vykonávanie aritmetickým jednotkám. Z toho dôvodu môže každé jadro vykonávaĢ inštrukcie nezávisle. Pri grafickej karte existujú bloky, ktoré majú spoloþnú kontrolnú jednotku, ktorá priradí vykonanie jednej inštrukcie všetkým aritmetickým jednotkám v skupine. Takáto architektúra sa oznaþuje ako SIMD (Single Instruction Multiple Data) a programy vytvárané pre grafické karty sú typu SPMD (Single Program Multiple Data). Tento rozdiel medzi architektúrami je znázornený na obrázku 2.

Pre využitie výpoþtového výkonu grafických kariet existujú viaceré technológie. V nedávnej minulosti sa využívali grafické karty len na spracovanie obrazového obsahu. Keć dosiahli vyšší výpoþtový výkon ako vtedajšie procesory, zaþalo sa uvažovaĢ o ich využití aj v iných oblastiach. Vtedy však neexistovali žiadne aplikaþné rámce na jednoduché využitie tohto výkonu. Kvôli ich absencii boli pokusy o využitie výpoþtového výkonu pomocou špeciálnych inštrukcií týchto kariet. Dáta sa prenášali ako textúry a programovalo sa špecificky pre každú kartu. Takéto programovanie sa oznaþovalo ako GPGPU (General- purpose computing on graphics processing units). Tento pojem sa v súþasnosti používa aj na všeobecné využitie výkonu grafických kariet, bez ohĐadu na použitý aplikaþný rámec.

Existujú viaceré aplikaþné rámce na využitie tohto potenciálu. Medzi najznámejšie patria tieto:

x CUDA (Compute Unified Device Architecture) (Kirk et al., 2010) Návrh platformy pre využitie GPU na všeobecné výpoēty 24

x OpenCL (Nvidia, 2013)

x DirectCompute (Nvidia, 2014b)

x Stream (Winkle, 2009) (už nie je podporovaný)

Každá z nich má urþité výhody aj nevýhody. Postupne si popíšeme ich charakteristické vlastnosti.

4.1.1 CUDA

CUDA je architektúra, ktorá umožĖuje využívaĢ GPU na všeobecné výpoþty (Nvidia, 2013). Bola vytvorená spoloþnosĢou NVIDIA a pracuje len na niektorých grafických kartách vyrábaných touto spoloþnosĢou (Nvidia, 2014a). Aj keć grafické karty tejto spoloþnosti sú rozšírené, podiel na trhu si delia s inými spoloþnosĢami, preto je využitie tejto architektúry obmedzené. CUDA bola uvedená v roku 2007. NakoĐko bola uvedená ako prvá na trh, veĐa vývojárov ju zaþalo používaĢ a z tohto dôvodu je aj najznámejšia. Poskytuje aj viaceré knižnice s algoritmami optimalizovanými pre vykonávanie na grafických kartách, ako napríklad cuFFT (Nvidia, 2012) pre Fourierovú transformáciu a cuBLAS (Barrachina, 2008) pre akcelerovanie základných lineárnych algebrických rutín.

Pre programovanie v CUDA sa oficiálne dá použiĢ upravený jazyk C. Pri kompilovaní sa þasti urþené pre grafickú kartu skompilujú špeciálnym prekladaþom a zvyšná þasĢ sa skompiluje C kompilátorom pre CPU. Existuje aj možnosĢ programovaĢ v širokej škále iných programovacích jazykov pomocou produktov tretích strán. V súþasnosti je CUDA vo verzii 5.5, ktorá zlepšila hlavne možnosti identifikovania miest, kde sa dá zrýchliĢ výpoþet vykonávaný na GPU.

4.1.2 OpenCL

OpenCL je otvorený štandard pre paralelné programovanie v heterogénnych systémoch vytvorený skupinou Khronos (Nvidia, 2011). Každý výrobca výpoþtového zariadenia môže implementovaĢ tento štandard. Tým získa programátor jednotný prístup ku týmto zariadeniam pomocou spoloþného aplikaþného rámca. V súþasnosti sa dá využiĢ OpenCL pre výpoþty na väþšine súþasných grafických kariet, procesorov, ARM procesorov a ćalej sa rozširuje na programovateĐné FPGA obvody. Návrh platformy pre využitie GPU na všeobecné výpoēty 25

Verejne bol uvedený viac ako rok po architektúre CUDA. Z tohto dôvodu, aj napriek širokej podpore hardvéru, nie je tak rozšírený ako CUDA. Taktiež používa upravený jazyk C, ale používa iné kĐ~þové slová ako CUDA. Kećže nám dovoĐuje používaĢ väþšie spektrum hardvéru, inicializácia je dlhšia, aby bolo možné špecifikovaĢ ktorý hardvér chceme použiĢ a ako ho chceme použiĢ. Aktuálna je verzia 2.0, ktorá pridáva hlavne spoloþnú virtuálnu pamäĢ. Túto verziu však výrobcovia výpoþtových zariadení ešte neimplementovali a preto sa používa verzia 1.2.

4.1.3 DirectCompute

DirectCompute je aplikaþný rámec vytvorený firmou Microsoft pre využitie GPU na všeobecné výpoþty. Tento aplikaþný rámec je súþasĢou Microsoft DirectX a to verzie 11, no bol spätne implementovaný aj do verzie 10 (Nvidia, 2014b). DirectCompute je možné využiĢ len v operaþnom systéme Windows a to od verzie Windows Vista, kećže len tieto operaþné systémy podporujú DirectX 10 a vyššie. Ćalším rozdielom od predchádzajúcich dvoch je, že programy pre grafickú kartu sa nevytvárajú priamo v jazyku C, ale pomocou HLSL (High- level shader language) (St-laurel, 2005). Z dôvodu obmedzenia len na vybrané verzie operaþných systémov a podporu len grafických kariet, sa tento aplikaþný rámec takmer vôbec nepoužíva na generické výpoþty.

4.1.4 Stream

Stream bol aplikaþný rámec vyvinutý spoloþnosĢou AMD. Tak ako pôvodný aplikaþný rámec CTM (Close to Metal), tak aj Stream boli aplikaþné rámce, ktoré mali umožniĢ využiĢ grafické karty znaþky AMD na všeobecné výpoþty. Pravdepodobne kvôli malej rozšírenosti týchto aplikaþných rámcov ich AMD prestalo podporovaĢ. Od roku 2011 AMD pridalo podporu OpenCL 1.1 a od vtedy podporuje hlavne tento aplikaþný rámec na využitie ich grafických kariet pre všeobecné výpoþty.

4.2 Porovnanie technológii

V tejto þasti sú porovnávané len aplikaþné rámce CUDA a OpenCL, kećže sú najrozšírenejšie. Stream a CTM nie sú porovnávané, pretože boli prakticky nahradené aplikaþným rámcom OpenCL a naćalej už nie sú podporované ich tvorcami. Nebola nájdená žiadna implementácia agentovo orientovanej simulácie implementovaná pomocou DirectCompute a rozšírenie DirectCompute v iných oblastiach je minimálne. Z týchto Návrh platformy pre využitie GPU na všeobecné výpoēty 26 dôvodov, ako aj z dôvodov obmedzenosti na urþité verzie operaþných systémov, DirectCompute nie je zahrnutý v porovnávaní. Metódy používajúce pôvodné programovanie priamo pre GPU tiež nie sú porovnávané z toho dôvodu, že sú zbytoþne komplikované oproti terajším aplikaþným rámcom a hardvérovo neprenosné.

Vo svojom þlánku autori Karimi a spol. (2010) porovnávali aplikaþné rámce CUDA a OpenCL. Zameriava sa hlavne na rozdiel výkonu poþas výpoþtu, pretože inicializácia grafickej karty, kopírovanie dát a vytváranie výpoþtu pre grafickú kartu sa v týchto aplikaþných rámcoch líši. OpenCL kompiluje kernel poþas vykonávania programu, þo predlžuje þas vykonávania programu. Výhodu to má v možnosti optimalizácie kódu pre danú grafickú kartu. CUDA je vyvinutá firmou vyrábajúcou grafické karty urþené pre tento aplikaþný rámec a preto môže lepšie optimalizovaĢ výsledný kód pre tieto grafické karty.

Na porovnávanie použili Adiabatic QUantum Algorthms (AQUA) (Mosca, 2012). ýo je Monte Carlo simulácia quantového spinu. Vytvorené kernely sa líšili minimálne a to len v kĐ~þových slovách a výpoþte indexu poĐa. Na generovanie náhodných þísel použili generátor Mersenne-Twister (Matsumoto, 1998) Z porovnania rovnakých algoritmov na rovnakej grafickej karte vyšli nasledujúce výsledky. Presun dát pomocou OpenCL bol približne o 46% pomalší ako pri CUDA. Výpoþet na grafickej karte bol pri OpenCL o 27% pomalší oproti CUDA. PodĐa týchto výsledkov sa v závere vyjadrili, že pre aplikácie kritické na þas je vhodné použiĢ CUDA. Ak ale už vlastníme grafickú kartu ktorá podporuje len OpenCL, je možné použiĢ aj tú.

Aktuálnejšie porovnanie robili Fang, Varbanescu a Sips (2011). Porovnávanie vykonávali na šestnástich rôznych príkladoch. Spoþiatku im vyšlo že pri väþšine aplikácii je CUDA o 30% rýchlejšia oproti OpenCL. Ćalej prišli na to, že tieto výsledky im vyšli kvôli neférovému porovnávaniu. Zistili že pri povolení optimalizácie kódu v OpenCL, im vychádzali podobné þasy ako pomocou CUDA vo všetkých príkladoch okrem jedného. V tomto príklade urobili manuálnu zmenu a potom aj ten dosahoval podobné þasové výsledky. Pri férovom porovnávaní im vychádzali podobné výkonnostné výsledky pre oba aplikaþné rámce. PodĐa ich zhodnotenia, prenositeĐnosĢ OpenCL nemá vplyv na jeho výkon a je dobrou alternatívou oproti CUDA.

K podobnému záveru prišli aj autori Komatsu a spol. (2010), ktorí porovnávali aplikaþné rámce CUDA a OpenCL na menšom poþte príkladov. Pri priamom porovnaní im vyšli výsledky pre OpenCL pomalšie. Keć však použili OpenCL prepínaþe pri kompilácii Návrh platformy pre využitie GPU na všeobecné výpoēty 27 pre lepší preklad kódu, výsledky porovnania þasu im pre obe aplikaþné rámce vychádzali skoro rovnaké, okrem jedného príkladu. V tomto jednom príklade urobili manuálnu optimalizáciu a potom im už vychádzali podobné þasy.

Z þlánkov porovnávajúcich aplikaþné rámce vyplýva, že z pohĐadu výkonu, by pri správnom použití nemal byĢ výkonový rozdiel medzi CUDA a OpenCL. Ostatné aplikaþné rámce sme vylúþili kvôli ich veĐkým obmedzeniam. Ako základ pre našu platformu sme si zvolili aplikaþný rámec OpenCL. Zvolený bol z dôvodu jeho multiplatformovosti a podobných výkonnostných výsledkov ako CUDA.

Tým že sme si zvolili OpenCL, budeme môcĢ vykonávaĢ výpoþty na každom výpoþtovom zariadení, ktoré implementuje podporu pre OpenCL. ýo predstavuje prakticky všetky súþasné grafické karty. Tiež nám umožní spustiĢ výpoþet na všetkých jadrách procesora, ak by sa v poþítaþi nenachádzala grafická karta. Ak by poþítaþ obsahoval iné zariadenie podporujúce OpenCL, navrhnutá platforma umožní spustiĢ výpoþet taktiež aj na tomto zariadení.

Tým sme však prišli o výhody, ktoré poskytuje CUDA. Jedná sa hlavne o zanedbanie inicializácie. CUDA poskytuje možnosĢ špecifikovaĢ, na ktorej Nvidia grafickej karte sa majú vykonávaĢ výpoþty, ale ak to nezadáme, tak sa automaticky budú vykonávaĢ na jednej z grafických kariet Nvidia. V OpenCL je nutné explicitne definovaĢ, na akom výpoþtovom zariadení sa má výpoþet vykonaĢ. Ćalej sme taktiež prišli o knižnice s implementovanými algoritmami pre grafické karty.

4.3 Návrh vlastnej platformy

Napriek tomu že existuje veĐké množstvo platforiem, je Ģažké presne definovaĢ pojem platforma. Vo všeobecnosti sa jedná o prostredie, ktoré umožĖuje spustiĢ softvér, ktorý využíva zdroje poskytované platformou, priþom musí rešpektovaĢ jej obmedzenia. Medzi reprezentantov platforiem patria napríklad hardvérové prvky, operaþné systémy, ale aj knižnice, aplikaþné rámce, virtuálne stroja a iné.

Saver (2013) sa pri definícii platformy veĐmi zameriava na dôležitosĢ poskytnúĢ zákazníkovi þo najviac a kvalitných aplikácii pracujúcich v platforme. Popri tom ale rovnako vymedzuje platformu ako softvér, umožĖujúci spúšĢDĢ kód vytvorený pre danú platformu. Návrh platformy pre využitie GPU na všeobecné výpoēty 28

Naša platforma sa zameriava na poskytnutie výpoþtového výkonu grafických kariet. Na to, aby platforma poskytovala užívateĐsky prívetivý prístup, je potrebné riešiĢ nasledujúce body:

x Automatickú inicializáciu grafických kariet.

x Jednoduché zadávanie dát.

x Nenároþné zadávanie vykonávaného kódu.

x Jednoduché spustenie výpoþtu. V nasledujúcich podkapitolách sú postupne popisované jednotlivé þasti navrhovanej platformy. Najprv sú popísané možnosti inicializácie platformy a automatická inicializácia. Nasleduje popis zadávania algoritmu pre výpoþet, spôsoby prenosu dát, podpora zotavenia pri chybe v programe a možnosti merania zrýchlenia výpoþtu. Posledná podkapitola popisuje implementované paralelné funkcie poskytované platformou.

4.3.1 Inicializácia výpoþtového zariadenia

Jednou z výhod OpenCL je, že podporuje viaceré heterogénne zariadenia, þo však prináša nutnosĢ inicializovaĢ tieto zariadenia. Pritom je potrebné vytvoriĢ OpenCL objekty ako Context, Command Queue a Device. OpenCL automatický neinicializuje zariadenie lebo nemôže vedieĢ ktoré zariadenie má používaĢ a zároveĖ poþítaþ vôbec nemusí obsahovaĢ zariadenie podporujúce OpenCL. V platforme chceme využívaĢ na výpoþet predovšetkým grafické karty a pri detekcii viacerých kariet chceme použiĢ tú najvýkonnejšiu. Takéto požadované výpoþtové zariadenie je možné identifikovaĢ. Po detekcii tohto zariadenia, by bolo možné automaticky vytvoriĢ všetky objekty, ktoré sú potrebné pre výpoþty na tejto karte.

Navrhovaná platforma podporuje užívateĐský prívetivú automatickú inicializáciu nasledujúcim spôsobom. Pri prvom volaní niektorej z jej poskytovaných funkcii, ktoré potrebujú maĢ dostupné výpoþtové zariadenie, skontroluje þi platforma už bola inicializovaná. Ak zistí že nebola, pokúsi sa nájsĢ zariadenia podporujúce OpenCL. Najprv zistí, þi v poþítaþi sa nachádzajú grafické karty podporujúce OpenCL. Ak sa nachádzajú, tak ich inicializuje, a ako primárnu na používanie vyberie najvýkonnejšiu. Pre výber najvýkonnejšej grafickej karty sa porovnávajú frekvencie GPU a poþty výpoþtových jednotiek. Bolo by možné maĢ databázu názvov grafických kariet usporiadanú podĐa výkonu, þo by poskytlo presnejší výber najvýkonnejšej grafickej karty. Táto databáza by Návrh platformy pre využitie GPU na všeobecné výpoēty 29 však þasom neobsahovala najnovšie grafické karty. Ak platforma nenájde podporovanú grafickú kartu, skúsi nájsĢ podporovaný procesor, alebo iné výpoþtové zariadenie podporujúce OpenCL. Ak takýchto zariadení nájde viacero, vyberie to najvýkonnejšie z nich.

Automatická inicializácia platformy sa nevykonáva hneć po štarte programu, ale po prvom volaní funkcie, ktorá vyžaduje zariadenie na výpoþty. Tento návrh vyplýva z viacerých dôvodov, medzi ktoré patria nasledujúce:

x Umožnenie manuálneho vybratia výpoþtového zariadenia.

x Ak sa platforma v programe nepoužije, vôbec ho nespomalí svojou inicializáciou.

x Týmto spôsobom je možné sa vyvarovaĢ þiastoþnej, alebo chybovej implementácii OpenCL.

x platformu je možné deaktivovaĢ a žiadne implementované výpoþty sa nespustia.

Platforma poskytuje možnosĢ zvolenia si výpoþtového zariadenia použitého na výpoþty. Túto þinnosĢ umožĖuje vykonaĢ viacerými spôsobmi. Medzi užívateĐsky jednoduchší prístup patrí zadanie typu výpoþtového zariadenia. Zo zariadení zadaného typu platforma vyberie to najvýkonnejšie zariadenie, ak takéto zariadenie bude dostupné. Medzi typy výpoþtových zariadení patria grafické karty, procesor, špecializované výpoþtové zariadenia. K týmto typom je pridaná aj špeciálna možnosĢ fallback. Fallback primárne inicializuje grafickú kartu. Ak žiadnu nenájde, tak sa snaží inicializovaĢ najvýkonnejšie výpoþtové zariadenie nachádzajúce sa v poþítaþi, ktoré podporuje OpenCL. Táto možnosĢ sa používa aj pri automatickej inicializácii. Ćalšou možnosĢou je, že platforma poskytne zoznam dostupných zariadení podporujúcich OpenCL a používateĐ si môže vybraĢ, ktoré z nich sa použije.

Platforma podporuje zadávanie vykonávaného kódu, definovaním súboru v ktorom sa nachádza a ukladanie þasov výpoþtu. Tieto funkcie sú popísané v ćalšej podkapitole. Pri inicializácii je možné nastaviĢ adresáre, kde sa tieto súbory budú nachádzaĢ. Takto je napríklad umožnené zbieraĢ þasy trvania výpoþtov, aj keć program bude prístupný len na þítanie. Návrh platformy pre využitie GPU na všeobecné výpoēty 30

4.3.2 Kernel

Pre použitie grafických kariet na všeobecné výpoþty je potrebné vykonaĢ viacero krokov. Ak už máme inicializovanú grafickú kartu, je potrebné poskytnúĢ algoritmus, ktorý sa má vykonaĢ, dáta ktoré algoritmus spracúva a spustiĢ výpoþet. Pre poskytnutie užívateĐského komfortu môžu byĢ tieto kroky vykonané nad jedným objektom. Tento objekt sa v platforme oznaþuje ako kernel.

Objekt ponúka jednoduchý spôsob priradenia algoritmu, ktorý bude vykonávaĢ každé vlákno a jednoduché priradenie dát, ktoré sa môžu nachádzaĢ ešte na procesore a následné spustenie výpoþtu jedným príkazom. Platforma sa postará o inicializáciu grafickej karty. PodĐa zadaných dát vygeneruje typy a štruktúry v jazyku C99, ktorý používa OpenCL pre kód vykonávaný na zariadeniach. Tieto štruktúry použije na vygenerovanie hlaviþky hlavnej funkcie, do ktorej vloží používateĐov algoritmus. Takto vytvorený kód skompiluje s pomocnými funkciami. Ak sa v užívateĐovom algoritme nachádzala chyba, umožní mu ho opraviĢ bez prerušenia behu hlavného programu. Takto pripravený objekt je následne možné jedným volaním nechaĢ vykonávaĢ na výpoþtových zariadeniach a pomocou jednoduchých volaní vkladaĢ a získavaĢ nové dáta.

V nasledujúcich podkapitolách je postupne popísané ako funguje spracovanie zadaného kódu, konverzia vstupných a výstupných dát a ich automatické kopírovanie medzi pamäĢami a následne spustenie výpoþtu. Ćalej je popísané detegovanie chýb v užívateĐovom algoritme a podporované možnosti opravy. Ako posledné sú popísané možnosti merania zrýchlenia výpoþtu.

Zadávanie algoritmu pre výpoþet

Kód pre výpoþtové zariadenia je potrebné vytváraĢ v jazyku C, presnejšie vo verzii C99 (ISO/IEC 9899:1999) s urþitými rozšíreniami a obmedzeniami (Munshi, 2011). Medzi rozšírenia patrí napríklad podpora viacrozmerných typov, identifikátory vlákien, alebo vstavané matematické a geometrické funkcie. Medzi obmedzenia patrí napríklad nemožnosĢ použitia rekurzie, poþas výpoþtu nie je možné vytváraĢ dynamické polia, alebo nedostupnosĢ niektorých štandardných knižníc. Všetky rozšírenia a obmedzenia je možné nájsĢ v špecifikácii OpenCL (Munshi, 2011).

Pre zadávanie kódu by bolo možné navrhnúĢ vlastný jazyk, alebo použiĢ na zadávanie programu vývojový diagram, prípadne špecifikovaný XML dokument, tak ako Návrh platformy pre využitie GPU na všeobecné výpoēty 31 to je v prípade aplikaþného rámca FLAME GPU (Richmond, 2011b). Vykonávaný algoritmus sa v platforme zadáva v jazyku C. Je to z toho dôvodu, že rovnaký prístup sa používa v OpenCL, CUDA, ako aj vo výpoþtových rámcov založených na nich. Takto vytvorený algoritmus, je následne jednoduchšie prenositeĐný do iného aplikaþného rámca. Taktiež, jazyk C je pomerne rozšírený a pri inom prístupe, ako diagramoch alebo XML, by bolo nutné sa tento nový prístup najprv nauþLĢ, þo by predĎžilo þas prvotného nasadenia platformy.

Každé vlákno na grafickej karte vykonáva rovnaký program. Aby vlákna spracovávali rôzne dáta, alebo vykonali odlišné inštrukcie, musia obsahovaĢ kód, ktorý dokáže rozlíšiĢ jednotlivé vlákna. Vlákna sa vedia diferencovaĢ podĐa svojho identifikátora. Identifikátor majú lokálny a globálny. Globálny je unikátny pre všetky spustené vlákna aktuálneho výpoþtu a lokálny je unikátny v rámci skupiny. Ak sú vlákna usporiadané do viacrozmernej štruktúry, identifikátory sú viacrozmerné. Ćalej majú dostupné informácie o veĐkosti skupiny a poþte všetkých vlákien, ako aj poþte dimenzií v ktorých sú usporiadané. Majú prístupný aj identifikátor skupiny, aj keć ten je možné odvodiĢ z predošlých dvoch identifikátorov a veĐkosti skupiny.

Platforma používa OpenCL na skompilovanie kódu, ktorý sa má vykonávaĢ. Pritom užívateĐ zadáva len telo hlavnej funkcie, prípadne pomocné funkcie a platforma všetok zvyšný kód doplní. Robí to takým spôsobom, že vytvorí dlhý reĢazec z tela hlavnej funkcie, užívateĐských funkcii a doplneného kódu. V Ėom sa nachádzajú aj príkazy na použitie ćalších súborov, ako napríklad base.h, ktorý definuje makrá pre identifikáciu vlákna. Štruktúru výsledného reĢazca je možné vidieĢ na obrázku 5. Zelenou farbou sú zvýraznené komponenty generované platformou a modrou farbou sú zvýraznené komponenty ktoré zadáva užívateĐ. ýiarkovanou þiarou sú vyznaþené komponenty, ktoré nemusia byĢ obsiahnuté vo výslednom kóde. UžívateĐ môže urþLĢþi sa majú tieto þasti generovaĢ, alebo nie. Takto vytvorený reĢazec je potom možné skompilovaĢ. Návrh platformy pre využitie GPU na všeobecné výpoēty 32

Obrázok 5: Štruktúra kompilovaného kódu.

Program ktorý sa má vykonaĢ je možné zadaĢ viacerými spôsobmi. Najprv si rozoberieme prípad, keć algoritmus je reprezentovaný jednou funkciou. Túto funkciu budú vykonávaĢ všetky vlákna paralelne. Hlaviþku tejto funkcie nemusíme zadávaĢ. Tú vygeneruje platforma podĐa zadaných parametrov, þo bude bližšie popísané v nasledujúcej podkapitole. Teda staþí zadaĢ len telo funkcie. To je možné zadaĢ, buć ako reĢazec znakov do atribútu kernelu pri jednoduchších funkciách, alebo zadaĢ názov súboru v ktorom sa nachádza telo funkcie. Druhá možnosĢ ma viaceré výhody. Medzi tie patria napríklad možnosĢ zmeniĢ kód tela, bez toho aby bolo nutné znovu kompilovaĢ hlavný program. Tiež môžeme zmeniĢ telo funkcie aj vtedy, keć nemáme prístup k zdrojovým kódom hlavného programu. Prináša to však aj nevýhodu v tom, že implementácia vlastných algoritmov je zverejnená aj v prípade, že je to nežiaduce. To je možné obísĢ zadaním algoritmu priamo do kódu programu a nenaþítavaĢ ho z externého súboru. V budúcnosti by bolo možné doplnením podpory naþítania zašifrovaných zdrojových súborov obísĢ túto nevýhodu. Použitie externého súboru má ešte jednu výhodu, ktorá je podrobnejšie popísaná v kapitole 4.3.2.4. Tá umožĖuje pri syntaktickej chybe v tele hlavnej funkcie zobraziĢ popis chyby. Po Návrh platformy pre využitie GPU na všeobecné výpoēty 33 oprave chyby, platforma program pre grafickú kartu znova skompiluje a pokraþuje vo vykonávaní programu, bez nutnosti vypnúĢ a znovu zapnúĢ hosĢovský program.

Niekedy je potrebné rozdeliĢ kód na niekoĐko funkcií. Napríklad z dôvodov opakovania sa rovnakého kódu na viacerých miestach, alebo kvôli logickému deleniu programu, alebo z hĐadiska þitateĐnosti programu. Tieto ćalšie funkcie bude rovnako možné zadaĢ priamo ako reĢazec, alebo ich naþítaĢ z externého súboru.

Kompilovanie programu pre grafické karty je v platforme nastavené s OpenCL prepínaþom –Werror. To znamená že upozornenia kompilátora sú brané ako chyby v kóde a výpoþet sa nespustí kým nebudú opravené. Je to z toho dôvodu, že programy pre grafickú kartu sú nároþné na nájdenie logických chýb. Upozornenia, ktoré nám ukáže kompilátor, môžu pomôcĢ k nájdeniu viacerých logických chýb.

Prenos dát

Na to aby mohol prebehnúĢ výpoþet na grafickej karte, je potrebné maĢ prístup k dátam, ktoré sa používajú pri výpoþte. Pri výpoþte na procesore sa dáta vyskytujú väþšinou v RAM, prípadne už v cache alebo registroch. Pri grafických kartách môžu byĢ dáta v jednej alebo vo viacerých z pamätí grafickej karty, alebo grafická karta môže pristupovaĢ priamo do RAM poþítaþa. Prístup do pamäti poþítaþa je mnohonásobne pomalší voþi akejkoĐvek pamäti grafickej karty. To je zobrazené na obrázku 6, ktorý popisuje orientaþné rýchlosti pamätí pre architektúru grafických kariet Kepler od Nvidia. RýchlosĢ 1TB pri lokálnej pamäti sa dosiahne agregovaným prístupom viacerých vlákien. Návrh platformy pre využitie GPU na všeobecné výpoēty 34

Obrázok 6: Prenosová rýchlosĢ pamätí grafickej karty

Preto je nutné zabezpeþLĢ presun dát na grafickú kartu pred výpoþtom a späĢ do pamäte RAM po výpoþte.

Dáta sú zadávané do kernelu a sú brané ako parametre hlavnej funkcie. Navrhovaná platforma rozdeĐuje zadávanie dát na dve þasti. V prvej je nutné definovaĢ aký typ dát a pod akým názvom parametra chceme používaĢ. V ćalšom kroku môžeme pomocou názvu atribútu posielaĢ dáta na grafickú kartu alebo späĢ z nej naþítaĢ dáta. Pre rýchlejšie zadávanie je možné tieto dva kroky vykonaĢ aj naraz. Tým že dáta sú chápané ako parametre je zjednodušené zadávanie dát. Takýto prístup ponúka hneć niekoĐko zlepšení oproti zadávaniu dát pomocou OpenCL. Medzi tieto výhody patria nasledujúce:

x Konverziu typov z Object Pascal (Delphi) do C.

x Vytvorenie hlaviþky hlavnej funkcie s parametrami.

x Prístup k parametrom pomocou mien.

x Vytváranie potrebnej pamäte na GPU pri kopírovaní dát.

x Priradenie skopírovaných dát ako parameter hlavnej funkcie.

Automatická konverzia typov je veĐmi silný pomocník, pri ktorom staþí zadaĢ iba typ každého parametra a platforma ho sama skonvertuje na rovnaký typ v jazyku C. Bez tejto podpory by bolo nutné prepisovaĢ všetky dátové typy manuálne do jazyka C. Ak používame zložitejšie záznamy (v Object Pascal oznaþovaný ako Record) môžeme pri prepisovaní Návrh platformy pre využitie GPU na všeobecné výpoēty 35 urobiĢ chybu, alebo parametre nazvaĢ rozdielne a tým pádom môže skôr dôjsĢ k omylom v ćalšom kóde. Tým nás táto funkcia ochraĖuje pred chybou pri prepisovaní typov a ćalších chýb z nich vyplývajúcich.

Na konverziu typov medzi jazykom Object Pascal (používaný v Delphi) a jazykom C, sa využíva Run-time type information (RTTI) (Gajic, 2014). PodĐa detegovaného typu platforma vie zistiĢ aký prislúchajúci typ v jazyku C má vytvoriĢ. Podporuje všetky základné typy, ktoré jednoducho konvertuje pomocou zámeny kĐ~þových slov. Ćalej záznamy z ktorých vytvorí C dátový typ struct, so všetkými atribútmi obsiahnutými v zázname. Takisto statické a dynamické polia, ktoré skonvertuje na statické polia. Pri dynamických poliach sa pamäĢ alokuje až keć sa zadajú dáta. Tieto polia sa môžu skladaĢ zo základných typov, alebo tiež zo záznamov.

Pri konverzii záznamov na struct môžu nastaĢ viaceré problémy so zarovnaním atribútov. Zaþiatok atribútu musí byĢ zarovnaný podĐa veĐkosti dátového typu atribútu. Tieto veĐkosti sú najþastejšie 2, 4 a 8 bitov (Bryant a O'Hallaron, 2010). V prípade, že by po menšom dátovom type nasledoval väþší dátový typ, tak väþší dátový typ sa nebude nachádzaĢ hneć za predošlým typom, ale bude posunutý o toĐko bitov, aby zaþínal na adrese, ktorá je násobkom 2, 4 alebo 8. Toto sa deje kvôli tomu, aby väþší dátový typ bol správne zarovnaný a aj všetky nasledujúce atribúty. V opaþnom prípade by pre naþítanie jedného atribútu mohlo byĢ potrebné naþítaĢ väþší blok zarovnaných dát, kećže dáta sa väþšinou þítajú po blokoch. Tým by došlo k spomaleniu pri práci so záznamami. Takto upravený záznam sa nemusí rovnako upraviĢ aj na grafickej karte. Pri kopírovaní by sa dáta posunuli a buć by neboli konzistentné, alebo by sa zapísali mimo pridelenú pamäĢ. Z toho dôvodu je odporúþané maĢ v záznamoch zoradené dátové typy od najväþších po najmenšie. Pri takomto usporiadaní nedochádza k posúvaniu dátových typov v rámci záznamu. DodržaĢ túto podmienku môže byĢ obþas nároþné a zdĎhavé na zisĢovanie veĐkostí dátových typov. Z toho dôvodu platforma automaticky vypína zarovnávanie typov na grafických kartách a vstupné záznamy musia byĢ oznaþené ako packed. Takto sa docieli, že budú správne pracovaĢ akékoĐvek záznamy. Na obrázku 7 je znázornený záznam nachádzajúci sa na nasledujúcich riadkoch v nezarovnanej a v zarovnanej forme na 4 bity. Návrh platformy pre využitie GPU na všeobecné výpoēty 36

RExample = record a: Char; b: Integer; c: Char; end;

Obrázok 7: Zarovnanie záznamov

Kećže poznáme názvy všetkých parametrov vstupujúcich do výpoþtov a aj ich dátové typy, tým pádom je možné vygenerovaĢ hlaviþku hlavnej funkcie, spúšĢanej na grafickej karte. Staþí pre každý parameter pridaĢ správny adresný priestor a polia zmeniĢ na pointer na prvok poĐa. Nutnou podmienkou však je, aby pred kompiláciou boli dostupné všetky parametre, ináþ by sa kompilácia zastavila na nezadefinovanej premennej.

Jednou z nevýhod pri použití OpenCL je, že prístup k parametrom hlavnej funkcie je len cez poradové þísla. Na identifikovanie parametra sa nedá použiĢ meno parametra. Takto je nutné si pamätaĢ ktorý parameter je na ktorom mieste a správne posielaĢ a þítaĢ dáta z výpoþtového zariadenia. Pri zámene poradia väþšinou dôjde k pádu celého programu, alebo k zlým výsledkom spúšĢaného algoritmu. Keby niekto v kóde pre výpoþtové zariadenie zmenil poradie atribútov, program by prestal správne fungovaĢ. Aj z tohto dôvodu sa hlaviþka, spolu s parametrami funkcie, automaticky generuje. Oproti OpenCL, platforma podporuje prístup k parametrom pomocou mena. To uĐahþuje prácu s parametrami a zároveĖ eliminuje chyby spôsobené zámenou poradia parametrov.

Pri zadávaní dát sa musia vykonaĢ operácie, ktoré platforma musí robiĢ automatický, ale v OpenCL sa musia volaĢ samostatne. Medzi ne patrí v prvej fáze automatické alokovanie pamäĢového priestoru na grafickej karte, ak už v tom okamihu poznáme presnú Návrh platformy pre využitie GPU na všeobecné výpoēty 37 veĐkosĢ dát. V druhej fáze taktiež alokovanie pamäte, ak už nie je správnej veĐkosti a dealokovanie pôvodnej pamäte. Následne sa odkaz na novú pamäĢ pridelí ako parameter hlavnej funkcie. Pri uvoĐĖovaní kernelu sa uvoĐĖujú aj všetky jeho parametre. Ak tieto parametre nie sú spoloþné pre viaceré kernely, je automatický dealokovaná aj pamäĢ na grafickej karte.

Platforma umožní prideliĢ parameter jedného kernelu ako parameter inému kernelu. Tým sa umožní spúšĢanie viacerých algoritmov za sebou, ktoré budú vykonávané nad spoloþnými dátami. Dáta budú ostávaĢ na grafickej karte a ušetrí sa þas kopírovania dát do pamäte poþítaþa a späĢ na grafickú kartu

Spustenie výpoþtu

Výpoþet je možné spustiĢ jednoducho zavolaním funkcie Compute s poþtom vlákien na ktorých sa má výpoþet vykonaĢ. Je potrebné zadaĢ presný poþet vlákien (paralelných úloh) ktoré sa majú vykonaĢ. Ak by bol poþet vlákien menší, nevypoþítali by sa všetky výpoþty ktoré boli potrebné. Keby bolo þíslo väþšie, vlákna by sa podĐa aktuálneho programu mohli snažiĢþítaĢ a zapisovaĢ mimo alokovanú pamäĢ. Napríklad n-té vlákno by mohlo chcieĢ zapísaĢ výsledok výpoþtu do výstupného poĐa, ktoré by bolo dlhé len n-k prvkov.

Pre súþasné implementácie OpenCL a CUDA je nutné, aby poþet všetkých vlákien bol deliteĐný veĐkosĢou skupiny. Skupina nemôže obsahovaĢ veĐmi malý poþet vlákien, ináþ by grafická karta poskytovala len þiastkový výpoþtový výkon, pretože naraz môže spúšĢDĢ len obmedzený poþet skupín. Ak by to tak nebolo, mohli by sme urobiĢ skupiny s jedným vláknom a poþet všetkých vlákien by nebol nijak obmedzený. O splnenie podmienky deliteĐnosti poþtu vlákien sa stará platforma. Tá zaokrúhli poþet všetkých vlákien nahor s tým, že ako základ použije poþet vlákien v skupine. Takto by však nadbytoþné vlákna mohli pristupovaĢ mimo alokovanú pamäĢ a spôsobiĢ pád aplikácie. Aby sa tak nestalo, platforma za vygenerovaním hlaviþky hlavnej funkcie vkladá kód, ktorý zabezpeþuje aby doplnené vlákna nevykonávali zadaný program.

Niekedy je však toto správanie nevyhovujúce. Jedná sa o prípady keć poþítame s tým, že všetky vlákna v skupine musia vykonaĢ urþitý kód. Napríklad spoloþne naþítajú dáta do lokálnej pamäte, aby následne k týmto dátam malo prístup každé vlákno v skupine. Pri vytváraní kernelu, je možné zadaĢþo sa má robiĢ s nadbytoþnými vláknami. Kernel je Návrh platformy pre využitie GPU na všeobecné výpoēty 38 nastavený tak, aby sa nadbytoþné vlákna deaktivovali. UžívateĐ môže toto správanie zmeniĢ parametrom pri vytváraní kernelu. Potom sa poþet vlákien síce musí zaokrúhliĢ podĐa veĐkosti skupiny, ale pridané vlákna sa nedeaktivujú a budú vykonávaĢ rovnaký program ako ostatné. Vtedy musí poskytovateĐ programu zabezpeþLĢ, aby sa pridané vlákna deaktivovali, v þase keć nemusia/nesmú byĢ používané. To docieli vetviacou podmienkou, ktorá porovná premennú definujúcu posledné vlákno, ktoré má vykonávaĢ telo hlavnej funkcie. DocieliĢ to môže aj použitím makier, ktoré sú poskytované platformou. Jedná sa o makra vytvorené v jazyku C, ktoré zistia þi aktuálne vlákno má vykonávaĢ telo hlavnej funkcie, alebo už nie.

Vlákna, v ktorých sa výpoþet spustí, musia byĢ usporiadané v skupinách. UžívateĐ nemusí zadávaĢ poþet vlákien v skupine, ani ich usporiadanie, ak mu na Ėom nezáleží. Ak však požaduje špecifický poþet vlákien v skupine, môže ho zadaĢ ako ćalší parameter pri spúšĢaní výpoþtu. Rovnako jednoducho môže špecifikovaĢ aj viacrozmerné usporiadanie všetkých vlákien, aj vlákien v skupine. Staþí aby poþet vlákien nezadal pomocou þísla, ale ako pole, ktoré obsahuje poþet vlákien v jednotlivých dimenziách. Maximálne však môže používaĢ tri dimenzie.

Zotavenie sa pri chybe v algoritme pre GPU

Platforma automaticky kompiluje zadaný zdrojový kód programu, vykonávaný na výpoþtovom zariadení. To sa deje poþas prvého zadania dát do kernelu, alebo poþas prvého vykonania výpoþtu. Poþas kompilácie a poþas vykonávania kódu na grafickej karte môžu nastaĢ tieto základné chyby:

x Syntaktická chyba.

x Sémantická (logická) chyba.

Poþas kompilovania zdrojového kódu, sa môže kompilácia zastaviĢ na syntaktickej chybe. Bolo by vhodné, keby pri takejto chybe bol užívateĐ upozornený a mohol túto chybu opraviĢ, bez nutnosti znovu zapínaĢ hlavný program. Pri sémantickej chybe by bolo potrebné takisto užívateĐovi poskytnúĢ nástroje umožĖujúce detegovaĢ chybu.

To že syntaktická chyba je zobrazovaná bez nutnosti znovu zapnúĢ hlavný program, ušetrí vývojárovi algoritmu þas. Hlavne keć vytvára algoritmus používaný v simulácii a musel by zakaždým nanovo spúšĢDĢ simuláciu. Pri syntaktickej chybe sa využíva to, že Návrh platformy pre využitie GPU na všeobecné výpoēty 39

OpenCL kompiluje kód za behu programu. Pre zotavenie sa pri syntaktickej chybe je nutné zobraziĢ užívateĐovi kde a aká chyba nastala a po opravení chyby užívateĐom sa pokúsiĢ znovu skompilovaĢ kód. Kompilovaný kód sa však skladá z viacerých blokov znázornených na obrázku 5.

Pre zobrazenie správnej pozícii chyby je pri kompilácii potrebné zisĢovaĢ veĐkosĢ každého bloku a tento údaj si spolu s názvom bloku zapamätaĢ. Ak bol blok naþítaný zo súboru, zapamätá sa názov súboru. Ak nastane chyba pri kompilácii, je možné získaĢ popis chyby kompilátora. Ten však oznámi chybu na riadku z celého zdrojového kódu, reprezentovaného jedným reĢazcom. Tu využijem uložené dĎžky a názvy jednotlivých blokov kódu. Pomocou týchto údajov môžeme upraviĢ údaje o chybe získanej pri kompilácii, tak že bude obsahovaĢ popis bloku alebo názvu súboru v ktorom sa chyba vyskytla, spolu so správnym riadkom v tomto bloku.

Upravené hlásenie o chybe sa následné zobrazí užívateĐovi, spolu s možnosĢami znovu skompilovaĢ kód, alebo pokraþovaĢ vo vykonávaní bez funkþného kernelu. Pri možnosti znova skompilovaĢ kernel sa predpokladá, že užívateĐ podĐa oznámenej chyby opraví chybu v kóde a platforma sa pokúsi znovu skompilovaĢ upravený kód. Ak sa znova vyskytnú chyby poþas kompilácie, znovu sa zobrazia hlásenia o pozícii a type chyby. Ak užívateĐ nedá znovu skompilovaĢ kód, ale nechá program pokraþovaĢ, kernel sa nevykoná a program bude pokraþovaĢćalej.

V kóde pre výpoþtové zariadenie môže nastaĢ ešte sémantická (logická) chyba. ýasto sa jedná o zápis mimo alokovanú pamäĢ alebo inú logickú chybu, ktoré môžu vyvolaĢ pád aplikácie. Tieto chyby predstavujú väþší problém. Ak takéto prípady nastanú, platforma vyvolá výnimku, ale nevie presne o aký typ chyby ide. V niektorých prípadoch dokonca program pokraþuje bez chyby s tým, že výpoþet neprebehol, alebo dáta ostanú v nekonzistentnej forme. Ak používateĐ vlastní grafickú kartu od AMD, je na odhalenie takýchto chýb možné použiĢ program AMD CodeXL, dostupný na (AMD, 2013). V tomto programe je možné sledovaĢ všetky vlákna a ich premenné. Tiež je možné profilovaĢ výpoþty a tým zistiĢ ako je možné urýchliĢ výpoþet. Takto je možné odhaliĢ nesprávne hodnoty, ktoré by mohli spôsobiĢ aj pád aplikácie. Pre grafické karty od nVidia bohužiaĐ neexistuje podobný nástroj. Je to kvôli tomu, že sa zameriava na rozšírenie vlastnej proprietárnej technológie CUDA. Pre nájdenie logickej chyby na týchto kartách je nutné Návrh platformy pre využitie GPU na všeobecné výpoēty 40 použiĢ poþítaþ s grafickou kartou od AMD alebo logicky analyzovaĢ kód a manuálne v Ėom nájsĢ chybu.

Meranie rýchlosti výpoþtu

Hlavnou hnacou silou pre implantáciu výpoþtov na grafických kartách je urýchlenie výpoþtu. Z toho dôvodu je vhodné, aby sme vedeli ako rýchlo sa výpoþet vykoná. Zaznamenávanie þasu výpoþtu je integrované do kernelu. Ak sa zapne zaznamenávanie þasov, zaþnú sa pre každý výpoþet daným kernelom ukladaĢþasy do nastaveného adresára. Každá inštancia kernelu si vytvorí nový súbor a doĖho podrobne zaznamenáva þasy všetkých operácii.

Pre optimalizáciu výpoþtu nám nestaþí vedieĢ len celkový þas výpoþtu. Pre presnejšie zaznamenávanie þasu sa ukladajú þasy presunu každého atribútu s popisom názvu atribútu, smeru prenosu a veĐkosĢou prenesených dát. Pre výpoþet na grafickej karte sa ukladá þas výpoþtu a poþet vlákien, na ktorých sa výpoþet spustil. Tieto zaznamenané þasy obsahujú aj réžiu platformy. Pomocou všetkých týchto þasov sa dá presne urþLĢ, ako dlho trval výpoþet na grafickej karte a koĐko z neho zaberali jednotlivé þasti. Napríklad sa dá urþLĢ, že jeden atribút prenáša veĐa dát, alebo môžeme porovnaĢ výpoþet s implementáciou na procesore.

Pre meranie rýchlosti výpoþtu bola vytvorená samostatná trieda. Na zistenie presného þasu využíva QueryPerformanceCounter (Meier et al., 2004). Používaná ja pre zaznamenávanie þasu výpoþtu na grafickej karte a je ju možné použiĢ aj pri výpoþtoch na procesore. Namerané þasy je možné následne použiĢ na porovnanie zrýchlenia algoritmov implementovaných na grafickej karte. Trieda poskytuje jednoduché volania prístupné bez vytvárania inštancie þasovaþa. Meraný þas poskytuje v rôznych jednotkách, priþom najmenšou jednotkou je Tick. Jeden Tick predstavuje 20 mikrosekúnd. Nameraný þas sa dá uložiĢ hneć do súboru. Následne je možné súbory porovnávaĢ, napríklad pomocou Matlabu.

4.3.3 Prístup k OpenCL objektom

Platforma je navrhovaná so zreteĐom na to, aby používateĐ s Ėou mohol pracovaĢ s minimálnymi vedomosĢami o grafických kartách a aplikaþných rámcov. Samozrejme, þím viac o architektúre grafických kariet a paralelných algoritmoch vie, tým efektívnejší algoritmus môže vytvoriĢ. Návrh platformy pre využitie GPU na všeobecné výpoēty 41

Stále je však možné pristupovaĢ k objektom OpenCL pomocou vyhradených funkcii. To umožĖuje prepojenie s už existujúcimi výpoþtami vytvorenými priamo pre OpenCL, alebo integráciu s inými aplikaþnými rámcami postavenými na OpenCL, ktoré taktiež sprístupĖujú tieto objekty. Rovnako je možné tento prístup použiĢ na špeciálne príkazy, ktoré platforma v súþasnosti nepodporuje, ako napríklad prácu s textúrami.

Tým že je platforma navrhnutá aby bola užívateĐsky oddelená od OpenCL, v budúcnosti by bolo možné vnútorne implementovaĢ aj podporu CUDA a užívateĐovi sprístupniĢ dodatoþné funkcie dostupné v CUDA, ak by vlastnil grafickú kartu Nvidia.

4.3.4 Knižnice poskytované platformou

Samotné OpenCL neposkytuje knižnice s funkciami použiteĐnými vo výpoþte, tak ako je to napríklad pri CUDA. Jedná sa hlavne o paralelné algoritmy optimalizované pre grafické karty. Kećže vytvorená platforma sa zameriava hlavne na grafické karty, implementovali sme niekoĐko þasto používaných algoritmov na grafických kartách. Medzi tieto patrí napríklad prefix scan a triedenie.

Euklid

Euklid je knižnica so sériovými algoritmami. Pri vytváraní programu je možné urþLĢ, þi sa má k vytvorenému programu pre grafickú kartu prilinkovaĢ aj vytvorená knižnica s geometrickými operáciami. Obsahuje hlavne operácie s bodmi, úseþkami, polygónmi a kruhmi. Konkrétnejšie ide o vzdialenosti a prieseþníky, alebo kontroly, þi sa jeden objekt nachádza v druhom. Ak by užívateĐ nechcel používaĢ túto knižnicu, môže to platforme oznámiĢ. Tým sa urýchli kompilácia, tá však prebieha iba raz, následne sa kontroluje hash kódu s už skompilovanými programami, takže nie je nutné explicitne deaktivovaĢ podporu tejto knižnice.

Prefix scan

Prefix scan, alebo tiež kumulatívna suma, je operácia, ktorá pre zadané vstupné pole

x1..xn vráti pole y1..yn, kde = . Grafická karta toto pole dokáže spracovaĢ ௞ିଵ so zložitosĢou O(log n) pri ݕparalelnom௞ σ௜ୀଵ ݔ ௜výpoþte. Operácia sa delí na inclusive scan a exclusive scan. Líšia sa v tom, že inclusive scan používa na výpoþet vzorec = ௞ ݕ௞ σ௜ୀଵ ݔ௜ Návrh platformy pre využitie GPU na všeobecné výpoēty 42 a exclusive scan používa vzorec = . Je však možné vytvoriĢ jednu operáciu ௞ିଵ z druhej, tým že prvky sa posunú o jedna௞ a pridá௜ sa chýbajúci prvok. ݕ σ௜ୀଵ ݔ

Obrázok 8: Paralelný výpoþet prefix sum (Chen, 2012)

Tento algoritmus pre grafické karty pracuje v dvoch fázach. Tieto fázy sú znázornené na obrázku 8. Prvá fáza je oznaþovaná pomocou premenných y a druha fáza pomocou premenných z. V prvej fáze pre k=2 až n pripoþíta ku každému k-temu prvku, prvok vzdialený o k/2 prvkov, priþom k sa v každom kroku zväþší na dvojnásobok. Druhá fáza je v podstate opakom predošlej s tým rozdielom, že k zaþína od n a klesá po 2. Použitý algoritmus využíva lokálnu pamäĢ, pre rýchlejšie výpoþet. Vtedy sa dáta nemusia sþítavaĢ stále v pomalej globálnej pamäti ale len na zaþiatku a na konci sú do nej zapísane výsledky. Väþšie polia sú poþítané iteratívne, priþom sa najprv urobí scan po þastiach, potom scan nad najväþšími hodnotami z týchto polí a následne sa hodnoty z druhého scanu priþítajú k výsledkom z prvého scanu. Tento iteratívny prístup je možné viac krát opakovaĢ pre veĐmi veĐké polia a jedna iterácia je znázornená na obrázku 9. Návrh platformy pre využitie GPU na všeobecné výpoēty 43

Obrázok 9: Iteratívny scan väþších polí (Hurbert, 2007) Využitie prefix scanu je pri výpoþtoch na grafických kartách široké. Napríklad pri realizácii výpoþtu, kde potrebujú iba niektoré vlákna zapísaĢ výsledok do výsledného poĐa. Na identifikáciu pozície vo výslednom poli môžu vlákna použiĢ id vlákna, alebo globálnu premennú, ktorú si budú inkrementovaĢ pomocou atomických operácii a používaĢ ako identifikátor pozície. Pri použití atomickej premennej, vlákna musia na seba þakaĢ a zapisovaĢ výsledky postupne, þo spôsobí znaþné spomalenie. Pri druhej možnosti zas ostanú nevyužité prvky poĐa, ktoré boli rezervované pre vlákna nezapisujúce výsledok. Takéto pole sa dlhšie spracúva a musí obsahovaĢ prídavnú informáciu o platných prvkoch. Pri použití scanu, vlákna zapíšu platné výsledky najprv na pozíciu ID vlákna a ostatné pozície sú reprezentované nulovým prvkom. Následne sa spustí exclusive scan nad týmto poĐom, priþom každý nenulový prvok sa chápe ako þíslo jedna. Výsledkom operácie scan je pole, ktoré pre každý prvok platných dát obsahuje pozíciu, na ktorú je potrebné vypoþítaný prvok presunúĢ. Keć všetky vlákna presunú prvky na dané pozície, vznikne pole bez medzier len s výslednými prvkami. Tieto operácie sú znázornené na obrázku 10. Výsledné menšie pole je možné následne spracovávaĢ s menším poþtom vlákien, alebo rýchlejšie skopírovaĢ späĢ do RAM poþítaþa. Tento algoritmus využívajú viaceré algoritmy, ako napríklad radix sort. Návrh platformy pre využitie GPU na všeobecné výpoēty 44

Obrázok 10: Použitie operácie Scan na redukciu poĐa

Pre použite prefix scan boli implementované viaceré funkcie. Aj keć najþastejšie sa používa scan pri celých þíslach, implementované funkcie pracujú so všetkými základnými dátovými typmi, ktoré sa vedia porovnaĢ. Takisto sú podporované záznamy pri ktorých je potrebné urþLĢ, nad ktorou položkou sa má spustiĢ scan. Táto položka môže byĢ zasa akýkoĐvek typ, ktorý sa vie porovnávaĢ. Scan je možné robiĢ nad dátami v pamäti poþítaþa, vtedy sa najprv skopírujú na grafickú kartu a po operácii sa skopírujú naspäĢ. ýastejšie sa však používa scan nad dátami na grafickej karte, kećže prenos zaberá podstatnú þasĢ dĎžky výpoþtu. Tento prístup je rovnako podporovaný. Implementovaná je aj podpora scanu nad viacerými poliami naraz, þo sa þasto používa pri triedení pomocou Radixsort.

Triedenie

Pre usporiadanie prvkov na grafickej karte existuje hneć niekoĐko algoritmov. Najlepšie sériové algoritmy pre procesor ako quicksort, heapsort alebo mergsort majú zložitosĢ výpoþtu O(n*log(n)), priþom niektoré pri nevyhovujúcich podmienkach majú zložitosĢ O(n2). Naproti tomu, najlepšie súþasne algoritmy pre grafickú kartu ako bitonic sort, bitonic mergesort, alebo radix sort dokážu usporiadaĢ prvky nižšou zložitosĢou. Napríklad bitonic sort má zložitosĢ O(log(n)). Toto platí len do urþitého poþtu prvkov, v závislosti od maximálneho poþtu vlákien spustiteĐných na grafickej karte. Potom je výpoþet pomalší, kećže ćalšie prvky sa poþítajú postupne. Ale aj napriek tomu je výpoþet mnohonásobne rýchlejší v porovnaní so sériovými algoritmami.

Vytvorená platforma poskytuje pre utriedenie prvkov hneć dva algoritmy. Prvým je bitonic sort, ktorý sa dá použiĢ na akýkoĐvek typ, ktorý sa vie porovnaĢ. Druhým je Radix Návrh platformy pre využitie GPU na všeobecné výpoēty 45

(Harada et al., 2011) sort, ktorý pracuje len pre typy, ktoré sa dajú usporiadaĢ po bitoch. Medzi takéto typy patria celé þísla, alebo znaky, ale nepatria medzi ne desatinné þísla.

Bitonic sort bol navrhnutý priamo ako paralelný algoritmus, priþom využíva princíp triediacich sieti (Batcher, 1968). Triediaca sieĢ tohto algoritmu je znázornená na obrázku 11. VeĐmi dobre vysvetĐuje implementáciu bitonic sort pre grafické karty Baelto (2011). Najprv uvádza primitívne triediace algoritmy a postupne uvádza viaceré optimalizácie bitonic sortu. Postupne ich porovnáva a popisuje ako ktorá zmena ovplyvĖuje rýchlosĢ algoritmu.

Obrázok 11: Triediaca sieĢ bitonic sortu

Radix sort je triediaci algoritmus, ktorý priamo neporovnáva hodnoty pri triedení. Ćalšou vlastnosĢou, ktorá ho vyþleĖuje je, že teoretická zložitosĢ sériového algoritmu je O(k*n), kde n je poþet prvkov a k je poþet bitov alebo þastí, na ktoré sa triedený kĐXþ rozdelí. Dalo by sa usudzovaĢ, že paralelná veria by mohla maĢ zložitosĢ O(k). Avšak pre každé k je nutné vykonaĢ scan, ktorý má zložitosĢ O(log(n)). Z toho vyplýva, že pre triedené kĐ~þe kratšej dĎžky, ako napríklad dátový typ byte, je tento algoritmus veĐmi rýchly. Návrh platformy pre využitie GPU na všeobecné výpoēty 46

Obrázok 12: Radix sort pre grafické karty

Postup vykonávania je znázornený na obrázku 12. Pre každú þasĢ kĐ~þa k, sa opakujú nasledujúce operácie. Najprv sa spoþíta koĐko existuje kĐ~þov s rovnakou þasĢou. To sa uloží do tabuliek obsahujúcich þasti kĐ~þa a ich poþet. Nasleduje spustenie viacerých operácii scan, podĐa poþtu rôznych kombinácii þastí kĐ~þu. Pre situáciu na obrázku, by to bolo 16 operácii. Pre rýchlejší výpoþet môže každá skupina používaĢ lokálnu pamäĢ na spoþítanie kĐ~þov a vykonanie operácie scan. Potom sa spustí druhá operácia scan nad najväþšími þíslami z predošlých scanov. Tieto þísla reprezentujú vlastne sumu poþtu Návrh platformy pre využitie GPU na všeobecné výpoēty 47

NĐ~þov v skupine a na obrázku sú znázornené ako sum. Na všetky scan operácie sa používa jeho exclusive verzia. Hodnoty z posledného scanu sa pripoþítajú k poþtom kĐ~þov, tak ako je to znázornené na obrázku. Ako posledné sa preusporiadajú kĐ~þe podĐa získaných tabuliek. Všetky operácie, okrem operácii scanu sú na grafickej karte jednoducho vykonateĐné, þo znamená, že majú teoretickú zložitosĢ O(1) pri paralelnom vykonávaní, ak ja možné na grafickej karte spustiĢ naraz aspoĖ toĐko vlákien, ako je poþet triedených prvkov. Z toho vyplýva, že radix sort implementovaný na grafických kartách je ovplyvnený hlavne rýchlosĢou operácie scan.

4.3.5 Popis þastí platformy

V tejto kapitole sú v krátkosti popísané súþasti platformy používané na všeobecné výpoþty. Zjednodušený UML diagram platformy, zobrazujúci jej podstatné þasti, je znázornený na obrázku 13.

Obrázok 13: Zjednodušený UML diagram Kernelu a jeho závislostí

Trieda TECInit slúži na inicializáciu grafických kariet, alebo iných výpoþtových zariadení. Na popis zariadenia používa triedu TECDeviceIdent, ktorá sa vie uložiĢ a naþítaĢ, Návrh platformy pre využitie GPU na všeobecné výpoēty 48 z dôvodu umožnenia používaĢ rovnaké zariadenie pri ćalšom spustení programu. Trieda TECDevice slúži na vnútorne reprezentovanie zariadenia a používa sa pri všetkých operáciách vykonávajúcich sa nad daným zariadením. TECKernel bude používateĐ najviac používaĢ, kećže slúži na vytváranie a spúšĢanie výpoþtov na výpoþtovom zariadení. Na jej použitie treba vytvoriĢ jej inštanciu, zadaĢ vykonávaný kód, nastaviĢ atribúty a spustiĢ výpoþet. Triedy TECParameter a TECParameterArray sú vnútorne používané na ukladanie informácii o atribútoch, ako je meno, typ, adresa pamäte alebo štruktúra záznamu. PoužívateĐ väþšinou nepracuje priamo s nimi, ale cez funkcie dostupné v triede TECKernel. Platforma poskytuje aj viaceré triedy odvodené z TECKernel, ako znázornené TECScan a TECBitonic, ktoré používateĐovi poskytujú prívetivé používanie algoritmov optimalizovaných pre grafické karty. Rozšírenie agentovej architektúry pre využitie výpoētového výkonu grafických kariet 49

5 Rozšírenie agentovej architektúry pre využitie výpoþtového výkonu grafických kariet

Pre rozšírenie agentovej architektúry o možnosĢ využiĢ výpoþtový výkon grafickej karty, je potrebné vybraĢ vhodnú architektúru. V tejto kapitole sú popísané existujúce modely a aplikaþné rámce využívajúce výpoþtový výkon grafických kariet. Za nimi sú popísané niektoré agentové architektúry, ktoré by bolo možné rozšíriĢ o výpoþet pomocou grafických kariet. Z nich je jedna vybraná a bližšie popísaná. Do nej je integrovaná navrhovaná platforma s tým, že je kladený dôraz na jednoduchosĢ jej používania poþas simulácie.

5.1 Simulaþné nástroje využívajúce GPU

Vo väþšine prác sú simulaþné modely pre grafické karty vytvárané buć pomocou aplikaþného rámca využívajúceho výkon grafických kariet (najþastejšie to býva len CUDA), alebo staršími technikami, ako ukladania dát do textúr a používanie špeciálnych inštrukcií grafických kariet. Simulácií, ktoré by využívali aplikaþný rámec umožĖujúci previesĢ výpoþet agentovo orientovanej simulácie na grafickú kartu je veĐmi málo. Je to z toho dôvodu, že takéto aplikaþné rámce sa v súþasnosti ešte len vyvíjajú a simulácie používajúce tieto aplikaþné rámce vytvárajú len tvorcovia týchto nástrojov.

V nasledujúcej þasti predstavíme niekoĐko modelov, ktoré sú implementované s využitím grafických kariet a potom aj aplikaþné rámce, ktoré umožĖujú vykonávaĢ agentovo orientovanú simuláciu na grafických kartách. Ku každej z nich popíšeme ich výhody a nevýhody oproti ostatným.

5.1.1 Simulaþné modely implementované priamo pre GPU

Ukážkou simulácie pomocou pôvodného prístupu GPGPU, je simulácia evakuácie Đudí v krízových situáciách, popísaná v práci Courty a Musse (2005). Na modelovanie správania sa Đudí využívajú Helbingov (1995) model sociálnych síl. Zameriavajú sa na evakuáciu pred nebezpeþnými plynmi s vykresĐovaním priebehu simulácie do dvoj rozmerného priestoru. Dokázali simulovaĢ súþasne do 10000 Đudí pri plynulom priebehu zobrazovania. Rozšírenie agentovej architektúry pre využitie výpoētového výkonu grafických kariet 50

Za pomocí aplikaþného rámca CUDA, autori Strippgen a spol. (2009) simulovali pomocou agentovo orientovanej simulácie dopravu. Využili veĐmi jednoduchú reprezentáciu cestnej dopravy, pomocou definovania priepustnosti ciest podĐa dĎžky vozidla a maximálnej rýchlosti. Využili viacero optimalizácii, ako využitie štruktúry skladajúcej sa z polí namiesto polí štruktúr a namiesto posúvania áut v týchto poliach, si ukladali len platné pozície. S takouto simuláciou dosiahli voþi sériovej implementácii maximálne 67 násobné zrýchlenie, pri porovnávaní Intel Pentium Dual Core 2.2 GHz a GeForce GTX 280.

Ćalším príkladom využitia aplikaþného rámca CUDA je v þlánku autorov Erra a spol (2009). Simulaþný výpoþet správania sa škôlky rýb pomocou sociálnych síl. Pomocou jednoduchých správaní priĢahovania a odpudzovania od ostatných rýb vytvorili komplexné správanie. Pri každom kroku, v ktorom sa má vypoþítaĢ pohyb, sa vždy nanovo vytvára aj pomocná štruktúra. Pomocná štruktúra slúži na rýchle vyhĐadávanie v okolí. Skladá sa s týchto krokov: mapovanie agentov do buniek, radix sort, sériové usporiadanie dát, nájdenie prvej ryby v usporiadaných dátach a vyhĐadávanie vo vytvorenej štruktúre. Takto dokázali simulovaĢ 65536 rýb s 3D animáciou pri 60 fps. Na výsledok mal ale veĐký vplyv polomer rozhĐadu. Táto práca je zaujímavá pre použitie dátovej štruktúry na zrýchlenie vyhĐadávania v okolí, kećže niektoré agentovo orientované simulácie potrebujú priestorové vyhĐadávanie.

5.1.2 Simulaþné aplikaþné rámce používajúce GPU

Vo svojej práci autori Lysenko a D’Souza (2008) vytvorili podĐa nich prvý aplikaþný rámec pracujúci na GPU, ktorý sa dá použiĢ pri simulácii agentových modelov. Pre výpoþty na GPU využívajú techniky GPGPU. Na výpoþet slúži Stream Programming Model a pre uloženie dát využívajú ich mapovanie do textúr. Nevyužívali žiadne nové aplikaþné rámce, pretože vtedy ešte len tieto aplikaþné rámce vznikali, ale zmienili sa, že pri budúcom vývoji by chceli využívaĢ CUDA. Rozšírenie agentovej architektúry pre využitie výpoētového výkonu grafických kariet 51

Obrázok 14: Ukážka Sugarscape simulácie(Lynsenko et al., 2008)

Pomocou vlastného aplikaþného rámca vytvorili jednoduché simulácie Sugarscape a StupidModel. Simuláciu Sugarscape je možné vidieĢ na obrázku 14. Pri týchto modeloch dosahovali vyše sto násobné zrýchlenie výpoþtu, oproti sériovému kódu vykonávanom na procesore. Kećže využívali staršie techniky pre prácu s grafickými kartami, riešili hlavne problémy ako pracovaĢ s dátami v textúrach a ako ich efektívne spracovávaĢ. Žiadne ćalšie publikácie o rozvoji tohto nástroja, ani samotný nástroj nie sú zverejnené. Z tohto dôvodu sa tento aplikaþný rámec nedá prakticky využiĢ.

FLAME GPU je rozšírenie FLAME aplikaþného rámca, ktorý využíva grafickú kartu na spracovanie výpoþtov. FLAME (Flexible Large-scale Agent Modeling Enviroment) je generický agentový modelovací systém. Toto rozšírenie vytvoril Paul Richmond a venuje sa mu vo svojich viacerých þlánkoch. (Richmond et al., 2008a, 2008b, 2009a, 2009b, 2011a). Pre využitie grafických kariet používal zo zaþiatku GPGPU, ale neskôr prešiel na CUDA. Z tohto dôvodu je toto riešenie použiteĐné len na grafických kartách znaþky Nvidia. Vo svojom prvom þlánku nevyužíval ešte žiadne súþasné aplikaþné rámce pre výpoþet na GPU, ale využíval len inštrukcie GPU a textúry (Richmond et al., 2008a). Neskôr vytvoril simuláciu škôlky rýb, s vykresĐovaním vypoþítaných údajov, ktoré sa nachádzali na grafickej karte. V ćalšej práci využíval podobné techniky pre výpoþty na GPU, ale simuloval pohyb Đudí, þo je možné vidieĢ na obrázku 15 (Richmond et al., 2008b). Na výpoþet správaní Đudí využíval upravené sociálne sily. Ćalší rok už Richmond využil aplikaþný rámec CUDA a na jednoduchých príkladoch demonštroval viacero rozdielnych agentov a podporu vytvárania a rušenia agentov. (Richmond et al., 2009a) V ćalších prácach upravoval riešenie založené na CUDA, aby ho mohol využiĢ aj v iných oblastiach. Rozšírenie agentovej architektúry pre využitie výpoētového výkonu grafických kariet 52

Obrázok 15: Ukažka simulácie pomocou GPGPU, Đavo skutoþnosĢ, pravo simulácia (Richmond et al., 2008b)

V práci (Richmond et al., 2009b) sa zmienil, že by bolo vhodné prejsĢ z CUDA na OpenCL z dôvodu pokrytia väþšieho spektra výpoþtových zariadení. Posledné práce sú z roku 2012. Na svojich stránkach má dostupný FLAME GPU na stiahnutie, ktorý je vytvorený v CUDA 4.1. NakoĐko nie sú dostupne žiadne ćalšie þlánky po roku 2012 a CUDA verzie 4.1 je tiež z roku 2012, Richmond pravdepodobne nepokraþuje vo vývoji tohto aplikaþného rámca. Ćalším možným záporom môže byĢ dlhšie oboznamovanie sa s FLAME GPU. Je to z toho dôvodu, že pre prácu s ním je nutné poznaĢ XMMLGPU (Richmond et al., 2011b) vytvorený Richmondom. Z dôvodu nutnosti uþenia sa XML formátu používaného vo FLAME GPU a ćalších vlastností tohto aplikaþného rámca, ako aj z dôvodu možného zastavenia jeho vývoja pred dvoma rokmi, nie je vhodný na vytváranie simulácii pracujúcich na grafických kartách. Takáto simulácia by bola taktiež obmedzená len na špecifickú verziu CUDA (v súþasnosti pre verziu 3.1 a 4.1, priþom už existuje verzia 6.0RC) a využívala by len grafické karty nVidia. Väþšia perspektíva sa javí v analýze výhodných funkcii FLAME GPU a ich využitia vo vlastnej simulácii, prípadne vlastnej simulaþnej platforme využívajúcej grafické karty na výpoþet. Rozšírenie agentovej architektúry pre využitie výpoētového výkonu grafických kariet 53

5.2 Vybrané agentové architektúry

Vo svete existujú viaceré agentové architektúry. Medzi ne patria napríklad EcoLab (Standish, 2008), alebo Cougaar (Helsinger et al., 2004), MASON (Luke et al., 2005), Repast (North et al., 2009) a ABAsim (Adamko et al., 2006). V nasledujúcich odsekoch sú v krátkosti popísané.

Agentový modelovací systém EcoLab (Standish et al., 2004) využíva na zadávanie modelu skriptovací jazyk, podobný jazyku C++. UmožĖuje vykresĐovaĢ priebeh simulácie pomocou knižnice tk a obsahuje podporu pre ukladanie stavov simulácie a jej reštartovanie. Taktiež podporuje paralelné vykonávanie pomocou MPI (Message Passing Interface) (Snir et al., 1998).

Cougaar je architektúra s otvoreným kódom vytvorená v jazyku Java. Zameraná je hlavne na paralelnú simuláciu. O tom svedþí aj odolnosĢ voþi chybe výpoþtového prvku, alebo zmeny rýchlosti komunikácie. Pre zobrazovanie priebehu simulácie je možné použiĢ vstavaný web server.

Manson je rovnako vyvíjaný v jazyku Java. Simulácia je úplne oddelená od vizualizácie, priþom umožĖuje zobraziĢ simuláciu v 2D aj v 3D zobrazení. Zaujímavá je schopnosĢ uložiĢ aktuálny stav modelu a pokraþovaĢ v simulácii na inom poþítaþi s iným operaþným systémom.

Repast umožĖuje užívateĐovi meniĢ hodnoty simulácie poþas jej behu a poskytuje genetické algoritmy pomocou komponentu JGAP (Meffert et al., 2008) a neurónové siete (Marpone et al., 2013). Takisto má vstavaný geografický informaþný systém, takže poskytuje širokú prídavnú funkcionalitu využiteĐnú v simuláciách.

ABAsim rozdeĐuje agentov na dva druhy a to riadiacich a dynamických. Riadiaci agenti sú zodpovední za urþité þasti modelu a sú vytvorení pred simuláciou. Dynamickí agenti sa vytvárajú poþas simulácie a každý jeden v simulácii reprezentuje urþitú inteligentnú jednotku. Podporuje paralelné vykonávanie simulácie. Rozšírenie agentovej architektúry pre využitie výpoētového výkonu grafických kariet 54

Porovnanie vlastností niektorých uvedených architektúr je možné nájsĢ v (Railsback et al., 2006). Pre rozšírenie som si vybral architektúru ABAsim. Dôvody sú uvedené v prvom bloku nasledujúcej podkapitoly.

5.2.1 Agentová architektúra ABAsim

Na úþely rozšírenia agentovej architektúry pre podporu využitia grafických kariet, bola vybratá agentová architektúra ABAsim. S touto architektúrou som bol oboznámený poþas inžinierskeho štúdia a spolupracoval som na vývoji simulaþného nástroja PedSim (Varga ‚ 2012), ktorý túto architektúru používa. Na tejto architektúre sú vyvíjané komerþné nástroje a taktiež sa používa na výuþbové úþely. Architektúra delí agentov na dve skupiny. Práve táto vlastnosĢ je vhodná pre využitie grafických kariet, pretože dynamickí agenti sú dobrí kandidáti pre výpoþty na grafických kartách. Presnejší popis dynamických agentov je uvedený nižšie, pri špecifikácii architektúry. Túto výhodu budú môcĢ využiĢ aj existujúce riešenia, postavené na tejto architektúre.

ABAsim je dvojvrstvová agentová architektúra. Táto hierarchia je znázornená na obrázku 16, kde v hornej þasti sú znázornení riadiaci agenti a v spodnej þasti sa nachádzajú dynamickí agenti. Rozdiel medzi týmito agentmi je nasledujúci:

x Riadiaci agent – Títo agenti sú zodpovední za þasĢ modelu im urþenú. Na zaþiatku simulácie sú usporiadaní do hierarchie, kde ako celok pracujú na dosiahnutí simulovaného cieĐa. Poþas simulácie už nevznikajú, ani nezanikajú.

x Dynamický agent - Je podriadeným agentom a vždy je v správe jedného agenta. Predstavuje autonómnu entitu, ktorá plní ciele urþené riadiacim agentom, priþom sleduje aj vlastné ciele, ktoré sú však podriadené cieĐom od Rozšírenie agentovej architektúry pre využitie výpoētového výkonu grafických kariet 55

riadiaceho agenta. PokiaĐ sú riadiaci agenti navrhnutí pred simuláciou, dynamickí agenti sa môžu vytváraĢ a zanikaĢ poþas simulácie.

Obrázok 16: Dvojvrstvový model agentov v architektúre ABAsim (Adamko, 2013)

Riadiaci agenti sú zodpovední za vymedzené oblasti modelu, priþom je možné pridávaĢćalších agentov a tým rozšíriĢ simuláciu o ćalšiu oblasĢ. Takto je možné vložiĢ existujúci submodel do veĐkého modelu, ako napríklad riadenie vozíkov do modelu cestnej dopravy. Dynamickí agenti zasa umožĖujú modelovaĢ autonómne prvky, ktoré sledujú vlastný cieĐ. Tých je prevažne veĐké množstvo a riadia sa rovnakými pravidlami. Práve pri týchto dynamických agentoch je vhodné využiĢ výpoþtový výkon grafických kariet. To je vyhovujúce pre veĐký poþet vlákien na grafickej karte. Taktiež vykonávajú podobný kód, þo je vhodné kvôli malému poþtu kontrolných jednotiek, ktoré spracúvajú inštrukcie na grafickej karte.

Agenti medzi sebou komunikujú pomocou správ. Každý agent si môže registrovaĢ správy, na ktoré reaguje. Správy následne môžu posielaĢ priamo agentovi zodpovednému za jej spracovanie alebo nadriadenému agentovi submodelu alebo vyplniĢ len kód správy a simulácia nájde agenta, ktorý danú správu vie spracovaĢ. Simulácia však obsahuje jednu špeciálnu správu nazývanú Tick, ktorá nesúvisí s jednotkou tick používanou pri meraní þasu. Tá sa posiela všetkým dynamickým agentom, ktorí sa prihlásia na jej odber, každých x Rozšírenie agentovej architektúry pre využitie výpoētového výkonu grafických kariet 56 simulaþných jednotiek. Tým sa oznámi dynamickým agentom že majú vykonaĢ operácie pre aktuálny simulaþný þas.

5.3 Rozšírenie architektúry ABAsim

Medzi hlavné myšlienky vytvorenia platformy pre výpoþty na grafickej karte patrí súþinnosĢ s agentovým jadrom. Pomocou navrhnutej platformy by bolo možné vykonaĢþasĢ výpoþtu simulácie na grafických kartách. Od platformy však požadujeme, aby bola pevnejšie previazaná s agentovo orientovanou simuláciou a umožĖovala jednoduché vytváranie a používanie výpoþtov vykonávaných poþas simulácie. Napríklad automatizovaĢ niektoré úkony, ktoré by bolo nutné v simulácii opakovane vykonávaĢ, keby sa použila navrhovaná platforma, tak ako bola doteraz popísaná.

Dynamickí agenti sú z pohĐadu grafických kariet veĐmi zaujímaví. Je to z dôvodu že reprezentujú modelované jednotky, ktorých je zvyþajne veĐké množstvo. Napríklad pri simulácii pohybu chodcov to môže predstavovaĢ desaĢtisíce chodcov v modeli. Modelovanie toĐkých chodcov je veĐmi nároþné na výpoþtový hardvér, þo sa prejavuje na dlhom þase simulácie. Z toho dôvodu sa rozšírenie architektúry pre využitie výpoþtového výkonu grafických kariet zameriava na dynamických agentov. Grafické karty pre efektívne využitie požadujú úlohy, ktoré na veĐkom poþte vlákien vykonávajú rovnaký algoritmus. Dynamickí agenti sú pre grafické karty veĐmi vhodní kvôli tomu, že ich je väþšie množstvo a vykonávajú rovnaký algoritmus.

Samozrejme, že je možné využiĢ platformu aj v riadiacich agentoch. Tí však vykonávajú rôzne úlohy a to nie je vhodné pre grafické karty, ktoré pre efektívne spracovanie požadujú, aby bol rovnaký kód vykonávaný na všetkých vláknach. Ak však takýto agent vykonáva nároþnú operáciu, ktorú je možné previesĢ na paralelnú, môže využiĢ platformu a vykonaĢ tento výpoþet na grafickej karte. Takým istým spôsobom je možné vykonávaĢ paralelný výpoþet na rôznych miestach simulácie, napríklad pri spracovaní dát.

V simulácii sa môže nachádzaĢ viac rôznych druhov dynamických agentov. Napríklad jeden pre pohyb aut a iní pre pohyb chodcov. Týchto druhov však väþšinou nie je veĐa, pretože rovnaký agent chodca môže byĢ použitý pre dieĢa, starca, alebo hendikepovaného chodca. Pre integráciu platformy do agentovej simulácie bolo potrebné vytvoriĢ správcu všetkých výpoþtov dynamických agentov. Ako najlepšia pozícia, pre umiestnenie správcu, sa javil objekt zastrešujúci beh simulácie. Pri simulácií je tento objekt Rozšírenie agentovej architektúry pre využitie výpoētového výkonu grafických kariet 57 prístupný všetkým agentom, þo umožní agentom registrovaĢ sa, pre spracovanie pomocou platformy. Z toho dôvodu je implementovaný potomok objektu zastrešujúci beh simulácie, ktorý rozširuje funkcionalitu o správu výpoþtov na grafickej karte.

Pre výpoþet na grafickej karte je poskytovaná trieda, ktorú je potrebné zdediĢ. Táto trieda poskytuje jeden hlavný kernel s tým, že je možné použiĢćalšie pomocné kernely. Každá takto odvodená trieda musí maĢ pridelený þíselný kód, ktorý reprezentuje daný výpoþet. Následne sa musí registrovaĢ do simulácie. Tým je o tomto výpoþte oboznámený správca výpoþtov a dokáže ho poskytnúĢ poþas simulácie pre výpoþet dynamických agentov.

Pre jednoduchšie registrovanie agenta pre výpoþet na grafickej karte, je vytvorený potomok dynamického agenta. Potomok rozširuje funkcionalitu predka o možnosĢ prihlásiĢ sa na paralelný výpoþet a odhlásiĢ sa z konkrétneho alebo všetkých paralelných výpoþtov. Pre prihlásenie sa na paralelný výpoþet, je nutné oznámiĢþíselný kód výpoþtu, ktorý sa má vykonávaĢ. Výpoþet sa vykoná následne po tom, ako dynamický agent vykoná Tick. Ak sa zaregistruje na viacero výpoþtov, vykonajú sa postupne.

V jednoduchom prípade použitia, sa po každom ticku vyvolá výpoþet hlavného kernelu s poþtom vlákien rovnajúcim sa poþtu agentov, ktorí sa majú spracovaĢ. V tomto prípade je nutné preniesĢ dáta na a z grafickej karty potrebné k výpoþtu, priþom už pred spustením simulácie musel byĢ vytvorený objekt s výpoþtom. Jednoduchým preĢažením procedúry je umožnené spúšĢDĢ hlavný kernel s iným poþtom vlákien, alebo viaceré kernele. Pri takomto použití sú však zakaždým prenášané dáta o všetkých agentoch. Preto platforma oznamuje týmto objektom informáciu, keć sa prihlási na výpoþet nový agent alebo ak sa odhlási, prípadne zanikne agent. Vtedy môže užívateĐský kód na toto reagovaĢ a aktualizovaĢ iba relevantné dáta na grafickej karte.

5.3.1 Optimalizácie výpoþtu poþas simulácie

Ako súþasĢ návrhu platformy, mala byĢ overená možnosĢ optimalizácie výpoþtu na grafickej karte poþas behu simulácie. Pre takúto optimalizáciu je nutné najprv vymedziĢ aké prvky je možné optimalizovaĢ pre dosiahnutie lepších výsledkov. Kećže výpoþty vykonávame so zámerom vytváraĢ väþšie a rýchlejšie simulácie, pod lepším výsledkom rozumieme rýchlejšie vykonanie výpoþtu. Rozšírenie agentovej architektúry pre využitie výpoētového výkonu grafických kariet 58

OptimalizovaĢ môžeme viaceré súþasti výpoþtu. V nasledujúcom texte popíšeme jednotlivé súþasti s odôvodnením preþo sme si ich vybrali, alebo nevybrali na optimalizáciu.

Zámena operácii za natívne a jednoduchšie pre GPU

Tento postup sa zdal ako sĐubným kvôli jednoduchej zámene urþitých operácii. Ako napríklad delenie dvoma pomocou bitového posunu, alebo napríklad trochu komplikovanejších, ako zámena vetvenia za vstavané príkazy ako min, max, clamp. Tento prístup (Varga a Mintál, 2014) však neprináša takmer žiadne zrýchlenie z dôvodu už dostatoþnej optimalizácie kompilátorom kódu pre grafickú kartu. Pre uvedený dôvod, nie je tento prístup použitý v platforme.

Optimalizácia využitia pamäte

VeĐmi výrazné zrýchlenie výpoþtu poskytuje správne používanie rôznych pamätí grafickej karty (Kirk et al., 2010). Takéto optimalizácie sú však komplikované a veĐmi záležia od druhu algoritmu. Síce dokážu urýchliĢ výpoþet, ale nie je ich možné riešiĢ automaticky pre všetky situácie. Pre takúto optimalizáciu sa musí užívateĐ podrobnejšie oboznámiĢ s architektúrou grafických kariet a sám správne urþLĢ ktoré pamäte a ako budú používané. Táto optimalizácia takisto nie je použitá, ale z dôvodu jej zložitej povahy.

Zmena usporiadania vlákien

Výpoþty sa skladajú z veĐkého poþtu vlákien, ktoré je možné usporiadaĢ do rôzne veĐkých skupín. Ak užívateĐ explicitne nešpecifikuje veĐkosĢ skupiny, je možné použiĢ viaceré veĐkosti skupín. Tieto veĐkosti taktiež ovplyvĖujú rýchlosĢ výpoþtu. Napríklad pri väþšom poþte vlákien sa môže použiĢ ten istý údaj v lokálnej pamäti väþším poþtom vlákien a výpoþet to môže urýchliĢ. Naproti tomu, pri menšom poþte vlákien nemusí prísĢ tak rýchlo k vyþerpaniu zdrojov grafickej karty (registrov, lokálnej pamäte) a tým nedôjde k zníženiu maximálneho poþtu súþasne vykonávaných vlákien. Ak by pri väþšom poþte vlákien v skupine k tomuto došlo, menší poþet vlákien by sa mohol vykonávaĢ rýchlejšie. Zmena poþtu vlákien je jednoducho implementovateĐná a má vplyv na rýchlosĢ výpoþtu, preto je táto možnosĢ použitá. Rozšírenie agentovej architektúry pre využitie výpoētového výkonu grafických kariet 59

Použitie rôznych kernelov na dosiahnutie rovnakého výpoþtu

Rovnako ako existujú rôzne algoritmy pre procesor na výpoþet toho istého problému, tak je možné vytvoriĢ rôzne algoritmy pre grafickú kartu. Rôzne algoritmy môžu byĢ rýchlejšie v rôznych situáciách. Napríklad pri triedení, všeobecne používaný Quicksort môže v niektorých prípadoch dosiahnuĢ svoju najhoršiu zložitosĢ, þo je O(n2), priþom Heapsort má zložitosĢ vždy O(n log(n)) a v týchto prípadoch by dokázal zotriediĢ dáta rýchlejšie.

Pri grafických kartách je porovnanie rôznych algoritmov veĐmi dôležitejšie. Je to z toho dôvodu, že nové algoritmy urþené pre ne sa ešte len vyvíjajú a aj z dôvodu použitia rôznych pamätí v rôznych situáciách. Takisto rôzne nízkoúrovĖové optimalizácie, ako obchádzanie konfliktu bánk pamäte, môžu maĢ rôzny vplyv na rôzne grafické karty. Ako ćalší príklad je možné uviesĢ výpoþet pohybu chodcov (Varga a Mintál, 2014), kde sme implementovali výpoþet pohybu chodcov na grafickej karte. Vytvorili sme viacero algoritmov, z ktorých boli niektoré rýchlejšie pre menší poþet chodcov a niektoré pre väþší poþet. Ak sa bude automaticky vyberaĢ vhodný kernel, môže sa ušetriĢ veĐa þasu, priþom réžia výberu musí byĢþo najmenšia.

Z doteraz uvedených dôvodov vyplýva, že výber vhodného výpoþtu poþas simulácie by mohol priniesĢ znaþnú úsporu þasu a preto aj je implementovaný do navrhnutej platformy. Výber vhodného výpoþtu je dobre uplatniteĐný aj pri použití rôznych výpoþtových zariadení, kedy platforma by vybrala výpoþet vhodný pre dané zariadenie.

Optimalizácie podporované platformou

Z vymenovaných optimalizácii, sa v platforme používajú zmeny usporiadania vlákien a výber vhodného kernelu. Výber vhodnej kombinácie usporiadania vlákien a vhodného kernelu prebieha priamo poþas simulácie. Takto dokáže reagovaĢ na meniace sa a nepredvídateĐné situácie nastávajúce poþas simulácie. Algoritmus na výber správnej kombinácie je navrhnutý tak, aby þo najmenej spomaĐoval simuláciu. Preto po istom poþte iterácii jedným algoritmom prevedie výpoþet iným náhodným algoritmom. Ak tento nový algoritmus je rýchlejší predpokladá sa, že aktuálna situácia sa zmenila a je výhodnejšie používaĢ nový algoritmus. Preto sa bude istý poþet iterácii používaĢ nový algoritmus. Ak by bol pomalší, tak sa bude naćalej používaĢ pôvodný algoritmus. To isté platí pre usporiadanie vlákien s tým rozdielom, že sa nepoužívajú náhodne veĐkosti, ale blízke pôvodným Rozšírenie agentovej architektúry pre využitie výpoētového výkonu grafických kariet 60 veĐkostiam so zreteĐom na vlastnosti grafickej karty. Výsledky výberu vhodného kernelu sú uvedené v kapitole 6.4.

Algoritmus na výber vhodnej kombinácie je možné jednoducho nahradiĢ za vlastný. To je možné jednoduchým preĢažením jednej procedúry. UžívateĐ takto môže použiĢ komplikovanejší algoritmus na výber vhodného kernelu a poþtu vlákien v skupine, alebo deterministický algoritmus zohĐadĖujúci vlastnosti kernelov.

5.3.2 Interakcia s BDI

Vytvorená platforma mala byĢ overená v simulácii pohybu chodcov. Overená je na simulaþnom nástroji pohybu chodcov s názvom PedSim (Varga, 2011). Tento nástroj v súþasnosti podporuje modelovanie chodca pomocou paradigmy BDI (Bratman, 1987). To nám umožĖuje modelovaĢ inteligentnejšie modely chodcov. Napríklad si dokážu nájsĢ cestu v infraštruktúre ktorú nepoznajú, dokážu spoznávaĢ novu infraštruktúru a pod.

Takýto prístup však komplikuje výpoþet chodca, ktorý je reprezentovaný dynamickým agentom. Pôvodne, bez používania BDI, boli dynamickí agenti chodcov zodpovední len za pohyb chodca po voĐnej ploche. Kým chodci neboli modelovaný pomocou BDI, implementovali sme viacero spôsobov pohybu chodcov na grafických kartách (Mintál, 2013). Medzi nimi boli napríklad pohyb pomocou sociálnych síl (Helbing et al., 2005), alebo HiDAC (Pelechano et al., 2007). BDI dynamickí agenti sa riadia podĐa ABA-grafu. PodĐa ABA-grafu kontrolujú a plnia viaceré úlohy, z ktorých jedna je aj pohyb po voĐnej ploche, ak sa na nej nachádzajú. Ostatné úlohy sa väþšinou vykonajú rýchlo, ale pohyb po voĐnej ploche je výpoþtovo najnároþnejší. Chodec v každom ticku zistí, þi sa má poþítaĢ jeho pohyb, alebo nie.

Kećže chodec modelovaný pomocou BDI nevie þi v ćalšom kroku bude potrebovaĢ poþítaĢ pohyb, musí sa odhlásiĢ z výpoþtu pohybu pomocou grafických kariet. V ćalšom ticku, keć zistí že sa má poþítaĢ, tak sa prihlási a po výpoþte sa zasa odhlási. Toto spôsobuje výkonový problém, kećže sa musia stále prenášaĢ dáta o novom chodcovi. Ak by výpoþet na grafickej karte reagoval na prihlasujúcich a odhlasujúcich sa agentov, stále by musel meniĢ dáta na grafickej karte, þo by zaberalo veĐké množstvo þasu. Platforma umožĖuje pri registrácii dynamického agenta na výpoþet pomocou grafických kariet oznámiĢ, že þi sa má po každom ticku agent deaktivovaĢ. Tým sa pri prvom ticku po registrácii výpoþet agenta spustí, ale po Ėom sa zaznamená, že je deaktivovaný. Agent môže oznámiĢ simulácii, že Rozšírenie agentovej architektúry pre využitie výpoētového výkonu grafických kariet 61 chce byĢ poþítaný aj v ćalšom/aktuálnom ticku. Ak to spraví pred ukonþením aktuálneho ticku, bude poþítaný v aktuálnom ticku. Ak to spraví v synchronizaþnej správe, bude poþítaný v ćalšom ticku. Ak sa agent znovu neprihlási do ćalšieho ticku, bude odobratý z výpoþtu.

Týmto spôsobom je umožnené poþítaĢ dynamických agentov na grafickej karte, ktorí by sa pôvodne museli stále odstraĖovaĢ a ukladaĢ do pamäte grafickej karty, s výrazne menšou réžiou. Dynamický agent sa týmto spôsobom dokonca nemusí zakaždým odhlasovaĢ z výpoþtu, ale len oznámiĢ, že aj v ćalšom ticku sa chce poþítaĢ na grafickej karte.

Týmto návrhom platforma podporuje aj výpoþty dynamických agentov modelovaných pomocou BDI, priþom sa nepresúvajú nadbytoþné dáta. Paradigma BDI má byĢ integrovaná do architektúry ABAsim a tým pádom môže byĢ používaná aj v iných simuláciách. Potom by bolo umožnené aj v ćalších simuláciách využiĢ navrhnutú platformu. Takýmto spôsobom platforma podporuje aj iné prístupy výpoþtu dynamických agentov, ktoré by dopredu nevedeli þi ich výpoþty na grafickej karte budú potrebné aj v ćalšom ticku.

Pri písaní tejto práci sa podpora BDI v architektúre ABAsim ešte len vyvíja. Keć bude dokonþená, bolo by možné presunúĢ jej výpoþet na grafické karty. Význam to má z toho dôvodu, že sa najþastejšie používa v dynamických agentoch. Najprv však musí byĢ integrácia BDI do ABAsim dokonþená a otestovaný vplyv BDI na rýchlosĢ výpoþtu simulácie.

5.3.3 Popis þastí platformy umožĖujúce jej použitie v ABAsim

Táto þasĢ platformy uĐahþuje implementáciu výpoþtu dynamických agentov na grafických kartách. Zjednodušený UML diagram tried používaných pri implementácii výpoþtov na grafických kartách poþas simulácii je možné vidieĢ na obrázku 17. Rozšírenie agentovej architektúry pre využitie výpoētového výkonu grafických kariet 62

Obrázok 17: Zjednodušený UML diagram tried závislých na simulácii2 Z UML diagramu na obrázku 17 je pre používateĐa najdôležitejšia trieda TECSimKernel. Jej zdedením a implementovaním potrebných funkcií, sa definuje výpoþet, ktorý bude vykonávaný na grafickej karte poþas simulácie. Presnejší popis celého postupu pre výpoþet dynamického agenta na grafickej karte je popísaný v prílohe. TECSimulation je potomok simulácie, slúžiaci na registráciu výpoþtov, inicializáciu výpoþtov, spúšĢanie výpoþtov a oznamovanie o pridaní alebo odobraní dynamického agenta simulaþnému kernelu. TECKernelData je len pomocná trieda, ktorá pre daný þíselný kód obsahuje simulaþné kernely, agentov ktorí sa majú nimi poþítaĢ a informácie o tom, ktorý simulaþný kernel sa má vybraĢ. TECAgent je potomok dynamického agenta, ktorý doĖho pridáva funkcie na zaregistrovanie sa a odhlásenie sa z výpoþtu na grafickej karte.

2 tActor predstavuje dynamického agenta. Názov actor je použitý z historických dôvodov. Praktické použitie a overenie použiteűnosti navrhnutej platformy 63

6 Praktické použitie a overenie použiteĐnosti navrhnutej platformy

Kapitola popisuje praktické ukážky použitia platformy. Tieto ukážky umožĖujú si jednoducho predstaviĢ, ako je možné platformu používaĢ. Ukážky sú vyhodnotené z þasového hĐadiska a porovnané. Vyhodnotenie je zamerané na viaceré aspekty, ako porovnanie platformy s programom vytvoreným priamo v OpenCL, porovnanie s procesorom, alebo porovnanie rôznych algoritmov riešiacich rovnakú úlohu.

Experimenty, ktoré nepoužívali platformu v simulácii, boli opakované 100x a zobrazované budú ich priemerné hodnoty. Experimenty používajúce platformu poþas simulácie boli spustené aspoĖ 20 000 simulaþných tikov, þo predstavuje rovnaký poþet výpoþtov. Výsledky porovnaní boli vyhodnocované na poþítaþi s nasledujúcimi parametrami, ak nebude uvedené inak:

x Procesor: Intel(R) Core(TM)2 Duo P8400 2,27GHz

x Grafická karta: Nvidia GeForce 9600M GT 512MB

Platforma bola samozrejme testovaná na viacerých iných zariadeniach. Medzi ne patrili viaceré grafické karty Nvidia, AMD a procesor Intel.

Prvý experiment je vykonaný na algoritme sþítania vektorov. Pomocou neho je porovnaný výpoþet vytvorený v platforme s výpoþtom vytvoreným priamo v OpenCL. Tiež je na Ėom ukázaný vplyv prenosu dát na výpoþet. Druhý experiment je vykonaný na algoritme násobenia matíc. V Ėom je predvedené o koĐko môže byĢ výpoþet na grafickej karte rýchlejší oproti procesoru. ZároveĖ je porovnaná jednoduchá implementácia algoritmu s optimalizovanou implementáciou pre grafické karty. Nasleduje ukážka výpoþtu poþas simulácie. JednaĢ o simuláciu pohybu chodcov v simulaþnom nástroji PedSim. V závere kapitoly je otestovaná vlastnosĢ architektúry vybrania vhodného kernelu pre použitie poþas simulácie.

6.1 6þítanie vektorov

Ako prvý príklad je uvedené jednoduché sþítanie dvoch polí. Tento príklad je veĐmi primitívny, ale môžeme na Ėom ukázaĢ, ako sa jednoducho dá vytvoriĢ výpoþet používajúci navrhnutú platformu. Pracuje tak, že i-ty prvok z prvého vstupného poĐa sþíta s i-tym Praktické použitie a overenie použiteűnosti navrhnutej platformy 64 prvkom druhého vstupného poĐa a výsledok zapíše na i-tu pozíciu výstupného poĐa. Príklad je otestovaný a porovnaný s výpoþtom na procesore a s rovnakým výpoþtom vytvoreným v OpenCL. Tým je možné porovnaĢ rozdiely hlavne medzi programom spúšĢaným pomocou vytvorenej platformy a programom vytvoreným priamo v OpenCL. Porovnanie s procesorom nie je až tak vypovedajúce, lebo táto úloha nie je veĐmi vhodná pre grafické karty. Pre porovnanie procesora a grafickej karty je vhodnejší druhý príklad.

Najprv si uvedieme kód na výpoþet sþítania polí, ktorý sa spúšĢa pomocou platformy:

Algoritmus 1: 6þítanie vektorov pomocou platformy

1. function ArrayAdd(A, B: TArray): TArray; 2. var // TArray === array of Single 3. len: Integer; 4. begin 5. len := Length(A); 6. FArrayAdd := TECKernel.Create; 7. FArrayAdd.Code := 'c[id] = a[id] + b[id];'; 8. FArrayAdd.addParamArr('a'); 9. FArrayAdd.addParamArr('b'); 10. FArrayAdd.addParamArr('c'); 11. FArrayAdd.setParamLength('c', len); // alokacia pamate 12. // ------13. // Nasledujuci blok je mozne viacnasobne spustat s roznymi 14. // hodnotami dat 15. //------16. FArrayAdd['a'] := A; 17. FArrayAdd['b'] := B; 18. FArrayAdd.Compute(len); 19. Result := TArray(FArrayAdd['c']); 20. 21. FArrayAdd.Free; 22. end;

Takýto kód je úplný (netreba spúšĢDĢ žiadne ćalšie funkcie platformy) a je funkþný, ak sa v poþítaþi nachádza výpoþtové zariadenie podporujúce OpenCL. Platforma toto zariadenie inicializuje a vykoná všetky úkony, aby popísaný výpoþet mohol byĢ na nej spustený.

Riadok 6 vytvára inštanciu objektu, používaného na výpoþty v platforme. Riadok 7 vkladá kód, ktorý sa má vykonávaĢ na výpoþtovom zariadení. Riadky 8 až 10 definujú parametre a typy, ktoré pôjdu do výpoþtu. Riadok 11 slúži na alokovanie pamäte Praktické použitie a overenie použiteűnosti navrhnutej platformy 65 pre výstupný parameter. Tento príkaz musí byĢ vždy zadaný pre výstupné parametre. Riadky 16 až 19 je následne možné volaĢ aj viackrát, priþom môžeme stále meniĢ vstupné dáta. Riadky 16 až 17 slúžia na zadanie vstupných dát. Riadok 19 spusti výpoþet s tým, že výpoþet sa vykoná na toĐkých vláknach, koĐko je prvkov v poli. Riadok 19 naþíta výsledky výpoþtu. V tomto prípade musíme špecifikovaĢ typ premennej. Ak by sme použili príkaz getParam, tak by sme nemuseli zadávaĢ typ a volanie by vypadalo nasledovne:

19. FSimpleAdd.getParam('c', @c);

Prezentovaný kód výpoþtu zaberá 11 riadkov spolu s vytvorením a zrušením inštancie objektu na výpoþet. Z uvedeného kódu by sa dali ešte 3 riadky ušetriĢ, ak by sme pri definovaní vstupných parametrov zadalo rovno aj ich hodnoty a pri výstupnom parametri zadefinovali hneć jeho dĎžku. Takto však bolo ukázané, že vytvorený objekt výpoþtu je možné opakovane použiĢ na polia s rôznymi dátami a meniacimi sa dĎžkami. Rovnaký algoritmus vytvorený v OpenCL zaberal 29 riadkov, z þoho bolo 6 riadkov pre inicializáciu grafickej karty a 5 riadkov na zadanie vykonávaného kódu. Pri vytváraní algoritmu som sa snažil použiĢþo najmenej príkazov, inicializované bolo len jedno zariadenie, a to hneć prvé a neboli kontrolované návratové hodnoty príkazov pre kontrolu chyby pri vykonávaní. Príkazy volané v OpenCL sú vždy dlhé a s veĐkým poþtom parametrov. Približná dĎžka príkazov bola 50 znakov a najdlhší príkaz, slúžiaci na spustenia výpoþtu, mal 83 znakov.

Najprv sú uvedené dôvody, preþo boli testované vybraté þasti algoritmu. Predpokladá sa že výpoþtový objekt, spolu so zadaním algoritmu a typov parametrov, sa vytvorí raz (riadky 6 až 10 algoritmu 1) a následne môže byĢ výpoþet spúšĢaný viackrát s rôznymi dátami. Ak sa výpoþet vykonáva iba raz, predpokladá sa že je veĐmi nároþný, inak by sa neoplatilo ho implementovaĢ. Ak sa vykonáva viac krát, inicializaþná þasĢ tvorí len malú þasĢ celkového vykonávaného þasu. V nej je len jediná operácia, ktorá môže zaberaĢ istý þas a tou je kompilácia. Kompilácia sa vykonáva iba raz a následne sa porovnáva hash kódu s už skompilovanými kódmi. Z týchto dôvodov sa môže inicializaþná þasĢ zanedbaĢ.

Porovnávajú sa dva dva þasy výpoþtov. Prvý obsahuje prenos dát na aj z grafickej karty a samotný výpoþet. Jedná sa o riadky 16 až 19. Druhý obsahuje len samotný výpoþet, þiže iba riadok 18. To odráža situáciu, ak by dáta boli už na grafickej karte, napríklad z predošlých výpoþtov na grafickej karte a následne by sme chceli spustiĢ ich ćalšie spracovanie. Výsledok tiež ostane na grafickej karte pre ćalšie spracovanie. Výsledky týchto Praktické použitie a overenie použiteűnosti navrhnutej platformy 66 porovnaní je možné vidieĢ na obrázku 18. Os x popisuje aké veĐké sú vstupné polia. Oznaþenie EC znamená použitie platformy, CPU oznaþuje procesor a OpenCL je znamená použitie þistého OpenCL. Compute oznaþuje že merané boli iba þasy výpoþtu a Compute+Data znamená, že bol meraný výpoþet aj s presunom dát. Pre procesor je zobrazený len jeden výpoþet, pretože dáta sa nepresúvajú a má ich priamo prístupné.

Obrázok 18: Porovnanie þasov výpoþtu sþítavania polí

Z grafov je možné vidieĢ hneć viacero vlastnosti výpoþtov na grafických kartách. Po prvé je možné porovnaĢ výpoþet pomocou platformy s výpoþtom priamo v OpenCL. Tým sa zistí, þi platforma nepridáva k výpoþtu zbytoþne veĐkú réžiu. Z grafu vyplýva, že pri porovnaní samotného výpoþtu, sú þasy približne rovnaké. Niekedy je rýchlejší výpoþet platformy a niekedy OpenCL. Tieto malé výkyvy môžu byĢ spôsobené tým, že grafická karta sa musí používaĢ aj na zobrazovanie. V podstate sa ale dá prehlásiĢ, že réžia je zanedbateĐná. Pri porovnaní þasov výpoþtu s prenosom dát, medzi platformou a þistým OpenCL je vidno, že platforma je o nepatrnú þasĢ pomalšia. Tento rozdiel je však veĐmi malý. Jedná sa približne o jednu milisekundu. Môžeme tvrdiĢ, že platforma má zanedbateĐné spomalenie oproti programu vytvorenému priamo v OpenCL. Praktické použitie a overenie použiteűnosti navrhnutej platformy 67

Obrázok 19: Pomer þasu výpoþtu s prenosom dát k samotnému výpoþtu

Ćalej je možné vidieĢ jeden z dôvodov, preþo tento výpoþet nie je vhodný pre grafické karty. Tým je þas potrebný na prenos dát, oproti þasu samotného výpoþtu. Tento pomer je znázornený na obrázku 19. Samotný výpoþet v tejto situácii je veĐmi rýchly, kećže sa jedná len o sþítanie dvoch þísel. Pritom na každý takýto výpoþet je nutné preniesĢ tri þísla medzi operaþnou pamäĢou poþítaþa a grafickej karty. Pre efektívne využívanie grafických kariet, je vhodné, aby dáta potrebné k výpoþtu boli þo najmenšie. Na obrázku je možné vidieĢ že pre väþšie polia je pomer þasu na prenos dát a výpoþet približne 13-krát väþší ako samotný výpoþet.

Na obrázku 18 je vidno, že výpoþet pomocou grafickej karty, ak zarátame aj prenos dát, je pomalší ako výpoþet na procesore. Ako bolo spomenuté je to spôsobené nie príliš vhodnou úlohou pre grafické karty. Keć však porovnáme þas samotného výpoþtu na grafickej karte oproti þasu výpoþtu procesora je vidno, že výpoþet na grafickej karte je rýchlejší. Z toho vyplýva, že ak už máme dáta na grafickej karte, napríklad keć vykonávame viaceré výpoþty na nej za sebou, vždy sa oplatí previesĢ výpoþet na nej, ak existuje paralelný Praktické použitie a overenie použiteűnosti navrhnutej platformy 68 algoritmus daného výpoþtu. Tento prístup spustenia viacerých kernelov nám platforma umožĖuje využiĢ, vćaka možnosti priradenia jedného parametru viacerým kernelom.

6.2 Násobenie matíc

V tomto príklade je uvedený výpoþet násobenia matíc, ktorý je už vhodnejší pre grafické karty. Výpoþet je už nároþnejší, kećže na výpoþet jedného prvku výslednej matice je nutné spracovaĢ jeden riadok a jeden stĎpec vstupných matíc. Tým je možné lepšie využiĢ grafické karty.

Vytvorený kód ma urþité obmedzenia. Pre jednoduchosĢ, algoritmus môže násobiĢ len štvorcové matice. Ćalej matice sú spracovávané ako jedno dlhé pole a nie ako matica. Index prvku matice v poli je daný nasledujúcim vzĢahom:

x = j * length + i.

Priþom length je veĐkosĢ jedného rozmeru matice. Matice sú vytvárané s presnou veĐkosĢou, aby sme nemuseli deaktivovaĢ nadbytoþné vlákna. Nasledujúci kód zobrazuje vytvorenie kernelu, ktorý slúži na násobenie matíc.

Algoritmus 2: Násobenie matíc pomocou platformy

1. function MatrixMul(A, B: TArray): TArray; 2. var 3. len: Integer; 4. begin Praktické použitie a overenie použiteűnosti navrhnutej platformy 69

5. len := Sqrt(Length(A)); 6. FMatrixMul := TECKernel.Create; 7. FMatrixMul.Code := 8. 'float value = 0;' + 9. 'for (int k = 0; k < SIZE_G(0) ; k++) ' + 10. ' value += a[ID_G(1) * length + k] * b[k * length + ID_G(0)]; ' + 11. 'c[ID_G(0) + length * ID_G(1)] = value; '; 12. FMatrixMul.addParamArr('a'); 13. FMatrixMul.addParamArr('b'); 14. FMatrixMul.addParamArr('c'); 15. FMatrixMul.addParam('length'); 16. FMatrixMul.setParamLength('c', len*len); 17. FMatrixMul['length'] := @len; 18. 19. FMatrixMul['a'] := A; 20. FMatrixMul['b'] := B; 21. FMatrixMul.Compute([len, len]); 22. Result := TArray(FMatrixMul['c']); 23. 24. FMatrixMul.Free; 25. end;

Rozdiel oproti sþítaniu vektorov je len v riadkoch 5, 7, 16 a 21, Riadky 5 a 16 odrážajú len fakt, že pracujeme s maticou a nie s poĐom a tým padom musíme pracovaĢ s iným poþtom prvkov. Riadok 16 popisuje to, že výpoþet sa spúšta s vláknami usporiadanými v dvoch rozmeroch. Paralelne sa poþíta každý jeden prvok výstupnej matice a indexovaĢ ho môžeme pomocou ID_G(0) a ID_G(1). Algoritmus pre výpoþet jedného prvku je znázornený na riadkoch 7 až 11. Ten prechádza hodnoty v príslušnom riadku a stĎpci a sþítava násobky týchto hodnôt. Výslednú hodnotu uloží na požadované miesto vo výslednej matici. Praktické použitie a overenie použiteűnosti navrhnutej platformy 70

Obrázok 20: ýas výpoþtu násobenia matíc pomocou platformy a procesora

Na obrázku 20 je možné vidieĢ þas výpoþtu algoritmu, poþítaného pomocou platformy, ktorého kód je popísaný v algoritme 2 a þas výpoþtu algoritmu poþítaného priamo na procesore. EC predstavuje výpoþet pomocou platformy a CPU výpoþet na procesore. EC_Opt predstavuje optimalizovaný algoritmus, ktorý je popísaný v algoritme 3. Z obrázku vyplýva, že presun dát nemal na výpoþet takmer žiaden vplyv.

Nasleduje popis optimalizácie výpoþtu. Pre jej aplikovanie potrebujeme poznaĢ architektúru grafických kariet. Vo výpoþte sa veĐa krát pristupuje na rovnaké prvky vstupných matíc. Bolo by možné urýchliĢ výpoþet tým, že by sa tieto prvky uložili do rýchlejšej pamäte a následne by bolo k nim viac krát pristupované. Na túto situáciu sa dá využiĢ lokálna pamäĢ. Je to malá rýchla pamäĢ, ktorá je zdieĐaná v skupine vlákien. Takže vlákna v skupine môžu požadované prvky naþítaĢ iba raz a následne ich viac krát používaĢ. Táto pamäĢ je pomerne malá, preto sa naþítavanie musí rozdeliĢ do viacerých krokov. Praktické použitie a overenie použiteűnosti navrhnutej platformy 71

Pôvodný algoritmus staþí zmeniĢ len na dvoch miestach. Treba požiadaĢ o lokálnu pamäĢ, þo sa pre globálnu pamäĢ v predošlom kóde robilo na riadkoch 12 až15, pomocou nasledujúcich riadkov.

kernel.addParamArrLocal('Al', block_size*block_size); kernel.addParamArrLocal('Bl', block_size*block_size);

Tým sa vytvorí miesto v lokálnej pamäti, pre naþítanie þasti matice A a þasti matice B. Poslednú zmenu þo treba urobiĢ, je zmeniĢ algoritmus výpoþtu, ktorý sa nachádzal na riadkoch 8 až 11 za nasledujúci algoritmus:

Algoritmus 3: Optimalizovaný kód násobenia matíc implementovaný v platforme

1. 'float value = .0f;' + 2. 'for (int ok = 0; ok < length; ok += SIZE_L(0) ) {' + 3. ' Al[ID_L(0)*SIZE_L(0)+ID_L(1)] = a[ length*(ID_G(0) ) + ID_L(1) + ok ];' + 4. ' Bl[ID_L(0)*SIZE_L(0)+ID_L(1)] = b[ length*(ID_L(0)+ok) + ID_G(1) ];' + 5. ' SYNCHRONIZE' + 6. ' for (int k = 0; k < SIZE_L(0); k++) ' + 7. ' value += Al[ID_L(0)*SIZE_L(0)+k] * Bl[k*SIZE_L(0)+ID_L(1)]; ' + 8. ' SYNCHRONIZE }' + 9. 'c[ID_G(1) + length * ID_G(0)] = value;';

Tento algoritmus je už zložitejší. Riadok 2 popisuje že budeme naþítavaĢ a spracovávaĢ riadky a stĎpce po blokoch o veĐkosti skupiny. Riadky 3 a 4 naþítajú relevantnú þasĢ vstupných matíc do lokálnej pamäte. Riadky 5 a 8 slúžia na to, aby všetky vlákna dokonþili svoju þinnosĢ, aby dáta boli konzistentné. Zvyšok je už obdobou pôvodného algoritmu, keć postupne sþítavame násobky a výsledok uložíme na požadovanú pozíciu. Praktické použitie a overenie použiteűnosti navrhnutej platformy 72

Obrázok 21: Zrýchlenie výpoþtu matice pomocou platformy oproti CPU

Na obrázku 20 je možné vidieĢ porovnanie þasov všetkých algoritmov pre rôzne veĐkosti matíc. Vidno že prvý algoritmus implementovaný v platforme je rýchlejší ako procesor, ale optimalizovaný algoritmus je omnoho rýchlejší. Zrýchlenie oboch algoritmov, voþi algoritmu na procesore, je znázornené na obrázku 21. Z grafu na obrázku 21 vidno, že pre matice väþšie ako 150x150 je výpoþet prvého algoritmu na grafickej karte, približne 2,5 krát rýchlejší, voþi výpoþtu na procesore. Optimalizovaný výpoþet je približne 6 krát rýchlejší, priþom zrýchlenie jemne stúpa s väþšími maticami. Praktické použitie a overenie použiteűnosti navrhnutej platformy 73

Obrázok 22: VeĐkosĢ matice, pri ktorej platforma je rýchlejšia ako CPU

Z obrázku 20 však nevidno kedy je vhodné použiĢ výpoþet matice na procesore a kedy už pomocou platformy. Pri menších maticiach je réžia väþšia. Toto je možné dobre vidieĢ aj na obrázku 22. Pre optimalizovaný výpoþet, sa na testovanom poþítaþi oplatí poþítaĢ matice väþšie ako 50 prvkov.

6.2.1 Výpoþet dynamických agentov

Použitie platformy poþas simulácie je predstavené na jednoduchej ukážke vozíkov pohybujúcich sa k cieĐu. Tento príklad je veĐmi jednoduchý, ale práve preto sa na Ėom dá Đahko pochopiĢ používanie platformy poþas simulácie. Pre zložitejšie modely je potrebné nahradiĢ len algoritmus, ktorý sa má vykonaĢ na grafickej karte a pracovaĢ s viacerými dátami.

Príklad pozostáva z haly, v ktorej sa pohybujú vozíky k definovanému cieĐu. V každom ticku sa pohnú o normalizovaný vektor smerujúci k danému cieĐu. Predpokladá sa, že cesty sú dopredu vypoþítané a vozíkom sú prideĐované ciele tak, aby sa nezrazili, ani do niþoho iného nenabúrali.

Nasleduje kód popisujúci vytvorenie výpoþtu vozíka, ktorý sa je možné vykonaĢ na grafickej karte. Praktické použitie a overenie použiteűnosti navrhnutej platformy 74

Algoritmus 4: Výpoþet pohybu vozíka pomocou platformy

1. const constVozik = 20200; 2. 3. TECVozik = class(TECSimKernel) 4. begin 5. procedure addAgent(paAgent: tActor); override; 6. procedure AfterCompute(); override; 7. constructor Create(paSim: tSimulation); 8. end; 9. 10. constructor TECVozik.Create(paSim: tSimulation); 11. begin 12. inherited Create(paSim, constVozik); 13. Kernel := TECKernel.Create; 14. Kernel.Code := 'Pozicia[ID] += normalize(Ciel[ID]- Pozicia[ID]);'; 15. 16. Kernel.addParamArr('Pozicia'); 17. Kernel.addParamArr('Ciel', mtReadOnly); 18. end; 19. 20. procedure TECVozik.addAgent(paAgent: tActor); 21. begin 22. addAgentData('Pozicia', paAgent.UniqueID, agentVozik(paAgent).pozicia); 23. addAgentData('Ciel', paAgent.UniqueID, agentVozik(paAgent).ciel); 24. end; 25. 26. procedure TECVozik.AfterCompute(); 27. var 28. pozicie: TArray; 29. I: Integer; 30. begin 31. pozicie = TArray(Kernel['Pozicia']); 32. for I:= 0 to length(Pozicie) - 1 do 33. begin 34. Vykresli(Pozicie[I]); 35. ZbierajStatistiky(AgentMap[I], Pozicie[I]); 36. end; 37. setLength(pozicie, 0); 38. end;

Najprv je zadefinovaná konštanta oznaþujúca výpoþet na riadku 1. Ćalej je vytvorený potomok TECSimKernel na riadkoch 3 až 9. V konštruktore je použitá konštanta výpoþtu a vytvorený výpoþtový kernel. Ten obsahuje kód na priblíženie sa k cieĐu a definovanie Praktické použitie a overenie použiteűnosti navrhnutej platformy 75 parametrov hlavnej funkcie. Kód je pri praktickom použití oveĐa dlhší a komplikovanejší, ale ostatné þasti ukážkového príkladu sa zmenia len minimálne. V procedúre addAgent sa posielajú na grafickú kartu nové dáta v situácii, že vznikol nový dynamický agent. Pri zániku dynamického agenta, dáta definované pomocou addAgentData uvoĐní platforma. Kećže výpoþet je potrebné spúšĢDĢ s poþtom vlákien rovnajúcim sa poþtu agentov, nie je potrebné niþ upravovaĢ, pretože platforma spustí výpoþet za nás. Posledná procedúra je AfterCompute, ktorá naþíta nové dáta o polohách vozíkov z grafickej karty a zobrazí ich nové polohy, priþom zozbiera aj štatistiky.

Nato aby sa tento výpoþet používal poþas simulácie, je potrebné urobiĢ ešte dve veci. Za prvé vytvoriĢ inštanciu triedy TECVozik. Za druhé je po vytvorení dynamického agenta potrebné ho zaregistrovaĢ na výpoþet pomocou nasledujúceho príkazu :

ECSubscribeAction('constVozik');

Pre správnu funkþnosĢ treba maĢ simuláciu a dynamického agenta zdedených z tried poskytovaných platformou.

6.3 Výpoþet pohybu chodcov

Experiment vyhodnocujúci praktické nasadenie platformy v simulácii je vytvorený v nástroji PedSim. Nástroj PedSim slúži na modelovanie pohybu chodcov, pomocou rôznych druhov pohybu. Pomocou platformy bol implementovaný výpoþet pohybu chodcov Local Cells (Varga a Mintál, 2014). Vyhodnotené je zrýchlenie dosiahnuté touto implementáciou, oproti implementácii na procesore.

Pohyb pomocou Local Cells rozdeĐuje okolie chodca na rovnako veĐké bunky urþitej veĐkosti a jednu bunku pod chodcom. Znázornenie buniek je možné vidieĢ na obrázku 23. Chodec v každom kroku tieto bunky vyhodnotí podĐa toho, þi sa v nich nachádza prekážka. Ak sa v nich prekážka nachádza, tak do týchto buniek nepôjde. Ak sa v nich nenachádza žiadna prekážka, tak zistí pomocou gradientovej mapy, ako je bunka vzdialená od cieĐa. Následne sa pohne do bunky s najmenšou vzdialenosĢou. Toto bol zjednodušený popis výpoþtu, presný popis je možné nájsĢ v þlánku (Varga a Mintál, 2014). Praktické použitie a overenie použiteűnosti navrhnutej platformy 76

Obrázok 23: Vyhodnocované bunky chodca v Local Cells

Pre výpoþet tohto pohybu je implementovaných viacero algoritmov, s rôznymi optimalizáciami. Porovnaná je základná implementácia bez optimalizácii a najrýchlejšia implementácia, voþi implementácii na procesore. Najrýchlejšia implementácia obsahuje viaceré optimalizácie, ako rýchlejšie vyhĐadávanie chodcov v bunkách. Kód týchto algoritmov nie je uvádzaný, lebo je príliš rozsiahly.

Obrázok 24: Infraštruktúra použitá pri testovaní Local Cells (Varga a Mintál, 2014) Praktické použitie a overenie použiteűnosti navrhnutej platformy 77

Algoritmy boli testované na infraštruktúre Mariánskeho námestia, nachádzajúceho sa v Žiline. Infraštruktúra je znázornená na obrázku 24. Chodci ním prechádzali pomedzi uliþky a aj po voĐnom priestranstve, priþom prúdy chodcov sa križovali, spájali a viedli proti sebe, þím pokryli rôzne interakcie.

Pre porovnanie algoritmov bol použitý nasledujúci hardvér :

x Procesor Intel Core i7-740 QM

x Grafická karta NVidia GeForce GT 420M

Výsledky porovnania výpoþtov je možné vidieĢ na obrázku 25. Z výsledkov vyplýva, že prvotná implementácia pohybu bola takmer 3 násobne rýchlejšia oproti implementácii na procesore. Optimalizovaná verzia výpoþtu dosahovala 10 násobné zrýchlenie oproti implementácii na procesore.

Obrázok 25: Porovnanie þasov výpoþtov Local Cells

Výsledný pohyb chodcov po voĐnej ploche je možné vidieĢ na obrázku 26. Z porovnania algoritmov používajúcich platformu a algoritmu vykonávanom na procesore je zrejmé, že pri praktickom použití môže navrhnutá platforma výrazne urýchliĢ výpoþet. Praktické použitie a overenie použiteűnosti navrhnutej platformy 78

Obrázok 26: Chodci vykonávaní na grafických kartách (Varga a Mintál, 2014).

6.4 Automatický výber vhodného kernelu

V tejto þasti je otestovaná funkcia platformy, ktorá poþas simulácie automaticky vyberá najrýchlejší kernel. Otestovaná je v nástroji PedSim na pohybe chodcov pomocou Local Cells. Porovnávané sú dva algoritmy implementované pomocou platformy, ktoré dosahujú podobné þasové výsledky. Každý algoritmus je však rýchlejší v inej situácii. Praktické použitie a overenie použiteűnosti navrhnutej platformy 79

Obrázok 27: ýas výpoþtu rôznych kernelov, toho istého pohybu

Porovnávaný je optimalizovaný algoritmus z predošlej podkapitoly a algoritmus vyhodnocujúci každú bunku chodca paralelne. My už vieme, že prvý algoritmus je rýchlejší pre väþší poþet chodcov a druhý pre menší poþet chodcov. Pri použití automatického výberu kernelu netreba vedieĢ ktorý algoritmus je kedy rýchlejší, staþí oba algoritmy oznaþLĢ rovnakým þíselným kódom a platforma si poþas simulácie sama vyberie rýchlejší. Túto funkciu je vhodné použiĢ aj pri distribúcii programu na iné poþítaþe. Na výpoþtových zariadeniach týchto poþítaþov môže ísĢ rýchlejšie iný algoritmus, ako na testovanom zariadení. Praktické použitie a overenie použiteűnosti navrhnutej platformy 80

Obrázok 28: PravdepodobnosĢ použitia kernelu pre výpoþet pohybu chodca

Na obrázku 27 je možné vidieĢ þas výpoþtu dvoch popisovaných kernelov. Algoritmus z kapitoly 6.3 je oznaþený ako LC base a algoritmus vyhodnocujúci bunky paralelne je oznaþený ako LC parallel. LC parallel je rýchlejší do 200 chodcov a potom je rýchlejší druhý algoritmus. Skokový nárast þasu pre LC base bol pravdepodobne spôsobený tým, že paralelne sa vykonávalo maximálne 512 vlákien a po nich sa vykonali ćalšie vlákna. Na obrázku 28 je znázornený graf pravdepodobnosti použitia kernelu, v závislosti od poþtu chodcov. Poþas simulácii sa poþet chodcov najþastejšie pohyboval okolo 100 chodcov a 900 chodcov, preto pravdepodobnosti pri týchto þíslach sú presnejšie. Na grafe je možné vidieĢ že do 200 chodcov bol výrazne používaný kernel poþítajúci bunky paralelne. Od 200 chodcov bol zas þastejšie používaný druhý kernel. Lepšie je to možné vidieĢ na vyhladenom grafe, ktorý je zobrazený na obrázku 29. Praktické použitie a overenie použiteűnosti navrhnutej platformy 81

Obrázok 29: Vyhladená pravdepodobnosĢ použitia kernelov Záver 82

7 Záver

Súþasná doba si vyžaduje vypracovávaĢ špecifické simulácie v rôznych oblastiach. Napríklad v medicíne na analýzu rakovinových buniek, alebo v doprave pre odhad dopadu meškania dopravných prostriedkov. Väþšina simulácii je však veĐmi nároþná na výpoþtové prostriedky. Z tohto dôvodu sú tieto simulácie zdĎhavé a musia byĢ zjednodušované, obmedzované na urþitú þasĢ modelu, alebo inak optimalizované. Pri vykonávaní nároþných simulácií je vhodné þo najlepšie využiĢ hardvér. Málo využívaným a potenciálne veĐmi výkonným hardvérom sú grafické karty, preto sa táto práca zaoberá využitím tohto hardvéru v simuláciách.

Za hlavný prínos práce je možné považovaĢ rozšírenie agentovej architektúry ABAsim o možnosĢ využitia výpoþtového výkonu grafických kariet. To bolo dosiahnuté vytvorením platformy umožĖujúcej jednoduché použitie grafických kariet a jej integrovaním do architektúry ABAsim. Použitím rozšírenej architektúry je možné simulovaĢ veĐmi rozsiahle modely v kratšom þase pri použití dostupného hardvéru. Špeciálne sa podpora zameriava na dynamických agentov, ktorí vykonávajú rovnaké þinnosti a je ich väþší poþet, þo predstavuje vhodnú kombináciu pre efektívne využitie grafických kariet. Ćalej umožĖuje optimalizovaĢ tieto výpoþty priamo za behu simulácie, hlavne ak sú dostupné viaceré algoritmy na výpoþet agentov.

9ćaka použitiu OpenCL, ako medzivrstvy na komunikáciu s grafickou kartou, je možné na výpoþty používaĢ takmer každú súþasnú grafickú kartu, ako aj iné výpoþtové zariadenia (napr. procesory). Navrhnutá a implementovaná platforma dokáže sama vybraĢ vhodné zariadenie pre výpoþty a automaticky ho inicializovaĢ. Vćaka tomu je možné sa v nej zameraĢ priamo na implementáciu algoritmov. UmožĖuje užívateĐsky jednoduché a rýchle zadávanie dát a algoritmov, priþom používateĐ nemusí poznaĢ architektúru grafických kariet. VyužiteĐná je aj mimo simulácii, ale úloha sa musí daĢ rozdeliĢ na paralelné þasti, ktoré vykonávajú podobný algoritmus. V simulácii je táto podmienka splnená vćaka vlastnostiam dynamických agentov. Pri nich dokáže platforma priamo poþas simulácie vyberaĢ vhodnú kombináciu výpoþtov a rozloženia vlákien pre dosiahnutie najrýchlejšieho výpoþtu. Platforma ponúka viaceré algoritmy, ktoré sú optimalizované pre vykonávanie na grafických kartách. Záver 83

Práca prináša aj pedagogický prínos, keć umožĖuje študentom využívaĢ výpoþtový výkon grafických kariet bez hlbších znalostí o ich architektúre. Vytvorená bola aj aplikácia s príkladmi použitia, ktorá slúži na oboznámenie sa používaním platformy.

Implementovaná platforma je vyvíjaná a používaná v simulaþnom nástroji PedSim. Nástroj PedSim slúži na simulovanie pohybov chodcov. V nástroji sa platforma používa ako pred simuláciou na urýchlenie prípravy dát pre simulaþný beh, tak aj poþas simulácie pre výpoþet pohybu chodcov. Modely pohybu chodcov používané v nástroji PedSim boli integrované do nástroja Villon. Simulaþný nástroj Villon slúži na simulovanie rôznych druhov dopravy a integrácia umožnila simulovaĢ aj pohyb chodcov. Villon používa agentové jadro ABAsim, vćaka þomu bude môcĢ využiĢ vytvorenú platformu a tým aj výpoþtový výkon grafických kariet. Kećže Villon sa používa v komerþnej sfére, využitie platformy umožní vytváraĢ väþšie a presnejšie modely, z þoho majú prospech zákazníci.

Existujú viaceré otvorene oblasti, v ktorých je možné platformu vylepšiĢ. Rozšírenie o asynchrónne vykonávanie, ktoré by mohlo priniesĢćalšiu veĐkú úsporu výpoþtového þasu. Implementovaním ćalších paralelných algoritmov optimalizovaných pre grafické karty, ktoré by užívateĐ mohol jednoducho použiĢ, bez nutnosti hlbšieho oboznámenia sa s architektúrou grafickej karty. Zoznam použitej literatúry 84

Zoznam použitej literatúry

ADAMKO, N., KLIMA, V. 2006. Agent based simulation architecture augmented by actors. In: NKETSA, A., PALUDETTO, M., BERTELLE, C. ESM 2006 - The 2006 European Simulation and Modelling Conference, Toulouse, France : EUROSIS-ETI, s. 305–309. ISBN 90-77381-30-9.

ADAMKO, Norbert. 2013. Agentovo orientovaná simulácia zložitých obslužných systémov. Habilitaēná práca.

AMD. 2013. CodeXL. [online] [cit. 2014-03-8]. Dostupné z: http://developer.amd.com/tools-and- sdks/heterogeneous-computing//

Bainville, E. 2011. OpenCL Sorting. [online]. [cit. 2014-04-9]. Dostupné z: http://www.bealto.com/gpu-sorting.html

BARRACHINA, S., CASTILLO, M., IGUAL, F. D., et al. 2008. Evaluation and tuning of the Level 3 CUBLAS for graphics processors. In: 22nd IEEE International Symposium on Parallel and Distributed Processing, IPDPS 2008, Miami, Florida USA, s 1-8.

BATCHER, K. E. 1968. Sorting networks and their applications In: Spring joint computer conference. ACM. s. 307-314.

BORSHCHEV, A., FILIPPOV, A. 2004. From system dynamics and discrete event to practical agent based modeling: reasons, techniques, tools. In: Proceedings of the 22nd international conference of the system dynamics society. St. Gallen, Switzerland. 23 s. ISBN 978-1-935056-10-2.

BRATMAN, M. 1987. Intention, plans, and practical reason. Harvard University Press. 200 s. ISBN 0674458184, 9780674458185.

BRYANT, R. E., O'HALLARON, D. R. 2010. Computer Systems: A Programmer's Perspective. Addison-Wesley Publishing Company, USA, 1080s. ISBN 0136108040, 978-0130340740.

COURTY, N., MUSSE, S. R. 2005. Simulation of large crowds in emergency situations including gaseous phenomena. In: Computer Graphics International 2005, Stony Brook, New York, USA, s.206-212. ISBN : 0-7803-9330-9

ERRA, U., FROLA, B., SCARANO, V., et al. 2009. An efficient GPU implementation for large scale individual-based simulation of collective behavior. In: International Workshop on High Performance Computational Systems Biology, 2009. HIBI '09, Trento, s. 51-58. ISBN 978-0-7695- 3809-9.

FANG, J., VARBANESCU, A. L., SIPS, H. 2011. A Comprehensive Performance Comparison of CUDA and OpenCL. In: International Conference Parallel Processing (ICPP), 2011, Taipei City, s. 216-225. ISBN 978-1-4577-1336-1.

FARBER, R. 2010. OpenCL™ – Memory Spaces [online] [cit. 2014-3-25]. Dosuptné z: http://www.codeproject.com/Articles/122405/Part-2-OpenCL-Memory-Spaces

FORRESTER, J. W. 1968. Industrial dynamics-after the first decade. In: Management Science 14, s. 398-415

GAJIC, Z. 2014. RTTI in Delphi - Extended Run Time Type Information [online] [cit. 2014-4.8]. Dostupné z: http://delphi.about.com/od/oopindelphi/a/delphi-rtti-extended-run-time-type- information.htm Zoznam použitej literatúry 85

HARADA, T., HOWES, L. 2011. Introduction to GPU Radix Sort. [online] [cit. 2014-3-4]. Dostupné z: http://hgpu.org/?p=5888

HELBING, D., BUZNA, L., JOHANSSON, A., et al. 2005. Self-Organized Pedestrian Crowd Dynamics: Experiments, Simulations, and Design Solutions. In: Transportation Science, s. 1-24.

HELBING, D., MOLNAR, P. 1995. Social force model for pedestrian dynamics. s. 4282-4286. ISSN : 1539-3755.

HELSINGER, A; THOME, M; WRIGHT, T. 2004. Cougaar: a scalable, distributed multi-agent architecture. In: IEEE International Conference on Systems, Man and Cybernetics 2004 Vol. 2. IEEE, s. 1910-1917. ISSN 1062-922X, ISBN 0-7803-8566-7.

HUBERT, N. 2007. Gpu gems 3. Addison-Wesley Professional, 1008 s. ISBN : 0321515269, 978- 0321515261.

CHEN, L. 2012. Parallelism For Prefix Sum. [online] [cit. 2014-4-9]. Dostupné z: http://lanbochen.blogspot.sk/2012/03/parallelism-for-prefix-sum.html

JENNINGS, N R. 2001. An agent-based approach for building complex software systems. In: Communications of the ACM 44. s. 35-41.

KARIMI, K., DICKSON, N. G., HAMZE, F. 2010. A performance comparison of CUDA and OpenCL. In: arXiv preprint arXiv, Ithaca, NY, 12 s.

KAVIKA, A., KLIMA, V., ADAMKO, N. 2005. Agentovo orientovaná simulácia dopravných uzlov. Žilina, EDIS - Vydavateűstvo Žilinskej univerzity, 206 s. ISBN 80-8070-477-5.

KIRK, D. B., HWU, W W. 2010. Programming Massively Parallel Processors. Morgan Kaufmann, 258 s. ISBN 978-0123814722.

KOMATSU, K; SATO, K., ARAI, Y. et al. 2010. Evaluating performance and portability of OpenCL programs. In: The fifth international workshop on automatic performance tuning, 15 s.

KOSTÚR, P. 2007. Mikroskopické modelovanie správania sa mobilných objektov. písomná práca na dizertaēnú skúšku.

LUKE, S., CIOFFI-REVILLA, C., PANAIT, L. 2005. MASON: A Multiagent Simulation Environment. In: Simulation 81, s. 517-527. ISSN 0037-5497, 1741-3133.

LYSENKO, M., D'SOUZA, R. M. 2008. A framework for megascale agent based model simulations on graphics processing units. In: Journal of Artificial Societies & Social Simulation, Zv. 11, ē. 4, 10 s. ISSN : 1460-7425.

MARRONE, P., SMETS, T. L. 2013. Joone: Java Object Oriented Neural Engine. [online] [cit. 2014-4- 19]. Dostupné z: http://www.codertodeveloper.com/

MATHIAS, M. 2010. Možnosti využitia multiagentového modelovania v sociológii. In: Sociálne a politické analýzy, s. 19-38. ISSN : 1337-5555.

MATSUMOTO, M., NISHIMURA, T. 1998. Mersenne Twister: A 623-dimensionally equidistributed uniform pseudorandom number generator. In: ACM Transactions on Modeling and Computer Simulation, Zv. 8, ē. 1, New York, s. 3-30

MATTSON, M. 2011. OpenCL API 1.2 Reference Card. [online] [cit. 2014-4-7]. Dostupné z: http://www.khronos.org/files/opencl-1-2-quick-reference-card.pdf Zoznam použitej literatúry 86

MEFFERT, K., ROTSTAN, N., KNOWLES C., SANGIORGI, U. 2012. Jgap-java genetic algorithms and genetic programming package. [online] [cit. 2014-4-22]. Dostupné z: http://jgap.sf.net

MEIER, J. D., VASIREDDY, S., BABBAR, A., MACKMAN, A. 2004. How to: time managed code using QueryPerformanceCounter and QueryPerformanceFrequency. [online] [cit. 2014-3-12]. Dostupné z: http://msdn.microsoft.com/en-us/library/ff650674.aspx

MINTÁL, M. 2012. Accelerating distance matrix calculations utilizing GPU. In: Journal of Information, Control and Management Systems, Zv. 10, ē. 1, s. 71-79. ISSN 1336-1716.

MINTÁL, M. 2013. Social forces pedestrian simulation utilizing graphics card within simulation tool pedsim. In: IMEA 2013 : the 13th conference of postgraduate students and young scientist in informatics, management, economics and administration, Pardubice, s. 72-78. ISBN 978-80-7395- 696-7.

MEYERS, R. 2012. Computational Complexity: Theory, Techniques, and Applications, Springer New York, 3500 s. ISBN 1461417996, 978-1-4614-1799-6.

MUNSHI, A. 2011. The Opencl Specification. [online] [cit. 2014-04-22]. Dostupné z: https://www.khronos.org/registry/cl/specs/opencl-1.0.29.pdf

NORTH, M. J., MASCAL, C. M. 2009. Foundations of and recent advances in artificial life modeling with Repast 3 and Repast Simphony. In: Artificial life models in software, Springer London, s. 37- 60. ISBN 978-1-84882-284-9, 978-1-84882-285-6

Nvidia. 2010. OpenCL Programming Guide for the CUDA Architecture. [online] [cit. 2014-03-25]. Dostupné z:http://www.classes.cs.uchicago.edu/archive/2011/winter/32102- 1/reading/OpenCL_Programming_Guide.pdf

Nvidia. 2011. OpenCL™ JumpStart Guide v1.1. [online] [cit. 2014-03-25]. Dostupné z:http://corsi.cineca.it/courses/scuolaAvanzata/Ziegler- OpenCL/opencl_cuda40ea/OpenCL_Jumpstart_Guide.pdf

Nvidia. 2012. CUDA Toolkit 5.0 CUFFT Library. [online] [cit. 2014-04-19]. Dostupné z: http://www.math.univ- paris13.fr/~cuvelier/docs/Informatique/CUDA/docs/5.0/CUFFT_Library.pdf

Nvidia. 2013. CUDA C Programming guide. [online] [cit. 2014-03-25]. Dostupné z:http://docs.nvidia.com/cuda/pdf/CUDA_C_Programming_Guide.pdf

Nvidia. 2014a. CUDA GPUs. [online] [cit. 2014-03-25]. Dostupné z: https://developer.nvidia.com/cuda-gpus

Nvidia. 2014a. DirectCompute. [online] [cit. 2014-03-27]. Dostupné z: https://developer.nvidia.com/directcompute

PELECHANO, N., ALLBECK, J. M., BADLER, N. I. 2007. Controlling individual agents in high-density crowd simulation. In: SIGGRAPH Symposium on Computer Animation, San Diego, s. 99-108.

RAILSBACK, S. F., LYTINEN, S. L., JACKSON, S. K. 2006. Agent-based simulation platforms: Review and development recommendations. In: Simulation 82, Zv. 9, s. 609-623. ISSN : 0037-5497, 1741- 3133. Zoznam použitej literatúry 87

RICHMOND, P., ROMANO, D. 2008a. Agent based gpu, a real-time 3d simulation and interactive visualisation framework for massive agent based modelling on the gpu. In: Proceedings International Workshop on Supervisualisation, Kos Island, 9 s.

RICHMOND, P., ROMANO, D. 2008b. A High Performance Framework For Agent Based Pedestrian Dynamics On GPU Hardware. In: Proceedings of EUROSIS ESM 2008, Le Havre, 8 s.

RICHMOND, P., COAKLEY, S., ROMANO, D. 2009a. A high performance agent based modelling framework on graphics card hardware with CUDA. In: Proceedings of The 8th International Conference on Autonomous Agents and Multiagent Systems-Volume 2, s. 1125-1126

RICHMOND, P., COAKLEY, S., ROMANO, D. 2009b. Cellular level agent based modelling on the graphics processing unit. In: High Performance Computational Systems Biology, 2009, Trento, s. 43-50.

RICHMOND, P. 2011a. FLAME GPU Technical Report and User Guide, University of Sheffield. Department of Computer Science Technical Report CS-11-03

RICHMOND, P., ROMANO, D. 2011b. Template driven agent based modelling and simulation with CUDA. In: GPU Computing Gems Emerald Edition, s. 313-324. ISBN 978-0-12-384988-5

ROMANO, D., LOMAX, L., RICHMOND, P. 2009. Narcsim an agent-based illegal drug market simulation. In: Games Innovations Conference, 2009, London, s. 101-108.

SARVER, R. 2013. What is a Platform? [online] [cit. 2014-4-13]. Dostupné z: http://sarver.org/2013/09/26/what-is-a-platform/

SNIR, M., DONGARRA, J., KOWALIK, J. S., et al. 1998. MPI-the Complete Reference: The MPI core, MIT press, ASIN: B00GSW1QSO.

STANDISH, R. K., LEOW, R. 2004. EcoLab: Agent based modeling for C++ programmers. In: Proceedings SwarmFest 2003, 5 s.

STANDISH, R. K. 2008. Going stupid with EcoLab. In: Simulation 84, Zv. 12, s. 611-618.

ST-LAURENT, Sebastien. 2005. The COMPLETE Effect and HLSL Guide. Paradoxal Press, 324 s. ISBN 978-0976613213

STRIPGEN, D., NAGEL, K. 2009. Using common graphics hardware for multi-agent traffic simulation with CUDA. In: Proceedings of the 2Nd International Conference on Simulation Tools and Techniques, ICST (Institute for Computer Sciences, Social-Informatics and Telecommunications Engineering), Rome, Italy, 8 s. ISBN 978-963-9799-45-5

VARGA, M. 2012. Application of the ABAsim architecture in the pedestrian movement modeling tool. In: Journal of Information, Control and Management Systems, Zv. 10, ē. 1, s. 71-79. ISSN 1336-1716

VARGA, M. 2011. Simulaēný nástroj pre simuláciu správania sa chodcov. Fakulta riadenia a informatiky, diplomová práca.

VARGA, M., Mintál, M. 2014. Microscopic pedestrian movement model utilizing parallel computations. In: SAMI 2014 : IEEE 12th international symposium on Applied machine intelligence and informatics, Herűany, Slovakia, s. 221-226. ISBN 978-1-4799-3441-6. 88

WINKLE, W. V. 2009. ATI Stream: Finally, CUDA Has Competition. [online] [cit. 2014-4-19]. Dostupné z: http://www.tomshardware.com/reviews/amd-stream-gpgpu,2335.html Príloha ē.1 Programátorská príruēka k platforme 89

8 Príloha þ.1 Programátorská príruþka k platforme

Táto príloha podrobnejšie popisuje použitie platformy. Zameriava sa na všetky funkcie poskytované platformou, ktoré programátorovi umožnia využiĢ výpoþtový výkon grafických kariet. Postupne sú popísané funkcie používané pri inicializácii platformy, pre použitie na všeobecné výpoþty a pre použitie v simulácii.

8.1 Inicializácia výpoþtových zariadení

Platforma sa dokáže sama inicializovaĢ pre použitie najvýkonnejšieho výpoþtového zariadenia v danom poþítaþi. Táto podkapitola sa venuje prípadu, keć užívateĐ chce sám vybraĢ zariadenie na ktorom sa má poþítaĢ. Ćalej sa venuje nastaveniu globálnych parametrov platformy.

Pre výber konkrétneho zariadenia slúžia nasledujúce príkazy triedy TECInit :

x getAvailableDevices – Funkcia vráti zoznam záznamov TECDeviceIdent, ktoré reprezentujú dostupné výpoþtové zariadenia podporujúce OpenCL. Tento záznam obsahuje názov zariadenia a názov výrobcu zariadenia.

x initDevice – Ako vstupný parameter oþakáva záznam TECDeviceIdent. Funkcia inicializuje platformu, aby používala zariadenie so zadaným názvom.

x initDevices – Funkcia pracuje dvoma spôsobmi. Prvý spôsob je podobný funkcii initDevice, s tým rozdielom že môže byĢ zadaný väþší poþet záznamov. Druhý spôsob je pre používateĐa jednoduchší. Staþí zadaĢ aké zariadenia sa majú inicializovaĢ podĐa tabuĐky 2 a inicializujú sa všetky takéto nájdené zariadenia, priþom používaĢ sa bude najvýkonnejšie z nich.

TabuĐka 2: Typy zariadení podporované platformou

Typ Zariadenia podporujúce OpenCL, ktoré sa majú inicializovaĢ

EC_DEVICE_TYPE_CPU HostiteĐský procesor

EC_DEVICE_TYPE_GPU Grafické karty

EC_DEVICE_TYPE_ACCELERATOR Špeciálne výpoþtové zariadenie (napríklad IBM CELL Blade). Príloha ē.1 Programátorská príruēka k platforme 90

EC_DEVICE_TYPE_CUSTOM Špeciálne výpoþtové zariadenie, ktoré nepodporujú zadávanie vykonávaného kódu.

EC_DEVICE_TYPE_DEFAULT Prednastavené OpenCL zariadenie v danom operaþnom systéme

EC_DEVICE_TYPE_ALL Všetky dostupné podporované zariadenia

EC_DEVICE_TYPE_GPU_FALLBACK Ak sú dostupné grafické karty, tak grafické karty, ak nie tak procesory. Ak ani tie nie sú dostupné, tak akékoĐvek iné podporované zariadenie.

8.1.1 Globálne nastavenia

Platformu možno globálne deaktivovaĢ. Napríklad keć chceme otestovaĢ funkcionalitu dynamického agenta na procesore. Pre správnu funkþnosĢ si agent musí pri prihlasovaní sa na výpoþet pomocou platformy, skontrolovaĢ úspešnosĢ registrácie a v prípade neúspechu, vykonávaĢ výpoþet na procesore. Pre deaktivovanie slúži atribút TECInit.Enable, ktorý treba nastaviĢ na False.

Inicializaþnej triede je možné nastaviĢ aj cesty k súborom. Jedná sa o adresáre, v ktorých sa nachádzajú zdrojové súbory a adresár, do ktorého sa majú ukladaĢ þasy vykonávania kernelov. Atribúty, ktoré sa používajú na nastavenie ciest sú nasledujúce:

x DataFolder – Prieþinok v ktorom sa nachádzajú zdrojové súbory platformy (Súbory ako base.h, euklid.h a euklid.cl). Prednastavená je na „Data\OpenCL“

x TimesFolder – Prieþinok, do ktorého sa ukladajú þasy vykonávania kernelov. Prednastavená je na „Data\EC_Times“

x UserFolders – Zoznam ciest, v ktorých sa majú hĐadaĢ include súbory a súbory so zdrojovými kódmi pre výpoþet.

Pre pridanie cesty do UserFolders existuje aj funkcia addUserFolder. Do nej vstupuje len jeden parameter, ktorý reprezentuje reĢazec cesty, v ktorej sa majú hĐadaĢ užívateĐské súbory. Príloha ē.1 Programátorská príruēka k platforme 91

8.2 Kernel

Pod kernelom sa v platforme rozumie objekt, do ktorého je možné zadaĢ algoritmus, ktorý sa má vykonaĢ na výpoþtovom zariadení, dáta ktoré algoritmus spracúva a spustiĢ výpoþet algoritmu. Tento objekt môžeme získaĢ vytvorením inštancie triedy TECKernel. Pre zadanie algoritmu, ktorý sa má vykonaĢ na výpoþtovom zariadení, slúžia nasledujúce atribúty :

x Code – Do tohto atribútu je možné zadaĢ priamo kód, ktorý sa má vykonávaĢ paralelne na každom vlákne. Kód je v podstate textový reĢazec, obsahujúci telo hlavnej funkcie napísané v jazyku C.

x CodeFile – Názov súboru v ktorom sa nachádza rovnaký kód, ako sa zadáva do atribútu Code. Súbor sa hĐadá v aktuálnom prieþinku a v prieþinkoch zadaných pri inicializácii platformy. Ak je vyplnená properta Code aj CodeFile, používa sa CodeFile. Je výhodnejšie používaĢ túto propertu, nakoĐko platforma v tomto prípade umožĖuje užívateĐovi opraviĢ chyby v kóde bez reštartovania hlavného programu.

x Functions – Slúži na zadávanie pomocných funkcií, ktoré je možné volaĢ z tela hlavnej spúšĢanej funkcie. Rovnako ako do property Code, aj tu sa zadáva textový reĢazec obsahujúci kód funkcii v jazyku C.

x FunctionsFile – Podobne ako CodeFile, slúži na zadanie názvu súboru, v ktorom sa nachádzajú pomocné funkcie. Všetky ćalšie vlastnosti má rovnaké ako CodeFile.

Kód kernelu je možné zadávaĢ v jazyku C99 s niekoĐkými obmedzeniami a rozšíreniami. Medzi hlavné obmedzenia patrí vylúþenie podpory rekurzie, vytvárané polia môžu byĢ iba statické a nie sú dostupné niektoré štandardné knižnice jazyka C. Všetky, aj menšie obmedzenia, je možné nájsĢ v OpenCL špecifikácii (Munshi, 2011).

Medzi rozšírenia patrí práca s viacrozmernými typmi, matematické a geometrické funkcie, synchronizácia vlákien, identifikácia vlákien a ćalšie. Medzi viacrozmerné typy patrí napríklad float2, float3, float4, float8, float16. To platí aj pre ostatné typy ako intX, uintX, charX, doubleX a ćalšie. Prístup k jednotlivým prvkom týchto typov je pomocou atribútov x,y,z,w, ako napríklad position.x. Tiež je možné použiĢ atribúty s0, s1, .. se, sf, pre Príloha ē.1 Programátorská príruēka k platforme 92 prístup k vyšším prvkom. Ćalej je možný prístup k niektorým kombináciám atribútov, ako v nasledujúcom príklade : float2 position2D; float3 position3D = (float3)(1,2,3); position2D = position3D.xy;

Ćalej je možné s takýmito viacrozmernými typmi robiĢ základné operácie, ako odþítanie, sþítanie, násobenie a delenie. Pre základné a aj viacrozmerné typy je možné vykonávaĢ vstavané matematické funkcie, ako sú max, min, sin, cos, tan, log, pow a geometrické, ako cross, dot, length, distance a normalize. Všetky funkcie v prehĐadnej tabuĐke je možné nájsĢ v Opencl Reference Card (Mattson, 2011).

Všetky vlákna vykonávajú rovnaký kód, takže sa musia nieþím rozlišovaĢ. Na to slúži jednoznaþný identifikátor vlákna. Každé vlákno ma globálny identifikátor, ktorý pre jednorozmerné usporiadanie vlákien je dostupný pomocou makra ID. Toto usporiadanie sa používa aj pri výpoþte dynamických agentov poþas simulácie, takže každý agent je identifikovaný týmto ID. Identifikátor zaþína od þísla 0 a stúpa až po poþet vlákien (napr.: agentov v simulácii) - 1. Pre viac rozmerné usporiadanie sa používa ID_G(x), kde x reprezentuje dimenziu, pre ktorú chceme zistiĢ poradie vlákna. Dimenzie sú þíslované od 0 a maximálny poþet dimenzií je 3, þo predstavuje hodnotu 2. Každé vlákno má potom prístupné ešte dva identifikátory a to lokálny ID_L(x) a identifikátor skupiny ID_GROUP(x). Pre detekciu poþtu vlákien a skupín slúžia makrá zaþínajúce þasĢou SIZE_ a na konci sú použité rovnaké prípony, ako pri identifikátoroch vlákien. ýiže sa jedná o SIZE_G, SIZE_L, SIZE_GROUP. Ich popisy ako aj ostatných spomenutých príkazov na identifikovanie vlákien je možné nájsĢ v tabuĐke 3.

TabuĐka 3: Príkazy na identifikovanie vlákna poþas výpoþtu

Príkaz Popis

ID Globálny identifikátor jednorozmerných vlákien

ID_G(x) Globálny identifikátor vlákna v dimenzii x = (0, 1, 2)

ID_L(x) Lokálny identifikátor vlákna v dimenzii x

ID_GROUP(x) Identifikátor skupiny v dimenzii x Príloha ē.1 Programátorská príruēka k platforme 93

ID posledného vlákna, ktoré sa má skutoþne vykonávaĢ pri id_max deaktivácii nadbytoþných vlákien. K jednotlivým dimenziám sa pristupuje cez id_max.x / .y / .z

Poþet všetkých vlákien v dimenzii x. Obsahuje aj vlákna, SIZE_G(x) ktoré majú byĢ deaktivované.

SIZE_L(x) Poþet vlákien v skupine v dimenzii x

SIZE_GROUP(x) Poþet skupín v dimenzii x

DIM Poþet dimenzií

V tabuĐke je aj parameter Id_max, ktorý reprezentuje maximálne ID vlákna, ktoré ešte má vykonávaĢ výpoþet. Ten sa þasto používa pri práci s nadbytoþnými vláknami, ak nepoužijeme parameter paDisableAdditionalThreads pri vytáraní kernelu. V rovnakej situácii je možné použiĢ už vytvorené makrá IF_EXECUTE, IF_EXECUTE_X a IF_EXECUTE_XY. Makro obsahuje podmienku, ktorá sa vykoná len pre platné vlákna. Prvé makro sa dá použiĢ vždy, druhé a tretie sú jeho jednoduchšie verzie, pre použitie v jednorozmernom a dvojrozmernom usporiadaní vlákien.

Pri vytváraní kernelu je možné zmeniĢ základné nastavenia parametrov paDisableAdditionalThreads a useEuklid. Poþet vlákien spúšĢaných na výpoþtovom zariadení musí byĢ násobkom poþtu vlákien v skupine. Väþšinou však potrebujeme spúšĢDĢ premenlivý poþet vlákien, ktorý nie je násobkom poþtu vlákien v skupine. Túto situáciu ošetruje platforma sama a táto funkcionalita sa zapína parametrom paDisableAdditionalThreads. Tým sa spustí väþší poþet vlákien a zvyšné vlákna sa deaktivujú podmienkami na zaþiatku tela hlavnej funkcie. Parameter useEuklid slúži na oznámenie, þi sa má alebo nemá prilinkovaĢ vytvorená knižnica na prácu s geometriou. V tejto knižnici sa nachádzajú funkcie na overenie þi sa útvar nachádza v inom útvare, ako je od neho vzdialený a þi sa pretínajú. Všetky funkcie sú vymenované v súbore euklid.h. Oba tieto parametre sú v základnom nastavení zapnuté.

Dostupné je ešte jedno makro a to SYNCHRONIZE. Slúži na synchronizovanie vlákien, pred pokraþovaním vo vykonávaní. Používa sa najmä keć vlákna pracujú s lokálnou pamäĢou. Vtedy musí byĢ zaruþené, že do lokálnej pamäte uložili dáta všetky vlákna, predtým ako bude možné pokraþovaĢ vo výpoþte. V opaþnom prípade by mohli pristupovaĢ k nekonzistentným dátam. Makro SYNCHRONIZE musia však vykonávaĢ všetky vlákna Príloha ē.1 Programátorská príruēka k platforme 94 v skupine. Preto pri jeho používaní je nutné vypnúĢ paDisableAdditionalThreads a kontrolovaĢ kedy sa majú vykonávaĢ všetky vlákna a kedy len požadované kernelom.

Program je možné upraviĢ pomocou premennej BuildOptions. Pomocou nej je možné zadávaĢ nastavenia pri kompilácii. Pomocou prepínaþa –D name alebo –D name=value je možné zadaĢ hodnoty prekompileru. Tiež je možné zadaĢ prepínaþe urþujúce optimalizácie OpenCL kódu, ktoré sú popísané v OpenCL špecifikácii (Munshi, 2011) pri príkaze clBuildProgram.

8.3 Prenos dát

Zadávanie dát je rozdelené na dve fázy. Najprv je nutné definovaĢ typ parametra a jeho názov. Na to slúžia nasledujúce metódy:

x addParam(paName) – Slúži na zadávanie jednoduchých typov a rekordov.

x addParamArr(paName, paMemoryType) – Slúži na zadávanie polí skladajúcich sa zo základných typov, alebo rekordov.

x addParamArrLocal(paName, paLength) – Špecializovaná verzia predošlého príkazu, v ktorom je možné zadaĢ hneć aj veĐkosĢ lokálnej pamäte.

x addParam(paName, paOtherParam) – Slúži na zadávanie spoloþného parametru viacerých kernelov.

V druhej fáze sa zadávajú vlastné dáta, ktoré sa majú preniesĢ na grafickú kartu, alebo opaþne. Na to sa používajú nasledujúce metódy:

x setParam(paName, paData) – Slúži na vkladanie dát do parametra.

x setParamLength(paName, paLength) – Alokuje miesto pre výstupný parameter, alebo pre veĐkosĢ lokálnej pamäte.

x getParam(paName, paDataOut) – Skopíruje dáta z výpoþtového zariadenia do už alokovanej premennej paDataOut. Príloha ē.1 Programátorská príruēka k platforme 95

x getParamAllocated(paName) – Alokuje pamäĢ v RAM poþítaþa, skopíruje do nej dáta z výpoþtového zariadenia a pointer na túto pamäĢ vráti ako návratovú hodnotu.

Pre zadávanie a þítanie dát poskytuje platforma aj jednoduchší prístup. Povedzme že inštanciu kernelu nazveme VypocetA. Potom môžeme jednoducho zadávaĢ a naþítavaĢ dáta parametru pomocou nasledujúcich príkazov:

VypocetA[paName] := DataIn; DataOut := (typ)VypocetA[paName];

Pri výstupnom parametri sa nedajú dáta naþítaĢ do alokovanej pamäte, pretože kernel takýmto príkazom nemá prístup k tejto premennej. Preto sa vždy alokuje priestor v RAM poþítaþa a doĖho sa naþítajú dáta. Pre naþítanie dát do už alokovanej pamäte je nutné použiĢ príkaz getParam.

8.4 Spustenie výpoþtu

. Výpoþet sa spustí jednou z nasledujúcich procedúr:

Compute(paThreadSize: Cardinal; paBlockSize: Cardinal = 0)

Compute(paThreadSize: array of Cardinal)

Compute(paThreadSize: array of Cardinal; paBlockSize: array of Cardinal)

Procedúra má jeden povinný parameter a ten je poþet vlákien na ktorých sa má spustiĢ výpoþet. Potom má jeden nepovinný parameter a to poþet vlákien v skupine. Priþom oba parameter môžu byĢ aj viacrozmerné.

8.5 Výpoþty v simulácii

Pre výpoþty dynamických agentov poþas simulácie sa používa trieda TECSimKernel. Na jej použitie je nutné vytvoriĢ jej potomka. Pri jeho vytváraní je nutné zadaĢ celoþíselný kód, ktorý reprezentuje daný výpoþet. Tento kód potom použije dynamický agent, pri prihlasovaní sa na výpoþet pomocou neho. V potomkovi je možné implementovaĢ nasledujúce metódy : Príloha ē.1 Programátorská príruēka k platforme 96

x addAgent(paAgent: tActor); virtual; - Slúži na informovanie o prihlásení sa ćalšieho agenta na výpoþet.

x removeAgent(paAgent: tActor); virtual; - Oznamuje o odhlásení alebo zániku dynamického agenta

x BeforeSimulation(); virtual; - Vykoná sa raz pred simuláciou. V nej je možné vykonaĢ jednorazové inicializaþné procedúry, ako napríklad naþítanie prekážok (bodov, stien) pri simulácii chodcov.

x BeforeCompute(); virtual; - Volá sa pred samotným výpoþtom. Slúži len na oddelenie prípadného vkladania nových údajov od samotného výpoþtu.

x Compute(); virtual; - Spustenie výpoþtu. Ak sa neprepíše, zavolá sa výpoþet hlavného kernelu s poþtom vlákien rovnajúcemu sa poþtu agentov.

x AfterCompute(); virtual; - Volá sa po výpoþte. Rovnako slúži len na oddelenie spracovania výstupu výpoþtu od spúšĢania výpoþtu.

x addAgentData(paParamName: String; paAgentID: Cardinal; paData: Pointer) - Pridá dáta agenta do zadaného parametra

x getAgentData(paParamName: String; paAgentID: Cardinal; paDataOut: Pointer) – Vráti dáta agenta z daného parametra

x modifyAgentData(paParamName: String; paAgentID: Cardinal; paData: Pointer) – modifikuje dáta agenta v danom parametri

Z nich je potrebné implementovaĢ minimálne BeforeCompute a AfterCompute, alebo celý výpoþet vložiĢ do Compute. Prípadne reagovaĢ na addAgent a removeAgent. Z každej procedúry je možné pristupovaĢ k hlavnému kernelu, zoznamu agentov a k simulácii. Priþom zo simulácie je možné pristúpiĢ k všetkým potrebným simulaþným dátam. Procedúry addAgentData, getAgentData a modifyAgentData slúžia na zmenu dát prislúchajúcu danému agentovi. Pre zistenie mapovania id agenta na pozíciu v rámci parametra slúži pole agentMap.

Pre správnu funkþnosĢ platformy je nutné vytváraĢ simuláciu z triedy TECSimulation a nie z pôvodnej tSimulation. Rovnako je potrebné dynamického agenta vytváraĢ z triedy Príloha ē.1 Programátorská príruēka k platforme 97

TECAgent a nie z tActor. Tá rozširuje agenta o možnosĢ registrovaĢ sa a odhlasovaĢ z výpoþtu pomocou platformy. Slúžia na to nasledujúce príkazy :

x ECSubscribeAction(paCode: Integer; paDisableAfterCompute: Boolean = False) – Slúži na zaregistrovanie sa na výpoþet pomocou kódu paCode. Parameter paDisableAfterCompute sa používa pri simuláciách, ktoré dopredu nevedia þo bude agent robiĢ v ćalšom kroku, ako napríklad pri použití BDI.

x ECUnsubscribeAction(paCode: Integer) – Slúži na odhlásenie sa z výpoþtu špecifikovaným kódom paCode.

x ECUnsubscribeActions – Odhlási agenta zo všetkých výpoþtov pomocou platformy.

8.6 Použitie platformy

Ako súþasĢ navrhnutej platformy bol vytvorený program pre oboznámenie sa s Ėou. Program zobrazuje podporované výpoþtové zariadenia v poþítaþi a poskytuje niekoĐko testov na porovnanie výpoþtového výkonu a rýchlosĢ prenosu dát. Ćalej obsahuje viaceré ukážky použitia platformy. Jedna ukážka je zobrazená na obrázku 30.

Obrázok 30: Ukážkové príklady použitia platformy Príloha ē.1 Programátorská príruēka k platforme 98

Posledná þasĢ programu je veĐmi zaujímavá, lebo využíva vlastnosĢ platformy, ktorá umožĖuje kompilovaĢ kód pre výpoþtové zariadenia poþas behu programu. Zobrazený je kód, ktorý pohybuje body v rámci obdĎžnikového priestoru, priþom sa odrážajú od hraníc obdĎžnika. Každý bod je rátaný paralelne na výpoþtovom zariadení. UžívateĐ môže zmeniĢ kód programu, alebo poþet bodov a zmena v správaní sa prejaví na správaní sa bodov. Táto ukážka je zobrazená na obrázku 31.

Obrázok 31: Ukážka meniteĐného kódu spúšĢanom na grafických kartách

Tieto ukážky sú veĐmi vhodné pre rýchle oboznámenie sa študentov s vytvorenou platformou. Takto by bolo možné veĐmi rýchlo študentom vysvetliĢ ako jednoducho použiĢ platformu v simuláciách, ako aj v rôznych iných oblastiach na využitie výpoþtového výkonu grafických kariet.