DualCore procesory
Hodnotenie čitateľov: / 2
SlabéVynikajúce 

AMD X2 64V Marci 2007 sme si s Barborkou zakúpili z Dell-u mašinu s dvojjadrovým procesorom. S veľkým prekvapením a hrôzou som zistil, že na takej rýchlej mašine môj Viresol beží omnoho pomalšie než na notebook-u. Maličký slabučký procesorík, v porovnaní s krabicou nadupanou vo veľkom desktop-e, vydáva vo všeobecnosti lepší výkon aj v hrách.

Začal som sa problému venovať a hneď objavil, za pomoci Task Manager-a, že všetky výpočty bežia na iba jednom z dvoch jadier. Akokoľvek som zaťažil ViReSol, maximálne som vyčerpal 50% kapacity.

Rozhodol som sa s týmto skoncovať a upraviť ViReSol tak, aby vedel využiť obe jadrá procesora.

Procesy a ich vlákna

Na jednotlivé procesy (hlavné vlákna aplikácií) sa dá nastavovať afinita (Affinity), ktorá udáva na ktorých z dostupných jadrách (resp. CPU) bude mať proces povolené exekuovať svoje príkazy. Ktosi z Microsoftu si to vymyslel tak, že Windows XP podporuje maximálny počet 32 procesorových jadier: CPU 0 - CPU 31.

Afinita procesov však nie je predmetom nášho záujmu. Náš proces, hlavné vlákno aplikácie, ViReSol-u, bude ajtak môcť vykonávať len na jednom z jadier, aby všetko išlo pekne poporiadku. Tak či onak, samotná nečinná oddychujúca aplikácia nezažiera ani percento z celkovej kapacity oného jadra. Čo však dá zabrať, sú výpočty ako napríklad pri exportovaní obrázku v kompletnom 3 MPix rozlišení, keď sa na každom z troch miliónov pixelov musí vykonať neúrekom výpočtov. Nechať na tom pracovať len jedno jadro si programátor nemôže dovoliť, strácajú sa nie zlomky sekundy, ale celé večnosti. Smile

Teória riešenia

Preto si treba premyslieť, čo a na ktorom jadre necháme vykonávať. Vytvoríme si vlákna, toľko vlákien koľko jadier (avšak ešte nie je celkom bežné, aby ľudia mali viac než dva procesorové jadrá, tak vytváram len dva jadrá). Najprv si však zistíme afinitu procesu aby sme vedeli, či vôbec máme viac než jeden procesor k dispozícii. Ak áno, pokračujeme.

Dva vlákna, každé na vlastnom jadre (nastavujeme afinitu pre každé vlákno zvlášť) necháme spracovávať polku z obrázku, v hlavnom procese počkáme na ukončenie oboch vlákien, a výsledky spojíme. A už v polčase máme hotovo.

Riešenie

GetProcessAffinityMask(GetCurrentProcess,ProcessAffinity,SystemAffinity);

Pri štarte aplikácie zavoláme túto jednu metódu pre zistenie afinity jednak procesu, ako i celého systému. ProcessAffinity je premenná, do ktorej uložíme afinitu aktuálneho procesu (procesu, ktorého Handle zadáme ako prvý argument funkcie GetProcessAffinityMask, no a práve v našom prípade, logicky, použijeme Handle nášho procesu, ktoré zistíme zavolaním funkcie GetCurrentProcess). Taktiež získame aj systémovú afinitu, ktorá nám hneď ukáže, koľko má náš systém k dispozícii CPU.

ProcessAffinity aj SystemAffinity sú takzvané Affinity Mask-y typu DWORD (double word, 32 bitov). Každý z týchto bitov zodpovedá jednému procesorovému jadru. Ako som spomínal, systém Windows dokáže spravovať maximálne 32 procesorov, CPU 0 - CPU 31.

A teraz sa nám v tom už začína črtať určitá analógia. Napríklad zistíme, že afinita procesu je 3. Čo z toho? Keď sa pozrieme na číslo 3 ako je zapísané v tých 32 bitoch našej Affinity Mask-y, vidíme kóópu núl 000... a posledných 8 bitov vyzerá takto:

0000 0011

čiže tento proces (s afinitou vyčíslenou na 3) má povolené používať CPU 0 a CPU 1 zo všetkých procesorov systému.

constructor Create(AffinityMask:dword); overload;

constructor TRenderingThread.Create(AffinityMask:dword);
begin
inherited Create(false);
SetThreadAffinityMask(self.Handle,AffinityMask);
end;

A toto je upravený konštruktor vlákna. Vlastne sa použije zdedená časť konštruktora klasického vlákna TThread a pridá sa riadok pre nastavenie afinity novovytvoreného vlákna.

Takto sa to teda rieši, už je na vás, ako si to upravíte podľa svojich potrieb.

Posledná úprava ( Tuesday, 26 April 2011 )
 
< Predchádzajúca