| Grafický procesor se stal běžnou a již samozřejmou součástí většiny
        počítačů. Současný počítač tak představuje heterogenní výpočetní
        prostředí, ze kterého velké většina programového vybavení bohužel
        stále používá jen jeho, v určitém směru, méně výkonnou část. Právě
        algoritmy strojového vidění jsou velmi náročné na výpočetní výkon a
        často jsou také velmi dobře paralelizovatelné. Proto plné využití
        potenciálu počítačů se může pro aplikace strojového vidění a vizuální
        inspekce stát značnou konkurenční výhodou. GPU mohou provádět mnoho operací s daty, které jsou tradičně
        prováděny pomocí CPU, a některé z těchto operací mohou velmi významně
        urychlit. Zatímco CPU mají jen několik výpočetních jader, GPU jich
        mají několik set. Grafické procesory byly původně navrženy pouze pro
        akceleraci počítačové grafiky a pro práci s grafickými daty. I když
        dnešní systému mohou pracovat i s obecnými daty, funkčnost grafických
        procesorů stále zůstává hodně omezená a zdaleka ne všechny typy úloh
        je vhodné řešit prostřednictvím GPU. Na úvod si připomeňme základní koncepce architektury GPU v
        grafických adaptérech počítačů a nakonec se zaměříme na využití
        programovatelných GPU s systému strojového vidění VisionLab. Vnitřní architektury GPU hlavních výrobců NVIDIA, AMD a Intel se
        navzájem hodně liší. Jedná se o velmi složité obvody. Jen jako
        ilustraci složitosti a výkonnosti moderních GPU si uveďme několik
        parametrů grafického procesoru GeForce GTX 680: 
          
           
            
              | Počet tranzistorů | 3.5 miliardy |  
              | Počet výpočetních jader | 1536 |  
              | Hodinové frekvence GPU | 1006 MHz |  
              | Výkon přístupu k texturám | 128.8 miliard pixelů za sekundu |  
              | Šířka sběrnice grafické paměti | 384 bitů |  
              | Datová propustnost | 192.2 GB za sekundu |  
              | Výpočetní výkon (single presision) | 3.79 TFLOPS | Při pohledu na tyto působivé parametry je zřejmé, jak velká škoda
        by byla nechat tento potenciál ležet ladem. Tento procesor má již uniformní architekturu shaderů a je dalším
        důkazem, že vývoj v této oblasti stále více směřuje k vyšší
        použitelnosti GPU pro obecné výpočty než jen pro akceleraci grafiky.
        Tento trend začal u firmy NVIDIA uvedením přelomového procesoru G80 v
        roce 2006. V uniformní architektuře mohou všechny procesory v GPU
        podle aktuálních potřeb vystupovat v roli vertexových, fragmentových
        nebo geometrických shaderů. Cesta k dnešní uniformní architektuře nebyla krátká. S využitím
        grafických akcelerátorů pro akceleraci výpočtů se dokonce
        experimentovalo již době, kdy tyto čipy měly pouze pevně danou
        funkčnost a nebylo je možno programovat. Využívaly se hardwarové
        interpolátory a rasterizery, filtry textur, míchání vektorů, operace
        s accumulator a stencil bufferem atd. Tyto postupy
        vyžadovaly od programátorů hlubokou znalost principů fungování
        grafického řetězce a značnou kreativitu. Dalším krokem ve vývoji byly
        pak programovatelné fragmentové procesory s již standardizovanými
        pseudo assemblery, které se staly součástí grafických ovladačů.
        Hardware i instrukční soubory jednotlivých GPU byly a jsou doposud
        odlišné a právě překladače v grafických ovladačích umožnily
        přenositelnost kódů shaderů (zde máme trochu zmatení pojmů, označení
        shader se používalo jak pro programovatelné fragmentové procesory, tak
        pro programy těchto procesorů). Tento způsob programování GPU byl
        stále pro většinu programátorů zcela nestravitelný a používala jej jen
        hrstka nadšenců. Důležitým momentem byl příchod vysokoúrovňových jazyků pro
        programování shaderů. Všichni tři zástupci ( Cg ( NVIDIA pro DirectX i
        OpenGL), HLSL „High-Level Shading Language“( Microsoft DirectX) a GLSL
        „OpenGL Shading Language“(dodnes standardní jazyk shaderů pro OpenGL)
        ) mají podobné schopnosti a jejich zápis se velmi podobá jazyku C.
        Tyto jazyky jsou již velmi dobře použitelné pro programování obecných
        výpočtů, to znamená, že jsou jim přístupny téměř veškeré vlastnosti
        současných GPU, nicméně stále ještě z programátorů nesnímají
        nutnost znát vlastnosti grafického řetězce a přistupovat k GPU
        prostřednictvím grafického API. Původní základní princip GPU, totiž
        vytváření obrázků je i v jazycích vysoké úrovně stále
        viditelný. Dnes existuje řada softwarových prostředí a nástrojů, které
        programátora izolují od této původní podstaty GPU a předkládají mu
        obecně přijatelnější programovací model. Tyto nástroje, k nimž
        patří např. Sh (Rapid Mind), BrookGPU, Accelerator (Microsoft),
        PeakStream (Google), Ashli (nadstavba nad Cg, HLSL a GLSL), CTM ( AMD
        ), CUDA (NVIDIA), ArBB (Intel), OpenCL atd. Tyto nástroje více či méně
        obcházejí grafické ovladače, umožňují pracovat s pamětí v podobě
        proměnných a polí C jazyka a někdy dokonce
        i ukazatelů (CUDA) a především zajišťují upload vstupních
        dat do textur v grafické paměti, download výsledků z frame
        bufferu grafické paměti a just-in-time kompilaci a optimalizaci
        kódu shaderů. Vstupní i výstupní data mají obvykle podobu polí
        vektorů. Objevují se systémy, kde rozhraním na GPU je virtuální stroj,
        který zajistí přenositelnost kódu. V této oblasti je stále situace
        velice nepřehledná, probíhá zde rychlý vývoj a chybí silné
        a hlavně dlouhodobě stabilní standardy. Naštěstí v oboru strojového vidění pracujeme převážně s obrazovými
        daty a tradiční podoba grafického řetězce nám většinou velmi dobře
        vyhovuje. 
 Obr.1: Řetězec zpracování grafických dat v GPUPři obecných výpočtech pracuje GPU velice podobně. Pouze místo
        obrazových dat se pracuje se vstupními a výstupními bloky
        obecných dat a shadery jsou do jisté míry obecnými paralelními vlákny.
        Obraz z kamery vstupuje do GPU jako objekt textury, který musí být na
        začátku přenesen ze systémové paměti počítače do grafické paměti,
        které je přístupná pro GPU. Výsledný obrazový buffer nakonec také musí
        být často přenesen nazpět do systémové paměti počítače. Také bloky
        obecných dat musí být takto přenášeny mezi systémovou a grafickou
        pamětí. Tento princip může být pro programátora částečně zakryt
        programovým rozhraním vývojového prostředí, limity z něj plynoucí však
        překonat nelze. Právě přenosy velkých objemů dat mezi systémovou a grafickou pamětí
        (grafické adaptéry jsou obvykle připojeny přes sběrnici PCI-Express)
        mohou představovat citelné zpomalení a stát se tím rozhodujícím
        problémem v neprospěch využití GPU. Úloha vhodná pro GPU také musí mít několik charakteristických
        znaků. CPU má jen několik jader, ale každé toto jádro může pracovat na
        zcela odlišné úloze. GPU má výpočetních jader velmi mnoho, ale
        zjednodušeně řečeno, všechna jádra musí, byť s různými vstupními daty,
        zpracovávat tutéž úlohu. Výhody takovéto masivní paralelizace se více
        projeví v úlohách s vysokou výpočetní intenzitou, velkými objemy
        paralelně zpracovávaných dat a s minimálními závislostmi
        mezi jednotlivými těmito daty. Výsledek každého paralelního výpočtu v
        GPU závisí jen na vstupních datech a nikoliv na výsledky výpočtů
        ostatních paralelních procesů. Jednotlivá výpočetní jádra se tedy
        v průběhu výpočtů nemohou ovlivňovat, pouze mohou číst mnoho
        vstupních vektorových dat z mnoha datových polí. Prostředky GPUPro zpracování obrazu nás zajímají především: 
              
              Programovatelné procesory – v uniformní architektuře
              mohou vystupovat jako vertexové, fragmentové a geometrické. Při
              zpracování obrazu z kamery využijeme tradiční funkce vertexových
              a fragmentových shaderů: 
                  Vertexový shader je spuštěn pro každý vertex,
                  vykreslujeme-li např. trojúhelník, je spušten celkem
                  třikrát. Jeho výsledkem je grafický element, který je předán
                  do rasterizeru.Fragmentový shader je spoušten výstupem rasterizeru
                  pro každý fragment, tedy pro každý obrazový bod vykreslované
                  scény.Rasterizer – prostřednictvím interpolace vytváří
              jednotlivé fragmenty z obrazových elementů. Základním obrazovým
              elementem je trojúhelník, definovaný třemi vertexy. V jeho
              ploše jsou pak resterizerem interpolovány texturové souřadnice
              nebo barvy fragmentů.Textury – jsou bloky grafické paměti, které mohou být
              čteny fragmentovými procesory. Data z texturových objektů lze
              pouze číst, zápis do nich není fragmentovými shadery
              možný.Framebuffer – je blok paměti, do které fragmentové
              procesory zapisují výsledku běhu fragmentových shaderů. Data
              uvnitř framebufferu nelze fragmentovým procesorem číst
              a dokonce každý s paralelně běžících fragmentových
              shaderů může zapsat jen do jediné pozice v bufferu, která
              odpovídá jeho instanci v rámci plochy obrazu. Omezení textur jako zdrojů dat, do kterých není možno
            zapisovat, a framebufferů jako cílů, které nelze číst, klade další
            nároky na kopírování bloků dat v grafické paměti během opakovaného
            vícenásobného spouštení shaderů pro daný framebuffer. Proto dnes
            existuje možnost přiřazení textury jako cíle vykreslování. Tato
            možnost umožňuje realizovat vícenásobné vykreslování maximálně
            efektivně. Datové typy a programovatelnostGPU byly navrženy pro práci s obrazovými daty a
              zpočátku tak byly podporovány pouze celočíselné datové typy,
              které popisovaly fragmenty, tj. obrazové body – pixely. Pro
              všeobecné výpočty je důležitá schopnost dnešních GPU pracovat s
              poli vektorů čísel s plovoucí řádovou čárkou s jednoduchou (FP32
              – 4 byte na jedno číslo s plovoucí řádovou čárkou –float) i
              dvojnásobnou (FP64 – 8 byte na jedno číslo s plovoucí řádovou
              čárkou - double) přesností. Vstupní a výstupní data mohou být
              obvykle v těchto formátech: 
              
              8 bitů na pixel – takto je reprezentován buď index do
              palety barev nebo dva bity pro červenou, tři zelenou a tři
              modrou barvu16 bitů na pixel – obvykle pět bitů určuje červenou a po
              šesti bitech má k dispozici zelená a modrá barva24 bitů na pixel – osmibitový červený, zelený a modrý
              kanál32 bitů na pixel – osmibitový červený, zelený, modrý a
              alpha kanál reprezentující míru průhlednosti1 až 4 čísla v plovoucí řádové čárce na pixel, kdy každé
              číslo má přesnost na 16, 24, 32 nebo 64 bitů (FP16, FP24, FP32
              nebo FP64) Podstatnou vlastností paralelních procesorů v GPU je také
            to, že pracují v jedné instrukci s celými vektory. Např. při
            sečítání dvou čtyřrozměrných vektorů jsou současně sečteny všechny
            jejich příslušné složky. Ovladače grafických adaptérůSe začleněním překladačů vysokoúrovňových jazyků se grafické
            ovladače dále zkomplikovaly a jejich dlouholetá pověstná chybovost
            se mohla rozšířit do nových rozsáhlých oblastí. Na počátcích
            těchto technologií to opravdu programátoři neměli jednoduché.
            Relativně nejméně chyb vždy bývalo v ovladačích pro grafické
            adaptéry NVIDIA. Dnes již je v této oblasti situace naštěstí
            celkem stabilní a software využívající GPU obvykle pracuje
            spolehlivě s ovladači všech hlavních výrobců. Využití GPU v systému strojového vidění VisionLabAlgoritmy strojového vidění často pracují s velkými objemy
            dat a v těchto případech nebývá nikdy výpočetního výkonu
            nazbyt. Využití GPU všude tam, kde je to rozumné, nejenže přináší
            podstatnou akceleraci zpracování, ale dokonce umožňuje realizovat
            takové algoritmy, které by jinak byly v akceptovatelném čase
            nerealizovatelné. V programovém systému Control Web existují dva základní typy
            kamerových virtuálních přístrojů. Kromě základního přístroje
            camera existuje ještě přístroj gl_camera, který pro zpracování
            obrazových dat z kamery i jejich zobrazování používá
            vykreslovací stroj systému Control Web, který se vyznačuje
            architekturou klient-server a pracuje ve vlastním paralelním
            vláknu. Tento vykreslovací server mohutně využívá programovatelné
            GPU. V optimální situaci se tedy jedno jádro CPU stará o
            přípravu grafických dat a jejich transport do grafické
            paměti, kde jsou tato data masivně paralelně zpracována grafický
            procesorem. Takové řešení přináší výjimečně vysoký výkon při
            minimálním zatěžování vláken v reálném čase běžící aplikace.
            Zde je několik příkladů: Pokročilá adaptivní interpolace barevné mozaikyPodstatnou věcí ve prospěch kvality obrazu je možnost číst
                z barevných kamer syrová data a interpolovat barevnou mozaiku
                až v počítači a nikoliv již v kameře. Řada
                operací s obrazem je vzhledem k omezeným možnostem čipů
                kamerových řídicích jednotek velmi kompromisní. Kamera při
                interpolaci barevné mozaiky musí zůstat omezena na základní
                bilineární interpolaci, která je řešitelná celočíselnými
                výpočty. Obraz je pak zatížen všemi nežádoucími artefakty
                tohoto postupu, které plynou mimo jiného ze vzájemného
                prostorového posunu červeného a modrého barevného kanálu. Ve
                výsledku pak pozorujeme v blízkosti kontrastních hran
                šachovnicové vzory a modročervené lemování. Pokročilé
                algoritmy, které produkují výrazně čistší a ostřejší
                obraz, musí využívat výpočtů v plovoucí řádové čárce a
                obsahují více průchodů plochou obrazu. Takový algoritmus již
                není možno v reálném čase na proudu dat z kamery
                řešit ani pomocí vícejádrových CPU, je však příkladem ideální
                úlohy pro masivní paralelizaci v GPU. Virtuální přístroj
                gl_camera umožňuje volit mezi několika algoritmy
                interpolace barevné mozaiky. Adaptivní interpolace je v CPU nerealizovatelná v reálném
                čase a použití jakéhokoliv, byť "zastaralého" GPU je velkým
                přínosem. Korekce geometrických zkreslení obrazuProgramovatelná GPU umožňují velmi elegantně řešit
                problematiku změn geometrie obrazu, tzv. pixel displacement.
                Virtuální přístroj gl_camera tímto způsobem elegantně řeší
                nejen kalibraci geometrických zkreslení objektivů, ale dokáže
                např. i korigovat perspektivní zkreslení, odstranit natočení
                obrazu, rozvinout obraz z povrchu válce či koule. Umožňuje
                srovnat libovolně nelineárně deformovaný obraz. Tato úloha je rozdělena na dva klíčové problémy: za prvé
                jak informaci o správných pozicích získat a zadruhé jak obraz
                kvalitně zpracovat v reálném čase bez neúnosné zátěže
                počítače. Nejprve musíme získat obrazovou mapu, která popisuje změny
                pozic všech pixelů výsledného obrazu. Mapu získáme tak, že do
                zobrazovací roviny vložíme bodový rastr a systém si uloží
                kalibrační data pro daný objektiv a konfiguraci měření.
                Algoritmus měření mapy objektivy pracuje v CPU s přesností na
                setiny pixelu. Zde nám tolik nezáleží na rychlosti, tvorba
                mapy proběhne jen jednou, ale požadujeme nejvyšší
                přesnost. Rychlost geometrických korekcí každého snímku z kamery je
                již kritická a tento algoritmus musí běžet v GPU. Ukazuje se,
                že kvalita hardwarových texturových filtrů a interpolátorů u
                námi vyzkoušených GPU není dostatečná pro kvalitu obrazu
                požadovanou pro tuto úlohu. Proto je tvorba výsledného obrazu
                řešena s vysokou subpixelovou přesností programem
                fragmentového shaderu, který poskytuje zaručeně kvalitní a
                stabilní výsledky na veškerých GPU. 
 Obr. 4: Znázornění obrazové mapy pro geometrickou
                  kalibraciNěkteré systémy strojového vidění se pokouší kalibraci
                geometrie obrazového pole řešit v CPU. Výsledky ale odpovídají
                tomu, že z důvodů šetření výpočetním výkonem musí být
                zavedena řada omezení a kompromisů. Často se používá po
                částech bilineární interpolace obrazové mapy a také
                filtrace obrazu nemůže být dostatečně kvalitní. Výsledkem je
                pak nespojitý schodovitý obraz. Tato funkce je i prostředky nejvýkonnějších
                vícejádrových CPU realizovatelná jen problematicky a použití i
                slabšího zastaralého GPU je velkým přínosem. Obrazové filtryObrazové filtry vypadají na první pohled jako optimální
                úlohy pro řešení v GPU. Často tomu tak je, ale nemusí to
                platit univerzálně. Potíž může být v tom, že řada jednoduchých
                kernelových filtrů nemá příliš vysokou výpočetní intenzitu (a
                současné vícejádrové CPU také nepočítají až tak zoufale
                pomalu). Režie přenosu obrazových dat mezi systémovou a
                grafickou pamětí pak může i stonásobně vyšší rychlost výpočtů
                kernelu v GPU oproti CPU znehodnotit. 
 Obr. 5: Rychlost i velmi komplexních GPU filtrů je
                  omezena převážně režií přenosu datSituace se ale dramaticky změní v případě filtrů s nutností
                složitějších výpočtů v plovoucí řádové čárce, jako je tomu
                např. u transformací barevných prostorů, řešení saturační
                matic, šumových filtrů atd. Pak nám může využití GPU zrychlit
                tyto kroky až o dva řády. 
 Obr. 6: Anisotropický šumový filtr využívá výkonu
                  GPU ve výpočtech s plovoucí řádovou čárkouJednoznačnou úlohou pro GPU jsou i takové filtry, kdy pro
                výpočet každého pixelu je nutno číst mnoho pixelů z jeho okolí
                – příkladem mohou být algoritmy lokálního prahování obrazu.
                Pak schopnost GPU načítat desítky gigapixelů za sekundu z
                textur je nenahraditelná. GPU řešení může být i několiksetkrát
                rychlejší než snaha o totéž v CPU. 
 Obr. 7: Lokálně prahovací filtr využívá mohutného
                  datového toku GPU při čtení pixelů texturVe prospěch GPU se situace dále přiklání ve všech
                případech, kdy je nutno určitý filtr vícekrát opakovat. Tento
                požadavek je charakteristický např. u morfologických
                filtrů, které nejsou samy o sobě výpočetně příliš
                náročné, ale často potřebují desítky i stovky opakovaných běhů
                – příkladem může být např. hledání koster objektů nebo
                segmentace ploch kolem objektů. Obrazová data během
                opakovaných běhů filtru neopouští grafickou paměť a jsou stále
                rychle přístupná pro GPU. Pro tyto algoritmy je masivní
                paralelizace velkým přínosem. Transformační kódováníPříkladem zde může výt dvojrozměrná Fourierova transformace
                - převod obrazu z prostorové (časové) do frekvenční domény
                (krok gpu_fast_fourier_transform_2D). Byť je zde použit
                algoritmus rychlé Fourierovy transformace (FFT), transformace
                obrazu je natolik výpočetně intenzivní, že v reálném čase není
                jinak než s využitím GPU realizovatelná. Zde již není
                možno použít starší GPU, potřebné jsou vektory vstupních
                textur i výstupních bufferů s plovoucí řádovou čárkou.
                Takže nemáme na výběr – bez moderního grafického procesoru to
                v tomto případě nejde. GPU dokáže realizovat rychlou dvourozměrnou Fourierovu
                transformaci na proudu obrazových dat z kamery v reálném
                čase. Další možnostiVeškeré dosud uváděné příklady byly celkem jednoznačné.
                Existují však i problematické úlohy, kde přínosy GPU nemusejí
                být takto jasné. Příkladem takové úlohy může být např. rozpoznávání vzorů
                realizované prostřednictvím GPU (krok gpu_match_monochrome v
                systému VisionLab). Během hledání obrazového vzoru musí systém
                mnohokrát provádět normalizovanou křížovou korelaci s velkým
                počtem pixelů. To vyžaduje mnohonásobně opakované výpočty
                středních jasů, směrodatných odchylek, odmocnin atd. – to vše
                s plovoucí řádovou čárkou. Navíc krok hledá i pootočené nebo
                zvětšené či zmenšené obrazy předloh. Veškeré výpočty tedy
                navíc podléhají lineárním transformacím. Toto všechno vypadá
                na první pohled jaké výborná úloha pro GPU. Je však zde
                závažná potíž – výpočetní intenzita algoritmu je natolik
                vysoká, že není hrubou silou rozumně proveditelný ani
                nejvýkonnějšími GPU. Podobně jako v algoritmech pro CPU, musí
                i zde nastoupit řada optimalizací. A právě v těchto
                optimalizacích, bez kterých ale problém tak jako tak řešit
                nelze, se skrývá kámen úrazu. Algoritmus je nutno rozdělit do
                více fází, mezi kterými musí probíhat výměna dat mezi GPU a
                CPU. Časové ztráty přináší jednak kopírování bloků dat, ale
                také to, že CPU i GPU musí na sebe vzájemně mezi jednotlivými
                fázemi čekat a nemohou běžet paralelně. Tento krok je tedy
                výhodné použít jen s moderními velmi výkonnými GPU – čas
                hledání může být až desetinásobně kratší než na vícejádrových
                CPU. S méně výkonnými grafickými procesoru se ale může situace
                obrátit a krok může být i pomalejší než obdobný realizovaný
                čistě v CPU. Autor aplikace tedy musí vše zvážit a prakticky
                vyzkoušet. 
 Obr. 10: Hledání vzorů realizované prostřednictvím
                  GPU - tento příklad trvá asi 50ms na procesoru G80Obdobně, jako existují úlohy, pro které nelze použít
                masivně paralelní algoritmy v GPU, je zde i spousta úloh,
                které nelze efektivně řešit dokonce ani paralelními vlákny
                v CPU. Neexistuje zde jediný lék na všechno. Pro každou aplikaci musí její autor zvolit nejlepší způsob
                řešení. A k tomuto rozhodování patří i to, kde využije
                mohutného potenciálu grafických procesorů. ZávěrSystém strojového vidění VisionLab poskytuje krokům, které
            využívají GPU značný prostor. S vykreslovacím jádrem systému
            Control Web i virtuálním přístrojem gl_camera komunikují jen
            prostřednictvím velmi jednoduchého povelového rozhraní. Kroky
            dostanou k dispozici paměťový pixel buffer dané velikosti
            a formátu pixelů a mohou si zcela samostatně alokovat
            libovolné prostředky GPU – mohou si vytvářet např. vlastní
            texturové objekty, další frame buffer objekty, samozřejmě mohou
            načítat a spouštět vlastní shadery atd. Kroky strojového
            vidění tak mohou využívat veškerá nejnovější rozšíření, které
            přinášení aktuální grafické ovladače. Tyto možnosti umožňují
            systému strojového vidění VisionLab stále sledovat poslední vývoj
            technologií a přinášet tak svým uživatelům vysoký užitek a
            konkurenční výhodu. rc |