A következő címkéjű bejegyzések mutatása: OpenCL. Összes bejegyzés megjelenítése
A következő címkéjű bejegyzések mutatása: OpenCL. Összes bejegyzés megjelenítése

2011. november 21., hétfő

Khronos: OpenCL 1.2 specifikációk

[iPon] A Khronos Group szoftvermérnökei 18 hónappal az OpenCL 1.1-es változatának hivatalos bejelentése után végre elkészültek az OpenCL 1.2-es verziójával. A nyílt, mindenféle díjaktól mentes szabvány tökéletesen működik a különböző platformok között, így széleskörű támogatást nyújt ahhoz, hogy a mai modern processzorokat – CPU-kat, GPU-kat – hatékonyan vethessék be a fejlesztők párhuzamos számítási feladatokra.
A piacvezető vállalatokkal történő együttműködésnek köszönhetően az új verzió tökéletesen kompatibilis az OpenCL 1.1-es változatával, de hozzá képest még jobb párhuzamos számítási teljesítmény elérését teszi lehetővé, valamint sok-sok új funkciót is kínál, amelyek új kapukat nyitnak meg a fejlesztők előtt.

2011. július 4., hétfő

OpenCL fejlesztőkészletet adott ki az Intel

[prog.hu] Az Intel a napokban elérhetővé tett egy új fejlesztőkészletet ami lehetővé teszi az Open Compute Language (OpenCL) nyelven írt feldolgozórutinok közvetlenül a cég processzorain történő futtatását. Az OpenCL-t eredetileg a grafikus chipek és más, a gépbe szerelt segédprocesszorok számítási kapacitása kiaknázának lehetővé tételére alkották meg, de az Intel fejlesztőkészletével közvetlenül a processzorra lehet testálni a műveletek elvégzésének feladatát.

2011. január 29., szombat

Új nevet kapott az ATI Stream SDK

Az OpenCL API-ra építő ATI Stream SDK 2009 végén látott napvilágot, és az elmúlt év nyarán kapott egy nagyobb frissítést is, melynek eredménye az OpenCL 1.1-es platform támogatása lett. A Stream SDK 2.3 az év elején jelent meg, de nem került ki hivatalosan az AMD weboldalára. Ennek most már az okát is tudjuk, ugyanis a fejlesztői csomag mostantól AMD APP SDK néven lesz elérhető.
A fejlesztőkörnyezet OpenCL-t érintő optimalizációkat tartalmaz, ám a legnagyobb újítás az UVD motor elérhetősége az OpenCL felületen keresztül. Ez a funkció egyelőre csak Windows 7 mellett él, de később más operációs rendszerekre is ki lehet terjeszteni. Az APP SDK természetesen támogatja az AMD új hardvereit, beleértve a Fusion APU-kat. Szintén érdekesség, hogy az AVIVO HD jelzést is eldobta cég. Korábban már beszámoltunk róla, hogy az ATI-tól megmaradt technológia már nem tökéletes az UVD motor képességeinek kihasználására, így a vállalat a driver újraírásán dolgozik. Az új meghajtó Media Codec Package néven fut, de a Catalyst 11.1-hez tervezett verzió, még számos ponton az AVIVO HD-ből megmaradt rutinokat kamatoztatja. A teljes áttérésre az év első felében érdemes számítani.
Az APP SDK 2.3 szintén támogatja a vállalat partnereinek már elérhető OpenPhysics SDK-t, mely egyelőre béta fázisban van, de később publikusan is elérhető lesz. A fejlesztői csomag a Pixelux DMM2 és a Bullett fizikai motorokhoz kínál támogatást. Az utóbbi felületet használja a 3DMark 11 is, mivel a rendszer képes némely fizikai számítás gyorsítására a DirectCompute API-n keresztül. A jövőt érintő fejlesztésekkel kapcsolatban megkerestük a Bullett vezető programozóját. Erwin Coumans elmondása szerint a motor új generációs verziója a márciusban megrendezendő, San Francisco-i GDC-n mutatkozik majd be, és a teljes futószalag gyorsítható a grafikus processzoron keresztül, az OpenCL vagy a DirectCompute felületet használva.
A AMD APP SDK 2.3 az alábbi oldalról tölthető le. A rendszer a Windows 7, Vista és XP operációs rendszerek mellett az openSUSE 11.3, a Red Hat Enterprise Linux 5.4/5.5, illetve az Ubuntu 9.10/10.04 verziójú Linux disztribúciókat támogatja. Ezenkívül kezeli a Microsoft Visual Studio (MSVS) 2008/2010 Professional Edition, a GCC (GNU Compiler Collection) 4.4-es, valamint az ICC (Intel C Compiler) 11-es fordítómodulokat.

2010. augusztus 24., kedd

Frissült az OpenCL platform

Az OpenCL platformot még 2008 végén mutatta be a Khronos Group, ám most elérkezett egy apróbb frissítés ideje. Az nyílt forrású 1.1-s felület a funkcionalitás területén javított, így jobb programozhatóság és nagyobb teljesítmény várható tőle.
A platform új adattípusokat vezet be, melyek közül a legfontosabbak a háromkomponenses vektorok, illetve az új képformátumok. Az 1.1-es felület jobb együttműködést garantál az OpenGL API-val, továbbá lehetőség lesz operációkat végezni egy puffer kijelölt terültén.


Az ARM és az AMD üdvözölte a bejelentést. Sőt az utóbbi vállalat elmondta, hogy a Fusion APU-k, illetve az ATI Streammel kompatibilis hardverek támogatni fogják a megújult felületet. Az NVIDIA még nem szólalt meg az OpenCL 1.1-gyel kapcsolatban, de nyilvánvaló, hogy dolgoznak az implementáláson, így a GeForce GTX 400 család is kezelni fogja a platformot.

2010. augusztus 22., vasárnap

Cloo kedvcsináló

A most következő írás egy kezdő lecke azok számára, akik valamilyen okból kifolyólag menedzselt környezetből szeretnék használni az OpenCL API-t. Az írás sghc_toma OpenCL kedvcsináló című cikkén alapszik, ezért az azzal való egyezés nem a véletlen műve. Ezer köszönet érte sghc_toma-nak. Kezdjünk is hozzá.

Az OpenCL számolás nagy vonalakban

Az OpenCL eszköz (compute device) az a hardver, amin a párhuzamos feldolgozás történik. Ezekben a hardverekben egy, vagy több számolási egység (compute unit) van, melyek egy, vagy több feldolgozó egységet (processing element) tartalmaznak – tulajdonképpen ezek hajtják végre az utasításokat. Például egy videokártya minden stream processzora, és egy CPU minden magja is egy feldolgozó egység, az nVidia videokártyák egy multiprocesszora pedig egy számolási egység.


