V mnoha pocitacich nabizeji graficke karty vyrazne vyssi vypocetni vykon nez CPU, proc bychom na nich tedy nemohli spocitat ulohu, kterou potrebujeme? Pojdme to zkusit, musime si vsak uvedomit dva hacky - "seriovy" vykon je nizky, graficke karty nam vsak nabizeji desitky az tisice threadu; a vsechny thready v ramci pracovni skupiny museji vykonavat tu samou instrukci. Mame-li nekde v programu vetveni, thready mimo vetev cekaji a tedy do urcite miry plytvame vykon. Zaroven je nutno uvazit, ze data se museji presunout na a z graficke karty, coz take nejakou dobu trva (lze to ale delat paralelne s vypocty na jine casti datasetu). Musime tedy pro ulohu navrhnout vysoce paralelni algoritmus v modelu SIMT (single instruction multiple threads). Pro nektere ulohy, treba zpracovani obrazu ci signalu, je to ukol primocary, jindy (treba trideni) naopak dost tezky. Casto se nam nepodari zrychlit reseni jedne instance ulohy, dokazeme vsak alespon pocitat reseni pro mnoho instanci najednou. Vyuzivame-li grafickou kartu, mame jak "obsluzny" program psany v beznem programovacim jazyce a bezici na CPU, ktery zajistuje spusteni a komunikaci s kartou (a treba i mezitim pocita neco jineho), tak tzv. "kernel", ktery je v mnoha kopiich spusten na graficke karte. Jako parametry pak dostane pointery do pameti na graficke karte, ze kterych bere data a do kterych naopak zapisuje. O prenos dat na grafickou kartu se stara obsluzny program. Pro programovani se v soucasnosti nejcasteji vyuzivaji platformy CUDA a OpenCL. CUDA je platforma specificka pro NVidia karty, OpenCL naopak velmi obecny framework, ve kterem lze teoreticky ten samy kod pouzit pro CPU, GPU, FPGA, Cell, ... V praxi to nebyva nejlepsi reseni, alespon vsak kod pro GPU pobezi na kartach vsech vyrobcu (a pro nektere algoritmy jsou AMD/ATI Radeon karty vyrazne vhodnejsi!). Na druhou stranu tato obecnost usti ve velke mnozstvi "hlucheho" kodu kolem samotneho volani, a pri spusteni obsluzneho programu je nejprve kernel nutno zkompilovat, coz pridava programu nekolikasekundovy overhead. Chcete-li pouzivat OpenCL mimo zazemi malostranske UNIXove laboratore, potrebujete bezici X server s driverem od vyrobce graficke karty a OpenCL platformu - typicky jako soucast SDK, napr. CUDA SDK v pripade NVidia. Zkuste si nejdrive spustit /opt/cuda/sdk/OpenCL/bin/linux/release/oclDeviceQuery a zkontrolujte, ze ve vypisu vidite grafickou kartu. SDK obecne muzete povazovat za inspiraci pro implementaci kernelu pro nektere ulohy (soucasti jsou i zdrojaky), jeho soucasti je i treba nvv profiler. Prohlednete si a rozbehnete kostru OpenCL kitu pro zpracovani bitmapovych obrazku. Ta je navrzena tak, ze v ramci kazde workgroup (skupiny threadu bezici na jednom multiprocesoru) se provadi jeden job, tzn. zpracovani jednoho obrazku. Zpracovavame tedy tolik obrazku, kolik mame multiprocesoru (to je obvykle prave ta zajimava kvantita, kterou se lisi high-end a low-end karty stejne rady). Kernel, ktery se t-krat vykonava na kazdem multiprocesoru, si pak rozdeli obrazek na t-pixelove segmenty a v ramci kazdeho segmentu ma jeden thread na starosti jeden pixel. Odhadnete parametry kitu - pocet jobu a threadu per job - na zaklade parametru Vasi graficke karty vypsanych oclDeviceQuery. Pozor, nezajimaji Vas tolik "maximalni" hodnoty, to jsou pouze absolutni limity driveru/firmware, ktery si to "nejak rozlozi". Optimalni parametry budou nejspis maly nasobek poctu multiprocesoru resp. velikosti warpu. Merenim najdete konkretni nejlepsi hodnoty a srovnejte s teoretickym odhadem. Projdete si TODO komentare, ktere jsou soucasti OpenCL kitu. Dramatickeho zrychleni dosahnete zejmena tradicni konverzi threadu z byte-oriented zpracovani na int-oriented. Zkuste si naimplementovat nejakou jinou transformaci obrazku. Zamyslete se, jak naprogramovat na GPU nektere bezne algoritmy. Co takhle soucet velkeho mnozstvi cisel? Trideni? (Vzpominate na bitonicke trideni? A co radix sort - jak thready zkoordinovat?) Komponenty souvislosti grafu? A zkuste srovnat s vygooglenymi papery. :-)