GPGPU - OpenCL


General Purpose computations on GPU

Uvod

OpenCL kodirane rutine, zvane jezgre, mogu se izvršavati na grafičkim procesorskim jedinicama (GPU) i središnjim procesorskim jedinicama (CPU) nekih od najpoznatijih proizvođača kao što su Intel, AMD, Nvidia i IBM. Tako npr. ukoliko vaše računalo sadrži AMD Fusion procesor i AMD grafičku karticu, moguće je sinkronizirati jezgre kako bi se odvijale paralelno na oba uređaja i razmjenjivale podatke između njih. Drugim riječima OpenCL jezgre je moguće koristiti kako bi smo ubrzali OpengGL i Direct3D obradu. Iako djelomično podsjeća na NVIDIA CUDA, OpenCL strukture podataka i funkcije su jedinstvene, te ga zbog toga nije lagano naučiti što je jedan od njegovih nedostataka. Stoga ćemo vam u ovom radu probati približiti i objasniti rad sa OpenCL-om.


Razvoj aplikacija

Razvoju OpenCL projekta započinje kodiranjem „host“ aplikacije (C, C++), odnosno aplikacije koja se izvodi na korisnikovom računalu i koja otprema jezgre prema spojenim uređajima. Svaka host aplikacija koristi pet osnovnih strukture podataka u OpenCL-u:

  • Device (uređaj): je kolekcija jedinica dostupnih za izračunavanje. U OpenCL-u pod pojmom device zapravo mislimo na grafičke procesorske jedinice (GPU), centralne procesorske jedinice s više jezgri (CPU) i ostalih procesora kao što su DSP i Cell/B.E. procesori. U kodu uređaj reprezentira naredba cl_device_id.

  • Kernel (jezgra): je funkcija koju deklariramo u programu, a izvršava se na OpenCL uređaju (device). Jezgru identificiramo pomoću _kernel naredbe koju primjenjujemo na bilo koju funkciju definiranu u programu. U kodu jezgru reprezentira naredba cl_kernel.

  • Program: OpenCL program se sastoji od seta jezgri. Programi mogu također sadržavati pomoćne funkcije koje se pozivaju pomoću _kernel funkcija i stalnim podacima. U kodu program reprezentira naredba cl_program.

  • Command-queue: se koristi kako bi naredbe za uređaj postavili u red. Neki od primjera naredbi su izvršavanje jezgri, odnosno čitanje i pisanje memorijskih objekata. Drugim riječima command-queue je objekt koji sadrži naredbe koje će se izvršiti na određenom uređaju. Naredbe u redu se nalaze u određenom poretku, ali to ne znači da se moraju izvršavati u tom poretku. U kodu command-queue reprezentira naredba cl_command_queue.

  • Context: je okruženje unutar kojega se izvršavaju jezgre, odnosno domena unutar koje je definirana sinkronizacija i upravljanje memorijom. Context uključuje komplet uređaja, memoriju dostupnu tim uređajima, pripadajuće memorijske postavke i jedan ili više command-queue koji se koriste za raspored izvršavanja jezgri ili operacija na memorijskom objektu. U kodu context reprezentira naredba cl_context.

Ostale strukture i njihov odnos prikazan je UML dijagramom klasna na slici:

OpenCL UML Class Diagram


Primjer

Kako bi smo pobliže objasnili pet osnovnih struktura unutar OpenCL-a iskoristi ćemo primjer igre karata. U toj igri djelitelj dijeli karte iz špila jednom ili više igraču koji se nalaze za stolom. Samo oni igrači koji su za stolom mogu sudjelovati u igri, no to ne znači da i moraju. Svaki igrač nakon što zaprimi svoje karte igra na način za koji smatra da je najbolje. Također igrači međusobno ne komuniciraju i ne vide karte drugih igrača, ali mogu tražiti od djelitelja dodatnu kartu ili promjenu uloga. Djelitelj je taj koji mora odgovarat tim zahtjevima i preuzima kontrolu nakon što igra završi. Slika prikazuje jednu takvu igra.

Igra karata

U ovom primjeri djelitelja možemo zamisliti kao host aplikaciju, dok ostali dijelovi igre odgovaraju ranije navedenim strukturama podataka u OpenCL koje moraju biti kreirane i konfigurirane u host aplikaciji:
  • Device – Igrač: Kako igrač prima karte od djelitelja, tako i uređaj prima jezgre od host aplikacije.

  • Kernel – Karte: Host aplikacija raspodjeljuje jezgre uređajima na poprilično sličan način na koji djelitelj dijeli karte igračima.

  • Program – Špil karta: Način na koji djelitelj odabire karte iz deka možemo shvatiti kao način na koji host odabire jezgre iz programa. .

  • Command queue – Igračeve karte (karte u ruci): Svaki igrač dobiva karte koje nakon što zaprimi predstavljaju njegovu „ruku“, baš kao što svaki uređaj zaprimi jezgru kroz command queue.

  • Context – Stol: Baš kao što stol za karte omogućuje igračima da transferiraju karte jedan drugome, context omogućuje uređajima da preuzmu jezgre i transferiraju podatke..

  • Sljedeća slika prikazuje njihov odnos.

    OpenCL strutkture podataka