A videokártyán futó programrészlet neve kernel kód vagy függvény. Az egyes feldolgozó egységek a kernel kód egy példányát futtatják, mindegyikük más-más adatokon. A kerneleket OpenCL-C nyelven (ISO C99 alapokon) lehet írni, és minden eszközre külön le kell fordítani őket. Az OpenCL eszközre írt kódokat természetesen nem kell egy darab függvénybe sűríteni, a kernel hívhat más függvényeket, illetve lehet több kernel is. A kernelek, a kiegészítő függvények, illetve a kernel által használt konstansok együtt egy programot alkotnak.
A kernelek egy úgynevezett kontextusban (context), környezetben futnak, mely magába foglalja a használható eszközöket, az általuk elérhető memória objektumokat, illetve a kernelek futtatásának ütemezését végző parancslistákat (command queue). A programot, amely létrehozza a kontextusokat, előjegyzi a kernelek futtatását, host programnak nevezzük, az őt futtató hardvert pedig a host eszköznek. A videokártya szempontjából a host (gazda) a CPU. A host kódból lehet memóriát lefoglalni a kártyán, feltölteni adattal, és a kernel kód futása után a host kódból lehet elérni a számolás eredményét. A kernel kódból ez a memória hozzáférhető. A kernel kódot úgy kell elkészíteni, hogy az a feladatnak csak egy részét végzi el; hogy melyik részét, azt beépített paraméterek adják meg. A feladat felosztását mi határozzuk meg, azaz kijelöljük a GPU számára a paraméter tartományokat, amelyekben végre kell hajtani a kernelt, és a GPU saját erőforrásait figyelembe véve maga beosztja, hogy melyik rész mikor és melyik multiprocesszoron fut le.
A fentieket egy egyszerű példán át könnyedén megérthetjük. Tegyük fel, hogy egy mátrixszorzást szeretnénk elvégezni az OpenCL-el. Ehhez a kernel kódban általánosan, sor és oszlop paraméterre leírjuk azt, hogy a szorzatmátrix adott sorában és oszlopában, hogy áll elő az eredmény. A kernel számára kijelöljük, hogy a sor paraméter egytől a sorok számáig, az oszlop paraméter egytől az oszlopok számáig kell, hogy terjedjen. A GPU tehát kap egy feladatot: sor × oszlop-szor végrehajtani a kernelt. A feladat végrehajtását optimálisan a GPU határozza meg magának.

A platform modell

Az OpenCL működése leírható négy modell segítségével:
  1. a platform modell
  2. a futtatási modell
  3. a memória modell
  4. a programozási modell
Az elsővel tulajdonképpen már megismerkedtünk: a host/device kapcsolatról van szó.

A futtatási modell

Mint már említettük, az OpenCL eszköz egy feldolgozó egysége a kernel egy példányát futtatja. Egy kernel-példányt munkaegységnek (work-item) nevezünk. Mikor elindítunk egy számolást, meg kell adnunk, hogy összesen hány munkaegységre lesz szükségünk. A munkaegységek összessége az index tér (index space), mely lehet 1, 2, vagy 3 dimenziós. A munkaegységek munkacsoportokba (work-group) szervezhetők. Ez azért fontos, mert az egy munkacsoportba tartozó munkaegységek között lehetséges szinkronizáció, és mindegyikük hozzáfér a csoport lokális memóriájához (erről később bővebben), míg ez a különböző csoportba tartozó egységekről ez nem mondható el.


Minden munkaegységnek van egy úgynevezett globális azonosítója (global ID), mely egyértelműen meghatározza annak helyét az index térben. Hasonlóan, minden munkacsoportnak is van egy azonosítója (work-group ID). A munkaegységeknek ezen felül van egy helyi azonosítója (local ID), mely a munkacsoporton belüli helyét határozza meg. A fentiekből következik, hogy a munkaegység pozíciója az index térben meghatározható a csoport azonosító és a helyi azonosító kombinációjával. Az index tér dimenzióinak maximális száma, az egyes dimenziókban a maximális méret, illetve egy munkacsoport maximális mérete eszközönként eltérő lehet, ezt figyelembe kell venni programozás közben! Az OpenCL API természetesen lehetőséget nyújt ezen adatok lekérdezésére.

A memória modell

A munkaegységek/kernelek által hozzáférhető memória négy típusra van osztva. A globális memóriához (global memory) az index tér minden egyes munkaegysége hozzáfér, azt írni és olvasni is tudják. Eszköztől függően a globális memória írása/olvasása lehet cache-elt. A konstans memória (constant memory) a globális memória egy olyan része, melynek tartalma nem változik kernelfuttatás közben, azt csak a host módosíthatja.


Minden munkacsoport rendelkezik egy lokális memória (local memory) területtel, melyet minden munkaegység a csoportban képes írni/olvasni. A privát memória (private memory) minden egyes munkaegységnek a sajátja, ő írni/olvasni tudja, de más munkaegység nem fér hozzá. A CUDA-t ismerőknek: érdemes odafigyelni az elnevezésekre, mert bár a két környezet felépítése hasonló, a terminológia nagyon nem. Például a CUDA-féle lokális memória az, amit itt privátnak neveznek, és ami itt lokális memória, az a CUDA-ban megosztott (shared memory).

A programozási modell

OpenCL-t használva kétféle párhuzamosítást érhetünk el: data, illetve task parallel módon programozhatunk. Az első az OpenCL fő profilja, ez jelenti azt, hogy sok kernel példány csinálja ugyanazt az index tér más-más elemein. Ha több, más feladatot végző kernelünk van, betehetjük őket egy parancslistába, és az OpenCL megtesz minden tőle telhetőt, hogy ezek optimálisan használják ki a hardvert. Ez utóbbi a task parallel módszer, hiszen egymástól független folyamatok futnak párhuzamosan.

OpenCL a gyakorlatban

Most hogy átrágtuk magunkat a száraz tényeken, következzen egy konkrét feladat megvalósítása OpenCL-ben. Először is szükségünk van egy wrapperre amivel elérhetjük az OpenCL API függvényeit .NET környezetből. Erre jelenleg az egyik legígéretesebb projekt a Cloo és az OpenCL.NET. Jelen bejegyzésben a Cloo-val fogunk megismerkedni mivel ez objektum orientált szemlélettel készült. Töltsük le a Cloo legfrissebb változatát majd indítsuk el a Visual Studio-t. Hozzunk létre egy konzolos alkalmazást majd a referenciákhoz adjuk hozzá a Cloo.dll szerelvényt. Ezután már csak a szükséges namespace-ket kell elhelyeznünk:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Runtime.InteropServices;
using System.Diagnostics;
using Cloo;

Első programunk rendkívül egyszerű lesz, összeadunk két vektort és az eredményt eltároljuk egy harmadikban. Persze ezt a műveletet elvégezzük, mondjuk úgy 10 milliószor. Ha nem párhuzamos megvalósításban gondolkodnánk, akkor ezt valószínűleg egy ciklussal oldanánk meg, valahogy így.

for (int index = 0; index < n; index++) c[index]= a[index] + b[index];

A számoláshoz a vektorok i-edik elemeire van szükség - tehát az egyes számolások teljesen függetlenek egymástól, így a probléma szinte felkínálja magát párhuzamosításra. A terv az, hogy írunk egy kernelt, ami elvégzi a fenti műveletet egy vektor egy elemére, majd egy (n elemű vektorokkal számolva) n elemből álló index térre rászabadítjuk ezt a kernelt. Egyszerűen hangzik, mert az is.

A kernel

Első lépés a kernel kód vagy függvény elkészítése:

private static string code = @" kernel void VectorAdd(
global read_only float* a,

global read_only float* b,

global write_only float* c )

{
int index = get_global_id(0);
c[index] = a[index] + b[index]; }";

