
c++ více vláken, stejná cache
Zdravím,
píšu program, mám zde frontu úkolů, a potom vlákna, které mají frontu obsluhovat.
Problém nastává v tom, že fronta úkolů je globální proměnná, a když program běží ve více vláknech, tak každé vlákno, co upraví tu frontu tím způsobí, že u druhého vlákna přestane platit cache, a program se tím neskutečně zpomalí.
Nějak by to chtělo zajistit aby všechny vlákna používali stejnou cache. Ať data nemusí načítat přímo z paměti.
BTW. vies co to je critical section? Ak nie tak to je ta chyba.
Vím co je to kritická sekce.
Program funguje bez problému, nejsou tam žádné chyby. Jen je pomalejší, když vytvořím více než jedno vlákno.
int promenna = 0;
void vlakno(){
while(nejaka podmínka){
...nejaky kod;
LOCK();
promenna = promenna + 1;
UNLOCK();
}
}
Pokud mám jedno vlákno, tak to jedno vlákno má uloženou proměnnou "promenna" v cachce a nemusí sahat vůbec do paměti. Program je pak o něco rychlejší kvůli tomu.
Když mám dvě vlákna, tak každé vlákno má svoji vlastní cachce. Pokaždé když se tedy změní proměnná "promenna", musí ji jedno vlákno uložit do paměti, a druhé má neplatnou cache, a tak ji musí zase načíst z paměti. Program je potom mnohem pomalejší. (cache je rychlejší než paměť).
Proto by bylo vhodné nějak zařídit aby ty sdílené proměnné byli i ve stejné cache.
Cache funguje na HW urovni a nezaujimaju ju ziadne vlakna. Ked ti program nefunguje tak jak ma alebo tak jak ocakavas, tak mas v nom chybu (alebo v koncepte). Nechce sa mi lustit teraz tvoj program (ani si tu ziaden nedal, len splietas nezmysly)
Příklad kódu na kterým je to nejvíce vidět.
pokaždé jsou v programu 4 vlákna, všechny udělají stejný počet operací, ale pokud program pustíte na jednom jádře, tak bude výrazně rychlejší než když povolíte všechny jádra. (správce úloh >> podrobnosti >> spřažení >> jedno jádro pro příkazovej řáek ze kterýho to budete spouštět.)
Asi jsem se minule někde upsal, ale myslel jsem to tak, že každé jádro má vlastní cache.
Když tedy běží čtyři vlákna na jednom jádře procesoru - sdílí stejnou cache.
Když běží čtyři vlákna na čtyřech jádrech procesoru - mají každou svoji vlastní cache.
Ještě k tomu, když bych snad vytvářel vlákna nějak špatně, a kvůli tomu by se to zpomalilo. Proč to zpomalení není vidět v případě, kdy program běží na jednom jádře procesoru (jedna cachce pro všechny vlákna) a vytváří 10 000 vláken ??
Kazde jadro ma svoju L1 cache, L2 cache je spolocna. Vsetko je vec HW a neda sa to zmenit.
V tom programe nic neratas a vpodstate vsetky thready vkuse cakaju na lock. Za normalnych okolnosti thready maju robit ulohu ktora je XYZXYZ x narocnejsia jak lock. potom sa to neprejavuje.
P.S. a to je ta tvoja "chyba" (koncept pri multiprocesingu)
Ale jak píšu, když program běží v jednom jádře procesoru, (jedna L1 cachce) tak se problém neprojeví
Ale ty nemas program, ty mas prazdny lock a unlock. Jasne ze synchronizacia medzi core ma nejaku reziu. To neni problem, to je fakt ktory ma vediet kazdy programator. Az napises program normalny, ktory pracuje XYx dlhsie jak synchronizuje, tak nebudes mat ziaden problem.
P.S. uz pred 20rokmi sa to ucilo na vyske, bol o tom cely semester. Rezii sa nevyhnes, musis programovat tak aby to nevadilo alebo aby dopad bol minimalny. Napr. tak ze zoberes pre kazdy thread na vysokej urovni programu vacsi kus ulohy a unlocknes a makas, a nebudes to lockovat furt na najnizsej urovni.
Alebo napr. mozes mat frontu pre kazdy thread svoju, a ten kto vklada do fronty to rozdeluje do ciastkovych front apod. (a budes mat pevny pocet threadov napr. 4) ak to vkladanie neni casto apod.(zavisi od toho co riesis a k tomu treba urobit koncept). Alebo thready robia kazdy nieco ine. Ciel je minimalizovat synchronizaciu medzi cores. A je nezmysel vytvarat 10000 threadov, synchronizacia threadov ma vzdy overhead. Ktory si prave zmeral.
P.S. 2core spolu NEurobia nikdy tolko ako 1core 2xrychlejsie. To sa uci snad ako prve.
Ak tvoj program vyzerá podobne, tak potom áno, v spomalení zohráva svoju rolu aj cache na jednotlivých jadrách CPU. Všetky vlákna prakticky neustále súperia o vstup do kritickej sekcie. V tejto ukážke vlákna v podstate nerobia nič iné, než len sa medzi sebou synchronizujú.
Za normálnych okolností spracovanie z fronty vyzerá tak, že sa z nej vyberú dáta o úlohe a tá sa potom spracuje samostatne, bez potreby ďalšej synchronizácie. Synchronizovaný je len výber z fronty, ktorý zvyčajne trvá oproti spracovaniu zanedbateľný čas.
Ak sa nevieš vyhnúť tomu, aby sa tvoj program podobal tejto ukážke, tak to zadanie potom nie je vhodné na paralelizovanie a bude lepšie to spracovávať sekvenčne.