|
|
V souvislosti s uvedením Snow Leoparda se často mluví o technologii Grand Central Dispatch. Jedná se o relativně komplikovanou záležitost a asi z toho důvodu komentátoři většinou pouze opakují obecný pois ze stránek Apple, nebo co zaslechnli na WWDC. O co tedy vlastně jde? Předně je třeba říct, že se nejedná o nic nového natož pak revolučního. Existuje už několik velmi podobných implementací, pokud např. znáte Intel TBB, Qt Concurrent, Clik++ pak nemusíte v podstatě dále číst.
Microsoft chystá do VS 2010 hezky vypadající implementaci Concurrency Runtime. Doporučují prohlédnout si příklad, oproti normálnímu C++ jsou tam navíc jen lambda výrazy, na kterých to celé stiojí. Jedná se o provedení nějaké operace nad prvky nějaké kolekce a to s takovou mírou paralelity, jakou uzná za vhodné operační systém (resp. nějaký runtime nad ním). A to vše bez použití (sprostého?) slova thread.
Tady je jiný hezký příklad, který při prohledávání stavového prostoru na místech, kde by se algoritmus mohl vydat různými směry tak se rozmnoží a výpočet pokračuje všemi možnými směry současně (něco pro milovníky NDTM
). A to aniž by se ve zdrojáku kdekoliv vyskytlo (sprosté?) slovo thread.
Z těch příkladů je patrné, že se jedná o vytvoření programovacího paradigmatu, který:
Konečně zpět k GCD. Je mechanismus, který pro každý proces využívající GCD spravuje thread pool a jednu nebo více front (s prioritami) obsahujících “bloky práce”, které je třeba vykonat. GCD na základě dostupných zdrojů a znalosti front z jiných procesů vybírá bloky z front, přiřazuje je threadům z thread poolu a tím je provádí. Když programátor narazí na místo, které bybylo vhodné paralelizovat tak vytvoří několik “bloků práce” a hodí je do fronty případně může nechat vytvářet bloky v reakci na nějakou událost (např. časovač nebo socket). Čas na příklad.
Mějme cyklus
for (i = 0; i < count; i++) {
//dělej něco s i
}
ve kterém nezáleží na pořadí provádění jednotlivých iterací. Pak ji můžeme paralelizovat takhle:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(count, queue, ^(size_t i) {
//dělej něco s i
});
dispatch_apply vytvoří count lambda výrazů a každému z nich předa příslušnou hodnotu parametru i (tím se z nich stanou bloky) a hodí je do fronty. Blok je closure, ani nevím, jak se to řekne česky. Skončí až se celá fronta vyprázdní. Blok nemusí být definován přímo v seznamu parametrů, tzn. jako anonymní, deklaruje a definuje se velice podobně jako ukazatel na funkci. Místo hvězdičky se píše stříška. Je to edy syntaktické rozšíření C, C++ a Objective-C. Více k tomu zde. C++0x lambdy vypadají jinak a nejsou closure.
To je celý základ, zbytek je omáčka okolo- lze definovat callback, který se zavolá po dokončení bloku, lze použít semafory k omezení přístupu k limitovaným zdrojům jako např. připojení k databázi, fronty lze pozastavit, určit priority…
Čekali jste něco, co samo pozná, co se kde dá paralelizovat, vyřeší race conditions a deadlocky? Doufám, že ne páč se nic takového nekoná. Čekali jste zajímavou implementaci abstrakce nad thready s plánováním ne na úrovni procesu ale na úrovni celého systému? Pak jste se trefili.
Největším problémem GCD podle mně je, že je ukrutně platformově závislý. V multiplatformních aplikacich se to z toho důvodu asi moc používat nebude.
Tohle 9 (slovy devět) let existuje ve Windows od verze Windows 2000 a taky se to zhusta využívá. Mac OS přišel s křížkem po funuse. Knihovny jsou v .NET nejméně 5 let, v C++ je to těch 9 let. Dále je ve Windows takhle uděláno nejenom pro ThreadQueue ale i pro TimerQueue, takže programátor doslova nahrne práci do Windows a dál se nestará, Windows to řeší za něho samovolně.
1: a existovalo to už před vícejádrovými procesory a Microsoft to příští rok představí znova, jenom aby se na to nezapomnělo.
[1] Porovnávať Grand Central s TimerQueue je vážne zábavné. Myslím že keď budeš mať pole s 10^7 prvkami a pre každý zaregistruješ timer callback asi budeš výkonom dosť sklamaný ![]()
Každopádne toto porovnanie je úpne scestné a dosť smiešne. Mimochodom - ThreadQueue? Nepamätám si že by som niečo také v .net videl.
[2]
žeby ten MS bol až taký dobrý, a podporoval viacjadrové procesory ešte pred tým ako vznikli?
Mimochodom, koho zaujíma, že MS mal niečo také už vo Viste? Je to rovnaké ako napr. s Time Machine. Možnosti boli, nikto o nich nevedel a preto ich nepoužíval.
http://www.infoworld.com/d/windows/apple-steals-microsofts-multicore-thunder-grand-central-594
http://www.infoworld.com/d/windows/building-my-windows-7-time-machine-966
Ale více jádrové stroje jsou tu už dost dlouho…
[cca1] tie články sú neuveriteľne ignorantské. Randall Kennedy evidentne o GC nemá ponatia. GC nie je len o tom že môžeš rozložiť task na viac vláken. Veď to tu bolo dávno. GC je o tom ako to spravíš. Rozšírenie objc o closury (blocks), závislosti medzi task queue, automatické vytvorenie threadov v závislosti na počte a vyťažení CPU, atď. Žiadna z týchto vecí nie je úplne nová ani niečo čo tu ešte nebolo. Ale spojené dokopy to robí písanie vlacvláknových programov oveľa jednoduchšie ako keď ti niekto povie: Tu máš pár funkcií na vytvorenie vláken a synchronizáciu, staraj sa.
Je to podobné ako s time machine. To že vista má integrovaný backup je známa vec. Ale že to nikto nepoužíva má dobrý dôvod. Nikomu sa s tým nechce babrať. Zatiaľ čo time machine je vec ktorú nastavíš na dva kliky.
Podobne je to s viacvláknovými programami. Požnosti písať paralelné algoritmy sú dostupné dávno. Ale pri väčšine taskov sa na to väčšina programátorov vykašle pretože im to za tú námahu nestojí. Práve ten treshold chce GC znížiť.
Pred tým ako ktokoľvek začne diskutovať o GC mal by si prečítať toto:
http://arstechnica.com/apple/reviews/2009/08/mac-os-x-10-6.ars/12
a porozmýšlať či to tu skutočne v takejto forme už bolo a nie začať argumentáciu typu ale veď aj XXX má thread pool.
Mihův blog využívá WordPress MU a běží na Blog.zive.cz. Vytvořte si svůj vlastní blog
Sledování přes RSS: články
a komentáře
Partnerská sekce pro IT profesionály:
Microsoft TechNet/MSDN