Ennyi az egész. A kernel kulcsszó - meglepő módon - azt jelzi, hogy az adott függvény egy kernel függvény. Egy kernel argumentumai a private névtérben kell legyenek, és alapértelmezetten oda is kerülnek. Ha egy argumentum mutató, megmondhatjuk, hogy a global, local és constant névterek melyikébe mutasson. A get_global_id(0) függvény az adott munkaegység globális azonosítójának első koordinátáját adja vissza. Erre azért van szükség, hogy tudjuk, hogy egy adott kernelpéldány a vektor hányadik elemének számolásáért felel. Mivel vektorokon dolgozunk, az index terünk egydimenziós, így valóban csak az első koordinátára van szükségünk. Ezután a kernel már csak elvégzi a megfelelő műveleteket a vektorok megfelelő elemein, és az eredményt visszaírja a harmadik vektor megfelelő elemébe.

Platformok

A számoláshoz szükségünk van egy OpenCL eszközre. Ahhoz, hogy létrehozhassunk egy eszközt, szükségünk lesz egy platform ID-re. Az elérhető platformok listáját a következőképpen szerezhetjük meg:

int platformNo = ComputePlatform.Platforms.Count;
ComputePlatform platform = ComputePlatform.Platforms[0];

Ez a kódrészlet az első ComputePlatform.Platforms.Count hívással kideríti az elérhető OpenCL platformok számát. A mellékelt példaprogramban az első elérhető platformot használjuk.

Eszközök

Ha megvan a platformazonosítónk (platform), lekérdezhetjük az elérhető eszközök listáját:

ReadOnlyCollection<ComputeDevice> devices = platform.Devices;

Ez nagyon hasonlít az előző kódrészlethez, a különbség annyi, hogy itt eszközökről szerzünk listát.

Környezet

Most, hogy megvan az eszköz, létre kell hozni egy környezetet a számoláshoz. Ehhez első lépésben készítünk egy környezet tulajdonság listát a platform felhasználásával:

ComputeContextPropertyList properties =
new ComputeContextPropertyList(platform);

Majd a tényleges környezet létrehozása a ComputeContext osztály segítségével történik:

ComputeContext context =
new
ComputeContext(devices, properties, null, IntPtr.Zero);

Az első paraméterben az elérhető eszközöket adjuk át, persze minden adott eszközhöz külön is kreálható környezet. Ilyenkor a ComputeDeviceTypes felsorolás tagjaiból választhatunk: Default, CPU, GPU, Accelerator, All. A következő a környezet tulajdonságait tartalmazó lista. Majd ezután, ha szükségesnek látjuk létrehozhatunk call-back függvényt amivel a hibakódokról értesülhetünk, de mi most ezt nem alkalmazzuk, ezért null.

Parancslista

Most már van környezetünk, amihez már csak hozzá kell adni egy parancslistát, ahová majd a végrehajtandó kerneleket pakoljuk.

ComputeCommandQueue commands =
new ComputeCommandQueue(context, context.Devices[0], ComputeCommandQueueFlags.None);

Ez a hívás a context.Devices[0] azonosítójú eszközhöz hoz létre egy parancslistát. Több parancslistát is létrehozhatnánk, de a kitűzött feladat elég egyszerű, egy lista is elég. Több lista esetén, amennyiben az egyes parancsok használnak közös objektumokat, figyelni kell a szinkronizálásra; erről bővebben olvashattok a OpenCL specifikációban. Még egy dolog a parancslistákkal kapcsolatban: több eszköz esetén mindegyiknek saját listára van szüksége!
Foglaljuk akkor most össze, mink van eddig. Kiválasztottunk egy OpenCL platformot, és erről a platformról egy eszközt, amin számolni fogunk. Ehhez az eszközhöz készítettünk egy környezetet, melyhez létrehoztunk egy parancslistát és írtunk egy kernel függvényt is. Most már csak pár dolgot kell végrehajtanunk: kellenek memória objektumok, amikben átadjuk a kernelnek a két vektort, illetve visszakapjuk az eredményt. A kernelfuttatáshoz szükségünk lesz egy kernel objektumra, amit csak egy, az adott eszközhöz felépített program objektumból nyerhetünk ki. Folytassuk tehát a munkát, készítsük el a program objektumot.

Program objektum

Programot készíthetünk forráskódból, illetve binárisból is. A gyorsabb inicializálás érdekében célszerű az első futtatáskor lefordítani a forrást, majd a kapott binárist (több OpenCL eszköz esetén az eltérő gépi kód miatt binárisokat) elraktározni, s következő alkalommal abból készíteni a program objektumot. Lássuk, hogy forrásból hogyan készítünk programot (a binárisból készítésre most nem térünk ki):

ComputeProgram program =
new ComputeProgram(context, new string[] { code });

Most már van egy programunk, de ez még csak a forráskódot tartalmazza, tehát le kell fordítanunk:

program.Build(null, null, null, IntPtr.Zero);

A fordítás állapotáról a program.GetBuildStatus(devices[0]) tulajdonságon keresztül kaphatunk információt. Ha minden rendben volt a ComputeProgramBuildStatus.Success enumot kapjuk vissza.

Kernel objektum

Miután sikeresen felépítettük a programot, kinyerhetjük belőle a kernel objektumot:

ComputeKernel kernel = program.CreateKernel("VectorAdd");

Mint látható, a kernel objektum gyártás elég egyszerű művelet, csupán egy lefordított programra, és a kernel függvény nevére van szükségünk hozzá.

Memória objektumok

Nos, van már kernelünk, amit tudnánk futtatni, csak egy probléma van: nincsenek adataink, amin dolgozhatunk. Ezért most létre kell hozni memória objektumokat, s feltöltjük őket a vektorainkkal. OpenCL-ben az eszköz memóriáját kétféle objektumon keresztül érhetjük el: puffer és kép (image) objektumok. A pufferekbe bármilyen adatot tehetünk, míg a kép objektumok kettő, vagy háromdimenziós képek tárolására alkalmasak. A kép objektumokkal most nem foglalkozom részletesebben, kitűzött célunk eléréséhez nincs is szükség rájuk, a vektorokat pufferekben tároljuk:

ComputeBuffer<float> a = new ComputeBuffer<float>(context, ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.CopyHostPointer, arrA);
ComputeBuffer<float> b = new ComputeBuffer<float>(context, ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.CopyHostPointer, arrB);
ComputeBuffer<float> c = new ComputeBuffer<float>(context, ComputeMemoryFlags.WriteOnly, arrC.Length);

Ez a három függvényhívás létrehozza az adott kontextusban az a, b és c vektoroknak megfelelő puffereket. Az a és b vektort csak olvasni fogjuk, így a ComputeMemoryFlags.ReadOnly flaggel hozzuk létre, míg a c vektorhoz szükség van a ComputeMemoryFlags.WriteOnly flagre, hiszen abba írjuk majd a végeredményt. Lehetőség van a puffer készítésekor megadni egy host pointert (negyedik paraméter), és az adatot, amire mutat, rögtön felmásolni a pufferbe. Ehhez szükséges megadni a ComputeMemoryFlags.CopyHostPointer flaget. Puffert létrehozhatunk a host memóriájában is (ComputeMemoryFlags.AllocateHostPointer), illetve felhasználhatunk már lefoglalt host memóriaterületet is (UseHostPointer).

Kernel futtatás

OK, már majdnem kész vagyunk, már csak futtatnunk kell a kernelt. Egyszerűen hangzik, de azért ez nem csak annyiból áll, hogy meghívunk egy függvényt, aztán fut. Be kell állítani a kernel-argumentumokat, meg kell határozni a munkacsoportok és munkaegységek számát, és elő kell jegyezni a kernelt a parancslistában.

