Napred jsem nastudoval instrukce SSE4 a implementoval to pomoci nich. Jake pak bylo nemile prekvapeni, kdyz jsem zjistil, ze SSE4 ten procesor nepodporuje... Ale jinak obecne zrychleni pomoci threadu je dosti omezujici ... teoreticky max. 8x, ale v praxi mene ... jadra sdili jiste prostredky (cache, pamet apod.), pribude nejaka rezie na obsluhu vlaken apod. Ale je zde velka rezerva prave v optimalizaci seriove verze algoritmu a zaroven rozumnem rozvrzeni do vlaken s ohledem na sdilene prostredky. To je videt take na seriovem programu mlk. Takze se snazim pochopit zpracovani programu na nejnizsi urovni (instrukce procesoru) a prizpusobit tomu program - rozvrzeni dat v pameti, poradi zpracovani, pouziti vhodnych SIMD instrukci, prednacitani dat do cache apod. Celkem zajimave pocteni a ruzne tipy a triky jsou v manualech od Intelu (v PDF ke stanzeni na webu Intelu
http://www.intel.com/products/processor/manuals/), kde se primo zabyvaji optimalizaci, instrukcemi procesoru apod. Dale cerpam z menualu k Intelovskemu kompilatoru. Myslim, ze si mi to bude hodit i na jine veci ...
Neni vzdy nutne pouzivat primo assembler, protoze prekladac nekdy pochopi dany zamer napsany v Ccku a prelozi jej celkem dobre (nekdy i lepe, nez bych to napsal rucne). Ale ten Ccko kod vychazi primo z predstavy o tom, jak to bude vypadat v instrukcich procesoru. Tedy napred si to rozmyslim v instrukcich a pak zapisu v Ccku ... pripadne pseudoinstrukcich (Intelovsky kompilator ma nejake hlavickove soubory s funkcemi podobnymi s instrukcemi a prekladac je celkem inteligentne preklada). Nasledne koukam, jake instrukce kompilator vygeneroval a pokud tam vidim nejaky zjevny problem, snazim se jej odstranit. Bohuzel zatim nemam kompletni predstavu o tom, jak probiha pipeline, kolik instrukci dopredu musim co prednacitat apod. .... takze je to dosti o experimentovani a zkouseni ruznych konstant.
Ted tam nemam zadny inline assembler (jen vyuzivam funkce od Intelovskeho kompilatoru), ale chci to vyzkouset. Take mam jeste jistou rezervu v rezii - tedy zatim jsem optimalizoval jen vlastni nasobeni matic (a nikoli cteni ze souboru, zapis do souboru, reorganizace dat apod. ... a jeste tyhle veci delam jen v jednom threadu).
Kompiluji pomoci Intelackeho kompilatoru ... ale ne kvuli vykonu, ale kvuli tomu, ze to pisu ve Windows (Visual Studio) a GCCcko mi vzdycky vyhodi 100 chyb, ktere se mi nechce opravovat. A take je pro me dokumentace Intelu mnohem stravitelnejsi nez od GCC. Kdyz byl program jeste jednoduchy a sel mi po drobnych upravach zkompilovat i GCCkem, tak rozdil nebyl meritelny - jak by tomu bylo nyni, to nevim. Vliv nejakych parameteru na rychlost jsem nezaznamenal, i kdyz jsem zkousel kde co - kompiluji pouze s parametry -lpthread -D_REENTRANT. Ani zadne -Ox apod. tam nemam.
Zajimave by mohlo byt pouziti nejake lepsiho algoritmu (Winograd apod.) ... u vetsich matic by uz rozdil mohl byt dost znat. Krome toho rekurze se muze pomerne dobre paralelizovat. Zatim ale pouzivam primitivni, ktery pocita v kubickem case. Myslel jsem, ze jej zkusim ... ale uvidim, zda se k tomu casove dostanu.
Celkove to asi neni dobry postup, ale lepsi neznam. A je to pekny zrout casu.
PS: Take by me zajimalo, na jak velkych maticich se to bude merit, protoze optimalizace pro ruzne velikosti je zcela jina. Napr. pro male matice nema smysl spoustet mraky vlaken a pouzivat asymptoticky lepsi algoritmus. V extremnim pripade matic 1x1 pak jde jen minimalizaci rezie... Naopak pro hodne velke matice by melo smysl se zamerit na setreni pameti, aby se data vubec vesla do pameti (bez swapovani). Zatim to ladim pro takovy stred (cca matice medium a large).