Potential QA¶
Navigation¶
- Základné pojmy
- Všeobecná paralelizácia
- C# a .NET
- Otázky priamo k Mandelbrotovi a tvojej prezentácii
- Krátke „záludné“ otázky, ktoré sa môžu objaviť
Presentation QA¶
Základné pojmy¶
1. Čo je proces? Proces je bežiaca inštancia programu. Má vlastný adresný priestor, vlastné systémové prostriedky a môže obsahovať jedno alebo viac vlákien.
2. Čo je vlákno? Vlákno je najmenšia jednotka vykonávania inštrukcií v procese. Vlákna v rámci jedného procesu zdieľajú pamäť procesu, ale každé má vlastný stack a vlastný priebeh vykonávania.
3. Aký je rozdiel medzi procesom a vláknom? Proces je samostatné prostredie programu. Vlákna sú ľahšie jednotky vo vnútri procesu. Vytvorenie procesu je drahšie než vytvorenie vlákna a komunikácia medzi vláknami je jednoduchšia, lebo zdieľajú pamäť.
4. Čo je procesor? Procesor alebo CPU je celý hardvérový čip, ktorý vykonáva inštrukcie programu. Obsahuje jedno alebo viac jadier, cache a riadiacu logiku.
5. Čo je jadro procesora? Jadro je fyzická výpočtová jednotka CPU, ktorá vie vykonávať inštrukcie. Viac jadier umožňuje reálne paralelné vykonávanie viacerých úloh naraz.
6. Čo je hardvérové vlákno? Hardvérové vlákno je logická výpočtová jednotka procesora, napríklad pri SMT alebo Hyper-Threadingu. Jedno fyzické jadro môže sprístupniť dve logické vlákna, ale ich výkon nie je rovný dvom plným jadrám.
7. Čo je rozdiel medzi paralelizmom a konkurenciou? Konkurencia znamená, že viaceré úlohy napredujú súčasne z pohľadu programu. Paralelizmus znamená, že sa reálne vykonávajú naraz na viacerých jadrách.
8. Čo je sekvenčný algoritmus? Sekvenčný algoritmus vykonáva operácie po jednej, v jednom hlavnom toku vykonávania.
9. Čo je paralelný algoritmus? Paralelný algoritmus rozdelí problém na viac častí, ktoré sa vykonávajú súčasne, ak sú medzi nimi slabé alebo žiadne závislosti.
10. Aká je hierarchia program -> proces -> vlákno -> jadro CPU? Program je súbor na disku. Po spustení sa z neho stane proces. Vo vnútri procesu bežia vlákna a ich inštrukcie reálne vykonávajú jadrá procesora.
11. Je proces v RAM? Zjednodušene áno. Keď proces beží, operačný systém mu pridelí adresný priestor v pamäti, kde sú jeho dáta, kód, heap a stacky vlákien.
12. Čo znamená, že vlákno sa vykonáva na jadre? Znamená to, že konkrétne jadro CPU práve spracúva inštrukcie patriace danému vláknu. Vlákno je softvérová jednotka práce a jadro je hardvér, ktorý túto prácu vykonáva.
13. Čo obsahuje proces? Proces obsahuje najmä kód programu, dáta programu, heap, static dáta, otvorené systémové zdroje a jedno alebo viac vlákien.
14. Čo obsahuje vlákno? Vlákno obsahuje vlastný stack, registre, aktuálny stav vykonávania a informáciu, kde má pokračovať v kóde.
15. Čo je stack? Stack je pamäť určená hlavne pre lokálne premenné, parametre metód a informácie o volaniach funkcií. Každé vlákno má svoj vlastný stack.
16. Čo je heap? Heap je oblasť pamäte, kde sa ukladajú objekty a dáta vytvárané počas behu programu. V rámci jedného procesu ho môžu zdieľať viaceré vlákna.
17. Aký je rozdiel medzi stackom a heapom? Stack slúži hlavne na krátkodobé lokálne údaje konkrétneho vlákna. Heap slúži na objekty a zdieľané dáta programu, ktoré môžu žiť dlhšie.
18. Zdieľajú vlákna stack alebo pamäť procesu? Vlákna v jednom procese nezdieľajú stack. Každé má vlastný. Zdieľajú však pamäť procesu, najmä heap a ďalšie spoločné dáta.
19. Vidí proces stacky všetkých svojich vlákien? Áno. Stacky všetkých vlákien sú súčasťou pamäte procesu. Prakticky ale každý stack patrí konkrétnemu vláknu a používa ho hlavne ono.
20. Kde sú uložené údaje o plánovaní vlákien? Sú uložené v RAM, v interných dátových štruktúrach operačného systému a pri .NET aplikácii s nimi pracuje aj runtime. Sú tam napríklad stavy vlákien a údaje potrebné na prepínanie kontextu.
21. Čo je čas procesora? Čas procesora je čas, počas ktorého CPU skutočne vykonáva inštrukcie konkrétneho vlákna alebo procesu. Operačný systém ho prideľuje po malých časových úsekoch.
22. Čo je Garbage Collector? Garbage Collector je súčasť .NET runtime, ktorá automaticky uvoľňuje pamäť objektov na heape, keď na ne už neexistujú použiteľné referencie.
23. Čo je rozdiel medzi GC a Dispose?
GC uvoľňuje pamäť objektov. Dispose slúži na okamžité uvoľnenie externých zdrojov, ako sú súbory, streamy, sockety alebo databázové spojenia.
Všeobecná paralelizácia¶
24. Kedy sa oplatí paralelizovať algoritmus? Vtedy, keď je úloha výpočtovo náročná, rozdeliteľná na nezávislé časti a overhead paralelizácie je menší než získané zrýchlenie.
25. Kedy sa paralelizácia neoplatí? Pri malých úlohách, krátkych výpočtoch, silných dátových závislostiach alebo keď je program limitovaný I/O namiesto CPU.
26. Čo je overhead paralelizácie? Je to dodatočný čas navyše spôsobený plánovaním úloh, správou vlákien, synchronizáciou a komunikáciou medzi časťami programu.
27. Čo je speedup?
Speedup je pomer času sekvenčnej verzie ku času paralelnej verzie. Teda
speedup = Tsekvenčný / Tparalelný.
28. Čo je efektivita?
Efektivita vyjadruje, ako dobre sa využíva počet vlákien. Počíta sa ako
efektivita = speedup / počet vlákien.
29. Prečo efektivita klesá s rastúcim počtom vlákien? Pretože rastú režijné náklady paralelizácie a zároveň sa prejavujú limity hardvéru, napríklad pamäťová priepustnosť, cache misses alebo nerovnomerné rozdelenie práce.
30. Prečo speedup nie je lineárny? Lebo časť programu býva stále sekvenčná, pridáva sa overhead a hardvér nie je ideálny. To vystihuje aj Amdahlov zákon.
31. Čo je Amdahlov zákon? Hovorí, že maximálne zrýchlenie paralelného programu je obmedzené sekvenčnou časťou algoritmu. Aj keby sme mali nekonečne veľa vlákien, sekvenčná časť ostane úzkym hrdlom.
32. Čo je load balancing? Je to rovnomerné rozdelenie práce medzi vlákna. Ak je rozdelenie zlé, niektoré vlákna čakajú a iné sú preťažené, čím klesá výkon.
33. Čo je race condition? Je to situácia, keď výsledok programu závisí od poradia prístupu viacerých vlákien k zdieľaným dátam.
34. Čo je deadlock? Deadlock nastane, keď dve alebo viac vlákien čakajú navzájom na zdroje a program sa zablokuje.
35. Čo je starvation? Starvation znamená, že niektoré vlákno alebo úloha sa dlhodobo nevie dostať k procesoru alebo k zdroju, lebo ho neustále predbiehajú iné.
36. Čo je kritická sekcia? Je to časť kódu, kde sa pristupuje k zdieľaným dátam a musí byť chránená tak, aby do nej súčasne nevstúpilo viac vlákien, ak by to spôsobilo chybu.
C# a .NET¶
37. Prečo je C# vhodný na paralelné programovanie? Pretože .NET ponúka vysokú úroveň abstrakcie, ThreadPool, Task Parallel Library, Parallel.For, Parallel.ForEach, async/await a hotové thread-safe kolekcie.
38. Čo je Thread v C#?
Thread je nízkoúrovňová reprezentácia vlákna. Dáva veľkú kontrolu, ale dnes sa používa menej často, lebo TPL je pohodlnejšia a efektívnejšia.
39. Čo je ThreadPool? ThreadPool je skupina pripravených vlákien, ktoré .NET spravuje a používa na vykonávanie úloh bez potreby stále vytvárať nové vlákna.
40. Čo je Task?
Task je logická jednotka práce. Nie je to to isté ako fyzické vlákno. Runtime rozhoduje, na akom vlákne alebo kedy sa vykoná.
41. Aký je rozdiel medzi Thread a Task?
Thread je konkrétne vlákno, ktoré spravujem explicitne. Task je vyššia abstrakcia nad prácou, ktorú plánuje runtime, zvyčajne cez ThreadPool.
42. Čo je Task Parallel Library?
TPL je súbor knižníc v .NET na paralelné a asynchrónne spracovanie. Obsahuje napríklad Task, Parallel.For, Parallel.ForEach a súvisiace mechanizmy.
43. Na čo slúži Parallel.For? Na paralelizáciu cyklu s indexami. Vhodný je vtedy, keď viem rozdeliť iterácie na nezávislé časti.
44. Na čo slúži Parallel.ForEach? Na paralelné spracovanie kolekcie, keď pre každý prvok vykonávam podobnú nezávislú operáciu.
45. Aký je rozdiel medzi Parallel.For a Parallel.ForEach?
Parallel.For sa hodí pre rozsah indexov, Parallel.ForEach pre kolekcie a enumerovateľné zdroje.
46. Čo je PLINQ?
PLINQ je Parallel LINQ, teda paralelná verzia LINQ. Umožňuje paralelizovať dotazy nad kolekciami cez AsParallel().
47. Kedy použiť PLINQ? Keď mám dátové transformácie typu filter, mapovanie alebo agregácia a operácie nad prvkami sú nezávislé.
48. Je async/await to isté ako paralelizácia?
Nie. async/await je hlavne mechanizmus na neblokujúce asynchrónne operácie, často I/O. Neznamená automaticky využitie viacerých jadier.
49. Kedy použiť async/await a kedy Parallel.For?
async/await používam pri I/O operáciách, napríklad súbory, databáza alebo sieť. Parallel.For používam pri CPU-bound výpočtoch.
50. Čo je MaxDegreeOfParallelism?
Je to parameter, ktorým viem obmedziť maximálny počet súčasne vykonávaných paralelných úloh, napríklad v ParallelOptions.
51. Prečo by som chcel obmedziť počet vlákien? Kvôli stabilite, porovnávaniu výkonu, kontrole zaťaženia CPU, alebo keď viem, že vyšší počet už neprináša zisk.
52. Čo je lock v C#?
lock je synchronizačný mechanizmus, ktorý zabezpečí, že do kritickej sekcie vstúpi naraz len jedno vlákno.
53. Kedy použiť lock? Keď potrebujem chrániť zdieľaný stav pred súčasným prístupom viacerých vlákien.
54. Aká je nevýhoda locku? Spomaľuje program, lebo časť kódu sa vykonáva sekvenčne. Pri častom používaní sa môže stať úzkym hrdlom.
55. Čo je Mutex?
Mutex je zámok podobný locku, ale na rozdiel od neho sa dá použiť aj medzi rôznymi procesmi.
56. Aký je rozdiel medzi lock a Mutex?
lock sa používa hlavne medzi vláknami v jednom procese a je ľahší. Mutex je ťažší, ale vie synchronizovať aj viac procesov.
57. Čo je SemaphoreSlim?
SemaphoreSlim je synchronizačný mechanizmus, ktorý povoľuje vstup viacerým vláknam naraz, ale len do určeného limitu.
58. Aký je rozdiel medzi lock a SemaphoreSlim?
lock pustí dovnútra len jedno vlákno, zatiaľ čo SemaphoreSlim napríklad 2, 4 alebo iný zvolený počet.
59. Čo je Interlocked?
Interlocked poskytuje atómické operácie nad jednoduchými premennými, napríklad inkrementáciu, decrement alebo compare-exchange.
60. Kedy je lepšie použiť Interlocked namiesto lock?
Pri jednoduchých operáciách nad jednou premennou, napríklad počítadlo. Je rýchlejší než lock.
61. Čo sú concurrent kolekcie v .NET?
Sú to thread-safe kolekcie, napríklad ConcurrentDictionary, ConcurrentQueue, ConcurrentBag, ktoré umožňujú bezpečnejšiu prácu vo viacerých vláknach.
62. Čo znamená, že kolekcia je thread-safe? Znamená to, že s ňou môže bezpečne pracovať viac vlákien naraz bez toho, aby sa poškodila jej vnútorná štruktúra. Bezpečné sú najmä operácie, ktoré kolekcia sama podporuje ako synchronizované alebo atómické.
63. Čo znamená pomenovanie _counter?
Je to len pomenovanie podľa konvencie, najčastejšie pre privátne pole triedy. Na správanie programu to nemá žiadny špeciálny vplyv.
64. Kde býva zdieľaná premenná alebo objekt pre lock v C#?
Ak ide o pole objektu, býva ako súčasť objektu na heape. Ak ide o static premennú, patrí do statických dát runtime. Pri new object() sa samotný objekt vytvorí na heape a premenná drží len referenciu naň.
65. Musím pri locku použiť ten istý objekt pre všetky vlákna?
Áno. Aby lock chránil tú istú kritickú sekciu, všetky vlákna musia zamykať ten istý zdieľaný objekt.
Otázky priamo k Mandelbrotovi a tvojej prezentácii¶
66. Prečo je Mandelbrotov algoritmus vhodný na paralelizáciu? Pretože výpočet každého pixelu alebo riadku je nezávislý od ostatných. Ide teda o typický embarrassingly parallel problém.
67. Prečo si delil prácu po riadkoch a nie po jednotlivých pixeloch? Po riadkoch je rozdelenie jednoduchšie a praktické. Každé vlákno zapisuje do súvislej časti poľa, čo je dobré aj z pohľadu pamäte a cache.
68. Prečo tam netreba lock? Pretože každé vlákno zapisuje do vlastnej časti výstupného poľa. Nevzniká súčasný zápis na rovnaké miesto.
69. Čo bolo hlavným bottleneckom sekvenčnej verzie?
Samotná metóda ComputeMandelbrot, ktorá zaberala takmer celý CPU čas.
70. Prečo sa pri 12 až 16 vláknach zrýchlenie už výrazne nespomaľovalo? Lebo sa začali prejavovať limity škálovania: overhead paralelizácie, plánovanie úloh, pamäťová priepustnosť a fakt, že nie každé ďalšie vlákno prinesie rovnaký úžitok.
71. Prečo si robil warmup? Kvôli JIT kompilácii a ustáleniu výkonu. Prvé spustenie môže byť pomalšie a skresľovať benchmark.
72. Prečo si porovnával medián a nie len jeden beh? Lebo jednotlivé behy môžu kolísať. Medián je odolnejší voči odľahlým hodnotám a lepšie reprezentuje typický výkon.
73. Prečo nie je pri menšom rozlíšení efektivita taká dobrá? Lebo problém je menší, takže overhead paralelizácie tvorí väčšiu časť celkového času.
74. Prečo pri vyššom rozlíšení paralelizácia funguje lepšie? Lebo je tam viac práce na rozdelenie, takže sa lepšie amortizujú režijné náklady paralelizácie.
75. Prečo si použil Parallel.For a nie explicitné vytváranie threadov?
Lebo Parallel.For je jednoduchší, prehľadnejší, lepšie využíva ThreadPool a znižuje potrebu ručnej správy vlákien.
76. Čo by sa dalo na projekte zlepšiť? Mohlo by sa spraviť detailnejšie profilovanie, testovanie s rôznymi stratégiami chunkovania práce, prípadne GPU akcelerácia alebo SIMD optimalizácia.
Krátke „záludné“ otázky, ktoré sa môžu objaviť¶
77. Znamená 16 vlákien automaticky 16-násobné zrýchlenie? Nie. Ideálne lineárne zrýchlenie je v praxi veľmi zriedkavé.
78. Je vyšší počet vlákien vždy lepší? Nie. Po určitom bode už výkon rastie len minimálne alebo sa môže dokonca zhoršiť.
79. Môže byť paralelný program pomalší než sekvenčný? Áno. Ak je úloha malá alebo je overhead veľký, paralelná verzia môže byť horšia.
80. Je Task vždy spustený na novom vlákne? Nie. Task je len logická úloha. Runtime rozhoduje, kde a ako sa vykoná.
81. Je async vhodný na zrýchlenie CPU výpočtov?
Nie priamo. Na CPU-bound úlohy sa používa skôr paralelizácia cez TPL, nie samotné async/await.