kernel.SetMemoryArgument(0, a);
kernel.SetMemoryArgument(1, b);
kernel.SetMemoryArgument(2, c);

Ezek a függvény hívások állítják be a kernel argumentumokat. Az egyes argumentumokat a kernel függvény fejlécében elfoglalt helyük alapján azonosítjuk, ez a szám a SetMemoryArgument függvény első paramétere.

ICollection<ComputeEvent> events =
new Collection<ComputeEvent>();
commands.Execute(kernel, null, new long[] { count }, null, events);

Most már csak meg kell hívnunk a commands parancslista Execute() metódusát megfelelően felparaméterezve. Az első paraméter a kernel objektum, a második a GlobalWorkOffset amit általában null. A GlobalWorkSize vagyis a munkaegységek száma megegyezik a vektorok méretével. Azt, hogy ez hogyan van felosztva munkacsoportokra (LocalWorkSize), most teljesen mindegy (az egyes vektor elemek teljesen függetlenek egymástól, a munkaegységeknek nincs szüksége közös memóriára), ezért az OpenCL-re bízzuk.
Minden olyan függvény, ami a parancslistához ad elemeket, kér egy ComputeEvent típusú lista pointert (utolsó paraméter). Az így visszaadott ComputeEvent-tel lehet lekérdezni a parancs aktuális állapotát (pl. végzett-e?), illetve más parancsok várólistájához lehet adni a parancsot. A várólistában szereplő összes parancsnak le kell futnia, mielőtt az adott parancs lefuthatna. Nos, ha minden jól ment, ezen hívás után már fut is a kernelünk.

Eredmény olvasása

A számolás eredménye persze az eszköz memóriájában van, tehát ki kell olvasnunk onnan. Ehhez persze biztosnak kell lennünk benne, hogy a számolás befejeződött. Ezt a commands.Finish() függvénnyel biztosíthatjuk, ami csak akkor tér vissza, ha a paraméterként megadott parancslista minden parancsa befejeződött. Ezután még figyelembe kell vennünk azt is, hogy a host memóriájában menedzselt az az objektum amibe bele kívánjuk másolni a számítás eredményét és így meg kell védeni a GC-től.
A menedzselt objektumok nem-menedzselt kódból történő elérésének egyik módja, hogy használjuk a GCHandle struktúrát. A struktúra legfontosabb tulajdonsága, hogy akkor sem engedi a menedzselt objektumot kisöpörni a memóriából, ha már csak egy nem-menedzselt objektum hivatkozik rá (ellenkező esetben a memóriaterület felszabadul). Azt is megakadályozza, hogy az adott cím egy más szegmensre tolódjon a memórián belül. Az azonban lényeges, hogy a nem-menedzselt kódnak rendelkeznie kell a megfelelő jogosultságokkal ehhez, melyet a SecurityPermission osztály segítségével adhatunk meg.

GCHandle arrCHandle = GCHandle.Alloc(arrC, GCHandleType.Pinned);

Az eredmények host memóriába olvasása:

commands.Read(c, false, 0, count,
arrCHandle.AddrOfPinnedObject(), events);
commands.Finish();

Amikor ez lefut, a c memória objektum tartalma a host memóriában lévő arrC vektorba másolódik. Az arrCHandle AddrOfPinnedObject() metódusa kinyeri a szükséges címet. A pufferekbe írásnál kimaradt, most megemlítem: ha a második paraméter true, az olvasás/írás befejeztéig nem tért vissza a függvény, ha false, nem várja meg a műveletek befejeztét. Végül:

arrCHandle.Free();

Ezuán már a számítás eredménye elérhető az arrC tömbben és azt tehetünk vele amit csak akarunk. Végeztünk a számolással, de még nem fejeződött be a dolgunk. Illik eltakarítani magunk után, szabadítsuk fel az OpenCL erőforrásokat:

a.Dispose();
b.Dispose();
c.Dispose();
kernel.Dispose();
program.Dispose();
context.Dispose();
commands.Dispose();

Végszó

Elsőre kicsit bonyolultnak tűnhet a dolog, de higgyük el, hogy megéri a kínlódás mivel így új távlatok nyílhatnak meg előttünk. De még mielőtt elbúcsúznánk érdemes egy kis teljesítmény tesztet végrehajtani a klasszikus .NET for ciklus és az OpenCL/Cloo (GeForce 8800 GTS) páros között. Az eredmények a lenti ábrán láthatóak:

.NET for vs. Cloo

Hát igen, nem valami meggyőző. Nagy elemszámnál már a Cloo átveszi a vezetést, de nem sokkal. Mi lehet ennek az oka?! Először is a .NET nem is olyan lassú, mint hinnénk, másodszor pedig az OpenCL API-t nem tisztán értük el, hanem a Cloo wrapperen keresztül, így egy kis overhead mindig is lesz. Ez főleg akkor megy a teljesítmény rovására, ha a kernel program olyan apró és egyszerű, mint a mi VectorAdd példánk. Jóval nagyobb és összetettebb feladatok esetén már jóval nagyobb különbség is elérhető a CPU és a GPU között. Remélem érthető volt ez kis példa és talán meghozza a kedvet egy kis videokártya-programozáshoz. A teljes forrás letölthető: innen

2010. augusztus 17., kedd

A GPU-k miatt kihalnak a jelszavak?

Az egyszerűbb jelszavakat ma már egy otthoni PC-n is könnyű visszafejteni brute force módszerrel. Jelszavak helyett jelmondatok kellenek, mondják amerikai kutatók. A modern grafikus processzorok (GPU) kiemelkedő számítási kapacitása ma már nemcsak látványos 3D-s animációk megjelenítésére használható, hanem bármilyen nagy számításigényű feladat elvégzésére is. Amerikai kutatók szerint az, hogy a korábban csak szuperszámítógépekre jellemző teljesítmény az otthonokban is elérhetővé válik, kihúzhatja a talajt a jelszavas hitelesítés alól, mely ma messze a legelterjedtebb az informatikában. Az, hogy a GPU-k masszívan párhuzamos feldolgozási képessége jól hasznosítható a jelszótörésben, nem újdonság. Egy orosz vállalkozás már három évvel ezelőtt levédetett egy olyan módszert, amellyel az összes lehetséges kombinációt végigpróbáló ún. brute force támadásokhoz szükséges idő látványosan lerövidíthető. A Georgiai Műszaki Egyetem kutatói most azt mondják: a GPU-k számítási teljesítménye olyan ütemben növekszik, hogy csak hosszabb és bonyolultabb jelszavakkal érezhetjük ideig-óráig biztonságban magunkat. „Határozottan állíthatjuk, hogy ma egy hét karakterből álló jelszó reménytelenül kevés, de ahogy nő évről évre a GPU-k kapacitása, úgy nő a veszély is” – mondta Richard Boyd, a jelszavak esélyeit vizsgáló kutatás egyik vezetője.



Ma egy grafikus processzor számítási teljesítménye elérheti a két teraflopsot (billió művelet másodpercenként) – ezzel a mutatóval tíz évvel ezelőtt a világ legerősebb szuperszámítógépei közé is be lehetett volna kerülni. Bár korábban ezt a kapacitást kizárólag a háromdimenziós grafikai megjelenítés során hasznosították, néhány éve a GPU-gyártók felismerték a tudományos és műszaki számításokban rejlő potenciált, és kifejezetten ösztönzik a grafikus gyorsítóchipek ilyen célú felhasználását. Az e téren úttörő NVIDIA 2007 februárjában tette CUDA néven elérhetővé azt a standard C fejlesztői környezetet – számos könyvtárral, fordítóval és dedikált meghajtóprogramokkal –, amely ehhez megteremtette az alapot.


A jó jelszó hosszú és bonyolult

Ez a számítási kapacitás jelszótörésre is igen hatékonyan használható. A kutatók felhívják a figyelmet arra, hogy minél hosszabb jelszavat választunk, annál jobban védjük magunkat a brute force támadásokkal szemben, de fontos az is, hogy vegyesen használjunk számjegyeket, nagybetűket és különleges karaktereket. Az emberek többsége az egyszerűség kedvéért kizárólag kisbetűket választ a jelszavához, a jelszótörők is ezeket próbálják ki először.
„A billentyűzeten 95 karakter található, minden egyes karakter, amit hozzáadunk a jelszavunkhoz, exponenciálisan, 95-szörösére növeli a védettségünket” – mondja Boyd. A team szerint ha egy jelszó 12 karakternél rövidebb, ma már sebezhetőnek tekinthető. A kutatók ezért azt javasolják, hogy jelszavak helyett inkább „jelmondatokat” válasszunk, lehetőleg olyanokat, amelyekben számjegyek és szimbólumok is találhatók. A mondatokat a hosszuk miatt jóval időigényesebb visszafejteni, miközben könnyen megjegyezhetők.

Persze legyen bármilyen hosszú és bonyolult is egy jelszó, más trükkökkel (például jelszólopó programmal stb.) megszerezhető. Ezért hosszú távon a csak jelszavas hitelesítést egy olyanra kell lecserélni, amely úgy biztosít erősebb védelmet, hogy nem teszi bonyolultabbá a felhasználók életét – mondják a kutatók.

2010. május 19., szerda

Szuperszámítógéppé változtathatja a PC-ket a grafikus kártya?

Kaliforniai kutatók egy csoportja szerint gyakorlatilag szuperszámítógéppé változtatható át egy közönséges asztali PC is, ha a megfelelő szoftver segítségével sikerül kihasználni a belé szerelt grafikus kártya mag számítási kapacitását. Az Észak-Karolinai Állami Egyetem kutatói állításukat arra a tényre alapozzák, amely szerint bár egy átlagos CPU mindössze 20-60 gigaflops számítás teljesítménnyel rendelkezik, egy mai tipikus grafikus kártyára szerelt lapka (GPU) azonban ennek ennek 20-50-szeresével: mintegy 1 terafloppal.
Az amerikai kutatók egy olyan szoftvert fejlesztettek ki, amely képes egy eredetileg a számítógép központi processzorára írodott program átfordítására úgy, hogy az a számításaihoz a CPU helyett a grafikus magot, a GPU-t használja fel. Így, bár végül a program gyakorlatilag ugyanazt az eredményt szolgáltatja, de azt jóval gyorsabban képes visszaadni, annak köszönhetően, hogy a jóval nagyobb számítási kapacitást biztosító feldolgozó egységet használja fel a végrehajtásra.
Kifejlesztői szerint speciális fordítószoftverükkel készült programok akár 128-szor gyorsabban is futhatnak, mint natív - CPU-n futó - változataik, de 30 százalékkal lekörözik még a magasan optimalizált, szintén a GPU képességeit például az Nvidia CUDA csatolója révén kihasználni próbáló szoftvereket is. Ugyanakkor szerintük ez egyelőre csak a jéghegy csúcsa, és ha sikerül a korábbiaknál effektívebb konverziós technikát alkalmazniuk, akkor ennél jóval nagyobb mértékű sebességnövekedés is elérhető lesz.
A nagy problémát jelenleg az képezi, hogy a GPU-kat kifejezetten csak képadatok feldolgozására hegyezték ki, így viszonylag nehéz más jellegű, egymástól független adatsorok feldolgozásához felhasználni őket.

2010. március 23., kedd

OpenCL valamint GT300/RV870

Most, hogy próbálom magam elhelyezni az OpenCL világában egyre több információt és nagyon profi módon összeállított anyagot lelek fel magyar nyelven is és ez igen nagy örömömre szolgál. Most egy levelet sikerült elcsípni a Google segítségével. Remélem nem haragszik meg a szerzője, hogy belinkelem. Szóval olvassuk csak mert nagyon érdekes...

Üdvözlet mindenkinek,
István mondta, hogy szóljak pár szót az én gumicicámról, név szerint az OpenCL-ről. Aki esetleg már ismeretes a fogalommal annak a bevezető nem fog sok újat mondani, de az új kártyákról érdemes elolvasni az ismertetőket.
Az OpenCL egy új GPGPU eljárás/programnyelv/keret ami az Apple szárnyai alatt látta meg a napvilágot. A kezdeményezés lényege hogy egy egységes keretet adjon a GPGPU fogalomnak, ami könnyen kezelhető és mindenek felett platform független (a Mac OSX alatt léteznek a legrégebb óta működő compilerek). A kezdeményezés olyannyira ígéretesnek bizonyult, hogy felsorakozott mögé mindenki, akit az IT világban érdemes lehet megemlíteni (a lista irdatlan hosszú, minden nagy névvel rajta). A fejlesztés illetve szabványok jóváhagyója a Khronos Group (www.khronos.org). Az új keretrendszer roppant rugalmas és kényelmes is, nagyon jól struktúrált programok írhatók benne ahol jól elkülöníthetők és szinkronizálhatók a CPU-n és a GPUn végzett számítások. A keret egy-két említésre méltó tulajdonsága: a device-okon (lett légyen az GPU vagy CPU vagy akármi) lefutó programkód C szabvány nyelven írandó/írható, OpenGL hívások engedélyezettek device-ról (ergo kirajzoláshoz nem kell CPU-ra visszatérni sem buffert cserélni a CPU-val), a device-on futó kód (ezentúl kernel) runtime fordul (jól megírt program CPU-n lekérdezi a device képességeit (shader szám, elérhető memória, stb.), ehhez mérten paraméterezi fel a kernelt, majd ezekre optimalizálva fordítja le a kódot az OpenCL compiler. Így a jól megírt program minden kártyán optimálisan futhat, de más előnyei is vannak (bár kellemetlenségeket is okoz, ez tény)). Jól láthatóan a vörösök és a zöldek is nagy erőbedobással dolgoznak a fejlesztői környezeteiken és elsősorban az OpenCL támogatás az ami bővül minden egyes újabb verziónál. Szerintem mindenképp érdemes legalább egy pillantást vetni az új keretre, és megfontolandónak tartom a nagyobb lélegzetvételű új projektek ebben a nyelvben történő elkezdését. A cross-platform jellege, a gyártófüggetlensége, az OpenGL-el nem titkolt házasítása, a jól strukturáltsága, a C nyelv ismertsége és az óriási támogatása miatt szerintem futótűzként fog elterjedni a használatban. Aki jól tud CUDA-ban programozni, annak nem lesz nagy was ist das elsajátítania, mert a nyelv szintaktikája és megközelítése javarészt a CUDA-ra hasonlít. A nyelv felépítésében az NVIDIA volt a domináns.

Hol tart az OpenCL most?

NVIDIA nem kis lépéselőnyben van ATi-val szemben. NVIDIA-nak már van Mac-Linux-Windows alá CPU-ra és GPU-ra fordító compilere olyan segédprogramokkal, amik a kernelek debuggolását és optimalizálását is elősegítik (egy apró kényelmetlensége, hogy a kernelt nehezebb debuggolni, mert runtime fordul, ezért a fordítási hibák nem a program többi része mellett dobnak fordulási hibát. Ha az ember használ valami bonyolultabb fejlesztői környezetet, ami teszem azt támogat változókövetést, stb. akkor ezeket a funkciókat nem lehet használni a kernel debuggolására, mert a host processzortól független a program futása. Ezekhez a problémákhoz nyújt segítséget a VisualProfiler nevezetű okosság zöld oldalon). ATi nemrég fogadtatta el a teljes CPU támogatást natív 64-bites műveletekkel és gőzerővel dolgozik a GPU-s compileren. Amint ezt a csúfos lemaradását behozza az ATi, a zöldek elkezdhetnek rettegni.

Milyenek lesznek az új generációs GPU-k?

Megpróbálom az eddigi jól-rosszul palástolt vörös partiságomat leplezve objektíven tálalni a tényeket. Az NVIDIA GT300 kódú lapkája egy nem titkoltan GPGPU-ra épített chip. A zöldek ha félhivatalosan is, de bedobták a törülközőt az asztali szegmensbe szánt kártyákkal, elmondásuk szerint nem látnak már benne akkora piacot, és elsősorban az ipari felhasználás és az általános számításokra szeretnének koncentrálni. Az új kártyájuk DX11 alatt nyújtotta teljesítményt nem tartják olyan fontosnak. (Ez valószínűleg azért van, mert a 4xxx Radeon széria nagyon csúnyán elkente a GT2xx kártyák száját, és az ATi aggresszív árpolitikája ellehetetlenítette az NVIDIA-t a piacon. A korábbi 25%os piaci részesedésről 50% fölé emelkedett az ATi egyetlen év alatt. A vörösök megoldásai rendre felülmúlták ár/teljesítmény arányban a zöldekét. Az NVIDIA ilyen módon szeretne új piacon egyeduralkodóvá válni, ami teljesen érthető és logikus lépés.) Hardverben viszont nem kis lemaradással küszködik az NVIDIA, november végére saccolják az első GT300as kártya startját, ekkorra a vörösök már a Radeon 5870X2 kártyával fognak jelentkezni, aminek már a nevét is csak félve merem kimondani. A vörös tábor két hete dobta piacra az első RV870-es lapkával ellátott kártyájukat, a Radeon 5870-et és a kistestvérét, az 5850-et. Ezek nem titkoltan DX11re lettek bedrótozva, és ezzel érzésem szerint végleg megpecsételődött az NVIDIA sorsa a játékpiacon. A napvilágot látott tesztek azt bizonyítják, hogy az 5870 ereje DX11 támogatás nélkül is 85-90%-át hozza a korábbi kétmagos megoldásoknak (4870X2 és a GTX295), ami figyelemreméltó teljesítmény. Az NVIDIA új megoldása is várhatóan hasonló eredményt fog nyújtani, bár ez a DX11 hardveres elhanyagolása miatt (A DX11 legnagyobb újítását, a tesszalátor egységet nem implementálják, hanem a CUDA magok fogják emulálni) nem lesz ennyire látványos a játék teszteken. Az új üdvöskékről most is elmondható az a különbség, ami mindig is megvolt: a zöld kártyák memória, memória sávszélesség és textúrázó egység gazdagok, és ezt a jó tulajdonságukat a megszokottnál jobban erősítették, míg a vörösök annyira Shader processzor gazdagok, amennyire azt nem szégyellték (és textúrázó egységből is rápakoltak azért annyit, amennyi a korábbi generációs GTX295-ön van, csak hogy ne érje szó a ház elejét). Alább áljék pár hasznos link az érdeklődőknek, akik a kártyák újításairól szeretnének informálódni (rövidített verzió a linkek után):
Röviden a Fermi nevű GT300-as kártya egy nagyon memóriagazdag, gyorsítótáraiban bővebb, memóriasávszélben nagyobb megoldás lesz, mint a Cypress névre keresztelt 5870, és legnagyobb előnye ebben rejlik. A CUDA magokhoz rendelt cache 64kByte, szemben a Cypress 32kByte-jával. A CUDA magok csoportjaihoz rendelt L2 cache is figyelemreméltó méretű (768kByte), de ezt nehéz összemérni a Global Data Share-rel a Shaderek között, mert az egy 64kByte-os gyorsító tár a VRAMhoz. Az RV870 előnyei pedig a brutális számítási kapacitás (1600 shader proceszor egy magon. Egy db shader képességei a prohardveres oldalról olvashatók le) és talán a legfontosabb, hogy natív 64 bites felépítésűek a shaderek (A GT300 egy 32 bites architektúra, így következő generációváltásig biztos nem lesz fejlődés ilyen téren), ergo nem lassulnak a számítások fele tempóra 64 bites műveletek mellett. Az RV870-et a maga szerény 2,7 TFLOPS teljesítményével ha szembeállítjuk a beígért GT300 650 GFLOPS (64 bit) illetve 1,3 TFLOPS (32bit) teljesítményével, akkor azt hiszem elfogultság nélkül állíthatom hogy bármily szomorú is, annak ellenére hogy az NVIDIA kifejezetten az ipari és kutatási szegmenst akarja megcélozni a kártyáival, az ATi megoldások nagyon erősen meg fogják szorongatni őket (ha csuklóból nem verik el), különösen ha számításba vesszük azt is, hogy az ATi elsősorban az otthoni felhasználáshoz mérten fogja beárazni a kártyáit, nem pedig az ipari szegmenshez mérten. Objektivitásomat megtartva addig, hogy lenyeljek egy nagyon frappáns cikket (csak hogy miért vagyok vörös párti), véleményem szerint november-december tájára biztosra veszem hogy elkészül az ATi-s OpenCL compiler GPU-ra, és az akkor kijövő Radeon 5870X2, a maga előrelátható 5 TFLOPS-os 64 bites számítási kapacitásával félelmetes lesz. Én hobbi és napi szinten otthon vagyok a témában, onnan ez a tájékozottság. Ezután az ismertető után engem kár kérdezni, hogy milyengépet lenne érdemes venni. (Noha konkrét ötleteim azért vannak)
Nagy Máté Ferenc
2009. Okt. 8., Cs, 11:59:45 CEST

Szép új jövő? A GPGPU ma és holnap 2.

Bár mindenki sokat várt a GPGPU-tól, a gyártók nem siették el a támogatását. Az NVIDIA-nál sokáig csak a kiváltságosak érhették el a bétás CUDA GPGPU és PhysX csomagot. Ráadásul üzletpolitikai szempontból csak a G92-es maggal felvértezett GeForce 9-es szériánál használhattuk ki a GPU erejét – később persze minden GeForce 8-as kártyán engedélyezték ezeket a funkciókat. Ugyanígy az AMD-nél sem siettek a nagydobra verni a kártya ezen képességeit, a Folding@Home kliens is csak nemrég került bele a Catalyst telepítőcsomagba.
A döcögős indulás mégsem befolyásolja a GPGPU jövőjét, mert több kutatóintézet és nagy számítási kapacitással operáló vállalat a következő generációs szuperszámítógépeket „szuper gyors” számításokra képes grafikus vezérlőkkel teletömve képzelik el. Igaz, a grafikus vezérlőkön felül vannak még vetélytársak, ilyen például Playstation 3-ból ismert Cell processzor (amelyet már régóta alkalmaznak ilyen célokra, továbbfejlesztett változata pedig a kétszeres pontosságú feladatoknál is meglehetősen fürge), de az Intelnél is erősen készülődnek, hogy új fejlesztésükkel törjenek a babérokra. Összességében véve már nyugodt lélekkel kijelenthetjük, hogy a GPGPU-k jövője biztosított.


GPU PhysX vs CPU PhysX

A tudományos célokat szolgáló felhasználás minden bizonnyal még erősebb lapkák kifejlesztésére sarkallja a gyártókat, amelyek ugyan nemcsak a játékosok igényeit fogják szem előtt tartani, ám nagyobb számítási kapacitásuk révén a játékosok társadalma is profitálhat majd a folyamatból. Ismerve a grafikuskártya-felhozatalt, nem állíthatjuk, hogy túl sok gyártó van a piacon. Az AMD és NVIDIA mellett még a szebb napokat is látott S3 jelentkezett GPGPU-alkalmazással, ám a kis teljesítménye miatt nem várhatunk tőle csodát, illetve még a támogatottsága is kérdéses. Talán az Intel mozgolódása jelzi, hogy mégis milyen nagy piacot jelent ez a projekt a gyártók számára. Bár nagy a titokzatoskodás a téma körül, az Intel évek óta gőzerővel fejleszti a Larrabee kódnév alatt futó egységet, amelyet elsősorban grafikus magnak szánnak, ám egy egészen új elgondolásnak hála kiválóan alkalmas párhuzamosított számolásokra. A Larrabee érdekessége, hogy egységesíti a grafikus kártyáknál jelenleg is alkalmazott masszív párhuzamosított architektúrát az x86-os utasításkészletű processzorok tudásával (konkrétan egyszerűsített x86-os magokat felhasználva). Ez ily módon nagy átvitelt (pontosabban jobb sávszélesség-kihasználtságot) és remek programozhatóságot biztosít. A Larrabee felépítésének előnye, hogy nem csupán a DirectX és OpenGL grafikus API-kat támogatja, hanem a szoftveres úton megvalósított renderelésben is kiváló teljesítményt nyújt majd, amennyiben elkészül.

Fizika padlógázzal

Bizonyára sokan emlékeznek az Ageia PhysX kártyájára, amelynek külön bővítőkártyaként nem jósoltunk nagy jövőt, ám maga a technológia életképesnek bizonyult. Rontott a PhysX helyzetén, hogy már megjelenés után arról szóltak a hírek, hogy a GPU-k számítási kapacitása elegendő lesz a fizika számításához. Ez valóban igaznak bizonyult, amit az a tény is megerősített, hogy a kártya képességeit bemutatandó Cell Factor program megjelenítési sebessége a gyorsítókártya nélkül sem lassult be jelentősen. Azóta jelentős változások történtek, és a PhysX licenc az NVIDIA kezébe, a számítás pedig a CUDA-nak köszönhetően a GPU feladatsorába került, amit egy-két játékprogram valóban kihasznál. Ilyen például az Unreal Tournament 3, amelyhez léteznek nagyon látványos, direkt a fizikai gyorsítási képességre kihegyezett pályák – ezek már nem igazán futtathatók élvezhető sebességgel PhysX-gyorsítás – tehát CUDA-t támogató NVIDIA kártya – nélkül. Ugyanígy (számszerűsítve) látható a fizikai gyorsítás hatása a 3DMark Vantage CPU-tesztjében és még néhány programban, de egyelőre még nem számolhatunk be széles körű elterjedtségről.

Viszlát OpenGL, viszlát DirectX?

Ha már a jövő latolgatásánál és a szoftveres renderelésnél tartunk, érdemes megemlíteni, hogy az egész grafikus megjelenítéssel foglalkozó iparág látszólag elmozdult jól megszokott helyéről és a fix feladatok helyett az általános célú feladatfeldolgozást helyezi előtérbe. E tény részben a klasszikus értelemben vett – tehát csak az előre meghatározott feladatkör elvégzésére alkalmas – grafikus kártya halálát jelenti, amit már évekkel ezelőtt megjósoltak a játékfejlesztők. A kérdés csupán az, hogy mikor fog ez bekövetkezni, viszont jól látható, hogy a fejlesztések gyorsvonat sebességével robognak ebbe az irányba. Ennek következtében valószínűleg vissza fogunk térni a Direct3D és OpenGL API-k előtti időre, amikor a processzor még nyers erővel, szoftveres úton renderelt, csak most a CPU helyett a grafikus kártya fogja ugyanezen számolásokat elvégezni. A programozóknak és fejlesztőknek ez egyaránt azt jelenti, hogy valós programnyelvben kell (például az OpenCL) kódolni, míg ennek következtében a felhasználók számára teljesen mindegy lesz, melyik gyártó kártyáján játszunk. Egyetlen paraméter lesz ugyanis a döntő: a számítási kapacitás.
Ugyanakkor nem szabad azt hinnünk, hogy a programozásban a „szabad kéz” teljes mértékben megoldást jelent minden problémára. Nincs arra garancia, hogy az adott problémára a fejlesztő a legoptimálisabb megoldást találja-e meg, ezáltal esetenként nehezebb dolga is lehet, mint egy előre definiált és adott lehetőségekkel megáldott DirectX esetében. Arra sem számíthatunk, hogy az eddig uralkodó és jól bejáratott alkalmazásprogramozási felületek (DirectX, OpenGL) eltűnnek, de mindenképpen tartaniuk kell a lépést a változással – talán itt jön el ismét az az idő, amikor nem a DirectX-hez igazodik a grafikus kártyák tudása, hanem fordítva, mint a DirectX 9 előtti időkben.
írta Papp Gábor, 2009. február 09.

2010. március 22., hétfő

A GPU és CPU közös jövője 1.

A PC-k hőskorában még örülhettünk, ha grafikus kártyánk már elboldogult az SVGA-felbontással és az egyszerűbb játékokkal, hiszen akkoriban szó sem volt HD-ről vagy fotorealisztikus háromdimenziós megjelenítésről. Arról pedig álmodni sem mertünk, hogy a VGA-kártya egyszer a CPU babérjaira tör – márpedig most éppen ez történik.
Már a 90-es évek elején is sokat lehetett hallani a 3D-s gyorsítás fogalmáról. Ez a fogalom akkoriban az otthoni felhasználók körében kimerült az S3 Virge vagy az ATI Rage 3D szerény képességeiben, de az igazi lavinát a 3dfx Voodoo kiegészítő kártyája indította el. Ezt követően egymás után jelentek meg a gyorsabb változatok, majd az SLI-technológia. Időközben azonban az ATI és az NVIDIA is felnőttek ahhoz a feladathoz, hogy igazi 3D-s gyorsítással ellátott kártyát készítsenek – igaz, nem a 3dfx által megvalósított GLide API-vonalon, hanem az OpenGL- és a Direct3D-szabványnak megfelelően.
A Voodoo megjelenése óta eltelt 12 év alatt a grafikus magoknak – röviden GPU-knak – egyre komolyabb feladatokat kell végrehajtaniuk, ezáltal egyre több számítás terhet vesznek le a központi processzor válláról, már ami a megjelenítést illeti. Felépítés szempontjából a grafikus magok rendkívül nagyot léptek előre, komplexitás és gyártástechnológia tekintetében felvehetik a versenyt a CPU-kkal, míg bizonyos feladatoknál számítási kapacitásban már meg is előzték azokat.
Persze a grafikus megjelenítésért felelős lapka a felépítéséből adódóan sokáig nem helyettesíthette a processzort, azonban az új évezred elején debütáló NVIDIA GeForce 3 és az nFinite FX Engine névre hallgató programozható Vertex shader egység, valamint a shader modell első generációjának megjelenése magával hozta a programozható GPU-k korát. Ezt követően a GeForce FX és – az ATI oldaláról – a Radeon 9700 harmadik generációs GPU-k hoztak további fejlődést a shader modell 2.0 és a Vertex mellett már a programozható pixel shader egység megjelenésével.

GPGPU

Természetesen a GPGPU-nak rövidített általános célú (General Purpose) grafikus processzoroknál (GPU) sokkal többről van szó, mint a GeForce 3, az ATI Radeon 9700 vagy az NVIDIA GeForce FX esetében, ám az tagadhatatlan, hogy ebben a tekintetben ezek a lapkák szolgálnak technológiai alappillérként.
Az igazi áttörést a DirectX 10 által megkövetelt egyesített shader architektúra (Unified Shading Architecture) hozta meg, amely leváltotta a külön feladatokra specializálódott pixel és Vertex shader processzorokat. Az NVIDIA G80 és AMD R600 kódnevű lapkák voltak az első grafikus magok, amelyek az említett felépítésnek megfelelően készültek, akárcsak a jelenleg forgalomban lévő G92, GT200 és RV770 magok. Ezek a több mint száz univerzális feldolgozó egységet felvonultató magok olyan speciális párhuzamos adatfeldolgozási feladatokra is rávehetők, amiket korábban csak a CPU tudott kiszámolni. Ez azonban nem jelenti azt, hogy a CPU kiváltható a GPU-val, sőt, ez a közeli jövőben sem várható azon egyszerű oknál fogva, hogy ez az erősen párhuzamosított, grafikus megjelenítésre kihegyezett architektúra – legújabb generációs shader modell esetében – legfeljebb egyszeres pontosságú, 32-bites lebegőpontos számítások esetén használható hatékonyan.
Ezzel szemben egy 64 bites (kétszeres pontosságú) lebegőpontos számításnál már erősen csökken a teljesítmény és a CPU sokkal erősebbnek bizonyul, tehát még várni kell az igazi áttöréssel. Ez elsőre nem látszik a GPU-k adatlapján, így például az RV770 esetében sem. Ott hiába ámuldozott a szakma az 1,2 TFLOPS számítási teljesítményen – ez ugyanis csak az egyszeres pontosságú számításokra vonatkozik. A kétszeres pontosságra vonatkozó adatot az apró betűs részben olvashatjuk, ami csak 240 GFLOPS. Ráadásul a GPU végrehajtó egységei nagyon érzékenyek a kódra, ezért – és a lehető legjobb kihasználtság végett – az erre alkalmas környezetben (mint például az NVIDIA Cuda vagy az AMD CTM fejlesztőkörnyezete) a kódot külön kell optimalizálni és megfelelő nyelvre fordítani.

A jelen: AMD Stream és NVIDIA CUDA

A két nagy gyártó nem meglepő módon saját utakon kezdett bele a GPGPU-képességek kiaknázásába, ennek hála saját SDK-kat (rendszerfejlesztői készlet) fejlesztettek a programozók számára, de olybá tűnik, a CUDA nagyobb népszerűségre tett szert. A PhysX-képességek mellett olyan nagyszerű alkalmazásokat említhetünk meg, mint például a Badaboom konvertálóprogramot, a PowerDirectort vagy a PhotoShop CS4-et (Quadro kártyák esetében Premiere CS4 is) és még 155 más egyéb szoftvert – bár ezek nagy részének otthon nem vesszük semmilyen hasznát. Ezzel szemben az AMD nem adta közre pontosan, hogy mely programok támogatják a Stream-technológiát, de vélhetően jóval kevesebb, ami annak is betudható, hogy a projekt hivatalosan csak december óta létezik.


Real Time 3D Fluid and Particle Simulation and Rendering

Mivel az egész GPGPU-téma újdonságnak számít, a támogatottság jelenlegi helyzetéről nehéz többet elmondani. Jó jel, hogy a programozók gyorsan ráharaptak a témára, így további szoftverek támogatása várható még ebben az esztendőben.

OpenCL mindenekelőtt

Mint láthatjuk, a CUDA és Stream – illetve a CTM – legnagyobb hátránya, hogy nem kínálnak egyforma programozási nyelvet a fejlesztők számára, annak ellenére, hogy mindketten a C nyelvet használják. Ez körülbelül olyan helyzetet idéz elő, mint a 3dfx idejében a Glide és a Direct3D esete volt. Elképzelhető tehát, hogy lesznek támogatottsággal kapcsolatos viták. Ennek elkerülése végett a programozók kezébe olyan egységes, platformfüggetlen nyelvet és környezetet kell adni, amely kompatibilis mindegyik gyártó fejlesztésével és a magas mellett natív alacsony szintű hozzáférést enged közvetlenül a hardverhez és a memóriához, így megkerülve az OpenGL és DirectX API-kat. Ilyen például a teljesen ingyenes és nyílt OpenCL-szabvány, amelynek jogait az Apple birtokolja.


Az első OpenCL demó ami a GPU-t használja

A Khronos csoport neve alatt az Apple azonban számos nagyvállalattal (például Intel, NVIDIA, ATI, IBM, 3DLabs, EA) együttműködve közös erővel dolgozik a szabvány tökéletesítésén, mivel a leíró nyelv végleges változata rekordgyorsasággal (már tavaly decemberben) elkészült. Az OpenCL sokak szerint forradalmasítja a számítástechnikát és a lapkákban rejlő erőforrás-kihasználást – és ez alatt nemcsak a grafikus magokat értjük, hanem az akár mobiltelefonokba való processzorokat is. Úgy tűnik, a gyártók is hisznek az újdonság erejében, hiszen az AMD már a kezdetekkor teljes mellszélességgel az OpenCL támogatása mellett döntött, majd az NVIDIA is rábólintott a projektre, ám a CUDA sem merül feledésbe.
Bizonyára sokakban felmerül a kérdés, hogy ez mind szép és jó, de mit lép a Microsoft? Nos, a redmondi óriás sem ül a babérjain és továbbra sem kíván szakítani a hosszú évek alatt kemény munkával felépített DirectX birodalommal, így a 11-es változat része lesz a Compute Shader. Ez gyakorlatilag ilyen formában egy API-hoz kötött GPGPU-támogatás, szemben az OpenCL-lel, amely – mint említettük – független. Nehéz megmondani, melyik szabvány lesz a győztes, hiszen hiába érkezik későn a DirectX 11, a VGA-gyártók természetesen támogatni fogják, ezzel szemben az OpenCL egy jóval kötetlenebb eszközt ad a programozók kezébe, ami nem csak Windows alatt használható, hasonlóan az OpenGL-hez. Továbbá arról sem szabad megfeledkezni, hogy az egész GPGPU-s mizéria többről szól, mint a játékok látványvilága, tehát ez is az OpenCL malmára hajtja a vizet. Azonban még korai találgatásokba bocsátkozni...
írta Papp Gábor, 2009. február 09.