Your SlideShare is downloading. ×
Евгений Кирпичёв   Многопоточное программирование
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Евгений Кирпичёв Многопоточное программирование

291

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
291
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
1
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Ìíîãîïîòî÷íîå ïðîãðàììèðîâàíèå Êîððåêòíîñòü, ïàòòåðíû, ïîäõîäû Åâãåíèé Êèðïè÷¼â 24 ñåíòÿáðÿ 2010 ã.
  • 2. Öåëü äîêëàäà Ðàñøèðèòü êðóãîçîð â îáëàñòè ìíîãîïîòî÷íîãî ïðîãðàììèðîâàíèÿ âîîáùå. Êîððåêòíîñòü Êàê ñôîðìóëèðîâàòüD ïîâûñèòüD ãàðàíòèðîâàòü Èíñòðóìåíòû Ïàòòåðíû è âåëîñèïåäû Ïîäõîäû è ôèøêè ðàçíûõ ÿçûêîâ
  • 3. Êëàññèôèêàöèÿ ìíîãîïîòî÷íûõ ïðîãðàìì Parallelism vs Concurrency Parallel Îäíà çàäà÷à áüåòñÿ íà ìíîãî ÷àñòåé Concurrent Ìíîãî ðàçíûõ çàäà÷ (ñëîæíåå) Ñåãîäíÿ â îñíîâíîì î concurrency.
  • 4. ×àñòü 1. Êîððåêòíîñòü.
  • 5. Ñîäåðæàíèå Êîððåêòíîñòü Ïðè÷èíû áàãîâ Äîêàçàòåëüñòâî êîððåêòíîñòè Óëó÷øåíèå êîððåêòíîñòè Ïàòòåðíû è ïîäõîäû Ïàðàëëåëèçì Concurrency Cutting edge Haskell Erlang .NET Clojure Çàêëþ÷åíèå
  • 6. Ïðè÷èíû áàãîâ Êîðåíü âñåõ çîë èçìåíÿåìîå âî âðåìåíè ñîñòîÿíèå. N íèòåé, K ñîñòîÿíèé ⇒ O(KN) ïåðåïëåòåíèé Ïðîìåæóòî÷íûå ñîñòîÿíèÿ âèäèìû Äàæå âûçîâ ìåòîäà ýòî áîëüøå íå ÷åðíûé ÿùèê Åãî òåëî áîëüøå íå àòîìàðíî Êîððåêòíûå ìíîãîïîòî÷íûå ïðîãðàììû íå ìîäóëüíû ƒequenti—ly ™orre™t + ƒequenti—lly ™orre™t = gon™urrently ™orre™t
  • 7. Ïðè÷èíû áàãîâ Sequentialy correct + Sequentially correct = Concurrently correct
  • 8. Äîêàçóåìàÿ êîððåêòíîñòü Face it: Ïðîãðàììà íå áûâàåò ¾ïî÷òè êîððåêòíà¿. Ïóñòü âåðîÿòíîñòü áàãà 10−8 109 âûçîâîâ çà íåäåëþ è âåðîÿòíîñòü 1 − e−10 ≈ 1 Ïðè íåïðåðûâíîì òåñòèðîâàíèè îøèáêà òîæå âñïëûâåò òîëüêî ÷åðåç íåäåëþ Ðàáîòàåò èäåàëüíî (äîêàçóåìî) èëè íå ðàáîòàåò âîîáùå
  • 9. Äîêàçóåìàÿ êîððåêòíîñòü Face it: Ëèáî ïðîãðàììà äîêàçóåìî êîððåêòíà Ëèáî îíà, ïî÷òè íàâåðíÿêà, íåêîððåêòíà Tony Hoare: There are two ways of constructing a software design. One way is to make it so simple that there are obviously no deciencies, and the other way is to make it so complicated that there are no obvious deciencies. The rst method is far more dicult.
  • 10. Ôîðìàëüíûå ìåòîäû Ïðèìåíÿòü íå îáÿçàòåëüíî.
  • 11. Ôîðìàëüíûå ìåòîäû À çà÷åì òîãäà îíè âîîáùå íóæíû? ×òîáû îïèñûâàòü ñèñòåìó ïîëóôîðìàëüíî ×òîáû ÷óÿòü: ôîðìàëèçóåìà ëè ñèñòåìà â ïðèíöèïå? Åñëè íåò @ñèñòåìà ñëèøêîì çàïóòàíàA î êîððåêòíîñòè ìîæíî çàáûòüF
  • 12. Ôîðìàëüíûå ìåòîäû Ìîé îïûò: äîñòàòî÷íî ïîïûòàòüñÿ ôîðìàëèçîâàòü ñèñòåìó: Âñïëûâàþò ïðîòèâîðå÷èÿ, íåäîãîâîðêè â òðåáîâàíèÿõ Âûäåëÿþòñÿ êîìïîíåíòû áåç ÷åòêîé ñïåöèôèêàöèè ÁëàæåíD êòî âåðóåòD ÷òî îíè ” è òàê“ ðàáîòàþò
  • 13. Ôîðìàëüíûå ìåòîäû ×òî æå ýòî çà ìåòîäû? Íàïðèìåð, ëèíåéíàÿ òåìïîðàëüíàÿ ëîãèêà.
  • 14. ×òî òàêîå LTL Ëèíåéíàÿ òåìïîðàëüíàÿ ëîãèêà ñïîñîá ðàññóæäàòü î ïîñëåäîâàòåëüíîñòÿõ ñîáûòèé. Ïðîãðàììà ìîäåëèðóåòñÿ àâòîìàòîì ( ” ñòðóêòóðîé Êðèïêå“). Èññëåäóþòñÿ âîçìîæíûå ïîñëåäîâàòåëüíîñòè ñîñòîÿíèé.
  • 15. Çà÷åì LTL â ýòîì äîêëàäå ×òîáû ëó÷øå ôîðìóëèðîâàòü ñâîéñòâà ñâîèõ ïðîãðàìì. ×òîáû, â êðàéíåì ñëó÷àå, ñóìåòü èõ äîêàçàòü. Âðó÷íóþ Èëè èíñòðóìåíòàìè
  • 16. Ñòðóêòóðà Êðèïêå Ñòðóêòóðà Êðèïêå ≈ ãðàô ñîñòîÿíèé. Ìíîæåñòâî ñîñòîÿíèé Íåêîòîðûå íà÷àëüíûå Íåêîòîðûå ñîåäèíåíû ïåðåõîäîì Ïåðåõîä áåçóñëîâíûé Ìíîæåñòâî ôàêòîâ  êàæäîì ñîñòîÿíèè âåðíû íåêîòîðûå ôàêòû.
  • 17. Ñòðóêòóðà Êðèïêå Ìèêðîâîëíîâêà.
  • 18. Ñòðóêòóðà Êðèïêå Ïåðåõîäû íå ïîäïèñàíû, ïîòîìó ÷òî: Íîìåð ñîñòîÿíèÿ ïîëíîñòüþ îïèñûâàåò ñîñòîÿíèå ïðîãðàììû Åñëè ïåðåõîä óñëîâíûé íàäî ïîäåëèòü ñîñòîÿíèå íà äâà ÒîD â êîòîðîì óñëîâèå âåðíî @ïåðåõîä ìîæåò ïðîèçîéòèA ÒîD â êîòîðîì óñëîâèå íåâåðíî @ïåðåõîä íå ìîæåò ïðîèçîéòèA Ïðîãðàììó ìîæíî ñòðàíñëèðîâàòü â ñòðóêòóðó Êðèïêå Ñòðóêòóðû Êðèïêå ïðåêðàñíî ïîääàþòñÿ âåðèôèêàöèè
  • 19. LTL Ëèíåéíàÿ òåìïîðàëüíàÿ ëîãèêà (Linear Temporal Logic). Ðàññóæäàåò î ïîñëåäîâàòåëüíîñòÿõ ñîñòîÿíèé ìèðà âî âðåìåíè. Åñòü çàïðîñ ⇒ êîãäà-íèáóäü áóäåò îòâåò Áëîêèðîâêà çàïðîøåíà ⇒ êëèåíò áóäåò îáñëóæåí ñêîëü óãîäíî áîëüøîå ÷èñëî ðàç, ïîêà íå îòïóñòèò åå . . . Ïðåëåñòè: Êðàòêàÿ, ïîíÿòíàÿ, ìîùíàÿ è îäíîçíà÷íàÿ LTL-ñâîéñòâà ëåãêî âåðèôèöèðóþòñÿ äàæå âðó÷íóþ Îòíîñèòåëüíî ñòðóêòóð Êðèïêå Ìíîãî ìîùíûõ èíñòðóìåíòîâ
  • 20. Ôîðìóëû LTL p1, p2, . . . Ïåðåìåííûå A ∧ B, ¬A. . . Ëîãè÷åñêèå ñâÿçêè XA  ñëåäóþùèé ìîìåíò A (neXt) GA ≡ A Âñåãäà A (Globally) FA ≡ ♦A Êîãäà-íèáóäü A (Future) AUB A, ïî êðàéíåé ìåðå äî íàñòóïëåíèÿ B
  • 21. Áåñêîíå÷íîñòè Íà÷èíàÿ ñ íåêîòîðîãî ìîìåíòà, íàâñåãäà: FG A ≡ ♦ A Áåñêîíå÷íî ÷àñòî: GF A ≡ ♦A
  • 22. Èëëþñòðàöèÿ ôîðìóë LTL
  • 23. Ñâîéñòâà ìíîãîïîòî÷íûõ ïðîãðàìì Åñòü ðÿä î÷åíü ÷àñòî âñòðå÷àþùèõñÿ ñâîéñòâ. Ýòî ïðîñòî òåðìèíîëîãèÿ. Íî òåðìèíîëîãèÿ âàæíà. Êàê îíè íàçûâàþòñÿ? Êàê îíè ôîðìóëèðóþòñÿ â LTL?
  • 24. Ñâîéñòâà Æèâîñòü (liveness) ×òîEòî õîðîøåå êîãäàEíèáóäü ïðîèçîéäåòX ♦Alive Çàäàíèå êîãäàEíèáóäü íà÷íåòñÿ Áåçîïàñíîñòü (safety) ×òîEòî ïëîõîå íèêîãäà íå ïðîèçîéäåòX ¬Dead Çàäàíèå íèêîãäà íå ïîòåðïèò êðàõ
  • 25. Ñâîéñòâà Ñïðàâåäëèâîñòü (fairness) Òî, ÷òî ìîæåò ïðîèçîéòè ïðîèçîéäåò Ñëàáàÿ: ♦ Req → ♦Ack Ðåñóðñ çàïðîøåí @è îñòàåòñÿ çàïðîøåííûìA → êîãäàEíèáóäü áóäåò âûäàí Ñèëüíàÿ: ♦Req → ♦Ack Íèòü áåñêîíå÷íî ìíîãî ðàç èñïîëíèìà @èìååò íå ñàìûé íèçêèé ïðèîðèòåò èç íåáëîêèðîâàííûõA → êîãäàEíèáóäü ïîëó÷èò êâàíò Àíòîíèì starvation (ãîëîäàíèå)
  • 26. Ïðèìåðû LTL-ñâîéñòâ Óñòðîéñòâî íå âûêëþ÷àåòñÿ ñàìî ïî ñåáå (isOn → (isOn U (turnOPressed ∨ noBattery)) Íå ðåæå ÷åì ðàç â 5 òàêòîâ âêëþ÷àåòñÿ êîíòðîëëåð äâèãàòåëÿ ¬F5(activeThread = ENGINE_CONTROLLER)
  • 27. Model checking Íàóêà î ïðîâåðêå ñâîéñòâ ïðîãðàìì (íàïðèìåð, LTL) íà îñíîâå èõ ìîäåëåé (íàïðèìåð, ñòðóêòóð Êðèïêå) Model checking. Ïðåìèÿ Òüþðèíãà 2007 çà äîñòèæåíèÿ â îáëàñòè model checking, ñäåëàâøèå åãî ïðèìåíèìûì äëÿ ïðîåêòîâ ðåàëüíîãî ðàçìåðà.
  • 28. Èíñòðóìåíò: SPIN Ïîâñåìåñòíî èñïîëüçóåìûé ÿçûê + âåðèôèêàòîð LTL-ñâîéñòâ äëÿ ìíîãîçàäà÷íûõ ñèñòåì. Ëàóðåàò ACM Software System award (2001) (äðóãèå ëàóðåàòû: Unix, TeX, Java, Apache, TCP/IP, . . . ). Ñè-ïîäîáíûé ñèíòàêñèñ Äëÿ íàðóøåííûõ ñâîéñòâ ãåíåðèðóåòñÿ íàðóøàþùàÿ èõ òðàññà (óðîäëèâûé, íî òåðïèìûé) GUI ß ïðîâåðÿë: Ïðèãîäíî äëÿ ïðèìåíåíèÿ íà ïðàêòèêå. http://spinroot.com/spin/whatispin.html îôèöèàëüíûé ñàéòF
  • 29. AspectJ+LTL http://www.sable.mcgill.ca/~ebodde/rv/JLO/ tEvyX ïðîâåðÿåò v„vEñâîéñòâà â ðàíòàéìå @çàáðîøåíAF http://abc.comlab.ox.ac.uk/extensions „r—™e™he™kX ïðîäîëæåíèåD îò òåõ æå àâòîðîâX ïðîâåðÿåò ðåãóëÿðíûå âûðàæåíèÿ íàä òðàññàìè ïðîãðàììûF
  • 30. Model checking:further reading http://www.inf.unibz.it/~artale/FM/slide3.pdf Òóòîðèàë ïî v„vF http: //citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.60.3062 Ñòàòüÿ ïðî tEvy http://spinroot.com/spin/Doc/course/mc-tutorial.pdf wodel ghe™kingX e tutori—l overview @ìíîãî ññûëîêA Êàðïîâ ÞF ÃF wodel ™he™king @ïðîäàåòñÿ â ìàãàçèíàõAF http://savenkov.lvk.cs.msu.su/mc.html Èíòåðåñíûé êóðñ â ÌÃÓ @‡s€AF
  • 31. Java Path Finder Âèðòóàëüíàÿ ìàøèíà, óìåþùàÿ ñèìâîëüíî âûïîëíÿòü Java-êîä è âåðèôèöèðîâàòü ñâîéñòâà äëÿ âñåõ âîçìîæíûõ çàïóñêîâ ñ ó÷åòîì ìíîãîïîòî÷íîñòè. Ñäåëàíî â NASA. http://javapathfinder.sourceforge.net/ http://sourceforge.net/projects/visualjpf/ q…s http://www.visserhome.com/willem/presentations/ ase06jpftut.ppt ïîäîáèå òóòîðèàëà ÓòâåðæäàåòñÿD ÷òî ñïðàâëÿåòñÿ ñ ïðîåêòàìè äî IHuvygF Íàõîäèë áàãè â xeƒeEîâñêîì ñîôòå @â ìàðñîõîäåD íàïðèìåðA Îñíîâàí íà ƒ€sx Åñòü —ntEt—sk è ïëàãèí ê e™lipseY ðàñøèðÿåì ß íàïèñàë ìàëåíüêèé ïðèìåð ñ äåäëîêîìF ÑðàáîòàëîF
  • 32. Ôèëîñîôñêîå èçáàâëåíèå îò áàãîâ Íàäî óìåíüøèòü O(KN). Óìåíüøèòü ÷èñëî íàáëþäàåìûõ ñîñòîÿíèé (K) smmut—˜ility Èíêàïñóëÿöèÿ ñîñòîÿíèÿ Âûñîêîóðîâíåâûå îïåðàöèè Ôàêòîðèçàöèÿ Ñèíõðîíèçàöèÿ Íàâÿçàòü òðàññàì ýêâèâàëåíòíîñòü Èäåìïîòåíòíûå îïåðàöèè foo();foo(); ∼ foo(); Êîììóòàòèâíûå @íåçàâèñèìûåA îïåðàöèè foo();bar(); ∼ bar();foo();  ò.÷. èíêàïñóëÿöèÿ è íåçàâèñèìûå îáúåêòû Ñ÷èòàòü áîëüøåå ÷èñëî òðàññ êîððåêòíûìè (îñëàáèòü òðåáîâàíèÿ)
  • 33. Immutability Íåëüçÿ èçìåíèòü âîîáùå ⇒ íåëüçÿ èçìåíèòü íåïðàâèëüíî, íå â òîì ïîðÿäêå . . . Äîëæíà ñîáëþäàòüñÿ ðåêóðñèâíî ïî ïîëÿì îáúåêòà è ïî öåïî÷êå íàñëåäîâàíèÿ â îáå ñòîðîíû.
  • 34. Èíêàïñóëÿöèÿ ñîñòîÿíèÿ Ïðîãðàììà êîððåêòíà ðîâíî íàñòîëüêî, íàñêîëüêî êîððåêòíû è ñêîîðäèíèðîâàíû âñå, êòî ìîãóò ïîâëèÿòü íà ñîñòîÿíèå îáúåêòà. Ìîðàëü: ×åì ìåíüøå ñïîñîáîâ ïîâëèÿòü íà ñîñòîÿíèå, òåì ëó÷øå. Ìàëî êîìó äàâàòü ê íåìó äîñòóï Ìàëî êîãî íàäî áóäåò êîîðäèíèðîâàòü Äàâàòü äîñòóï â òåðìèíàõ ìàëîãî ÷èñëà âûñîêîóðîâíåâûõ îïåðàöèé Ìàëî êîìáèíàöèé îïåðàöèé íàäî ðàññìàòðèâàòü Ìåíüøå íàðóøàåòñÿ öåëîñòíîñòü ìåæäó îïåðàöèÿìè
  • 35. Âûñîêîóðîâíåâûå îïåðàöèè Îïðåäåëåíèå: Âûñîêîóðîâíåâàÿ îïåðàöèÿ îïåðàöèÿ, íå íàðóøàþùàÿ öåëîñòíîñòü ñèñòåìû. AtomicInteger.getAndIncrement ConcurrentMap.putIfAbsent Bank.transfer Äîñòàòî÷íî ïðàâèëüíî ðåàëèçîâàòü ñàìó îïåðàöèþ. Ïðîåêòèðóéòå API â òàêîì ñòèëå, åñëè ýòî âîçìîæíî.
  • 36. Âûñîêîóðîâíåâûå îïåðàöèè ×àñòíûé ñëó÷àé: Ó îáúåêòà â ìåðó áîëüøîå ñîñòîÿíèå Õî÷åòñÿ àòîìàðíî ïîìåíÿòü íåñêîëüêî åãî ÷àñòåé Çàïèõíèòå ñîñòîÿíèå â îáúåêò è ïîìåíÿéòå àòîìàðíî ññûëêó íà ýòîò îáúåêò AtomicReference ×èñòî ôóíêöèîíàëüíûå ñòðóêòóðû äàííûõ âñåãäà ïîòîêîáåçîïàñíû http://tobega.blogspot.com/2008/03/ java-thread-safe-state-design-pattern.html ÑìFòæF yk—s—kiD €urely fun™tion—l d—t— stru™turesF
  • 37. Ôàêòîðèçàöèÿ Ïðîãðàììà êîððåêòíà ðîâíî íàñòîëüêî, íàñêîëüêî êîððåêòíû è ñêîîðäèíèðîâàíû âñå, êòî ìîãóò ïîâëèÿòü íà ñîñòîÿíèå îáúåêòà. Ìîðàëü: Íåçàâèñèìûå àñïåêòû ñîñòîÿíèÿ âûíîñèòü â íåçàâèñèìûå îáúåêòû. Ñëîæíîñòü ïàäàåò ñ (K1 + K2)N äî KN 1 + KN 2 (áðåä, íî ñóòü ïðèìåðíî òàêàÿ).
  • 38. Ôàêòîðèçàöèÿ class DataLoader { ClientToken beginLoad(Client client); void writeData(ClientToken token, Data data); void commit(ClientToken token); void rollback(ClientToken token); }
  • 39. Ôàêòîðèçàöèÿ Ãðÿçíûé êîä: Òàáëèöà ClientToken/òðàíçàêöèÿ (ìíîãîïîòî÷íûå êëèåíòû) synchronized(locks.get(token)) Îáå òàáëèöû íàäî òîæå îõðàíÿòü
  • 40. Ôàêòîðèçàöèÿ Ðàçîðâåì ëèøíþþ çàâèñèìîñòü ìåæäó íåçàâèñèìûìè çàäà÷àìè. class DataLoader { PerClientLoader beginLoad(Client client); } class PerClientLoader { void writeData(Data data); void commit(); void rollback(); }
  • 41. Ôàêòîðèçàöèÿ Ïðîñòîé è íåçàãðÿçíåííûé êîä Ñèíõðîíèçàöèÿ ïðîñòûì synchronized Íèêàêèõ òàáëèö Íèêàêèõ ïðîáëåì ñ îõðàíîé òàáëèö îò ìíîãîïîòî÷íîãî äîñòóïà
  • 42. Îñëàáëåíèå òðåáîâàíèé Èíîãäà îáåñïå÷èòü æåñòêèå èíâàðèàíòû öåëîñòíîñòè íåâîçìîæíî. Îíè ìîãóò íàðóøàòüñÿ èçâíå Åñòü âíåøíèå ïðîöåññûD íàðóøàþùèå öåëîñòíîñòü Îíè íàì íå ïîäêîíòðîëüíû ÍàïðèìåðX ñèíõðîíèçàöèÿ ôàéëîâD èçìåíÿåìûõ âíåøíèìè ïðîöåññàìè Èõ ñëèøêîì äîðîãî ïîääåðæèâàòü ÍàïðèìåðD áîëüøàÿ ðàñïðåäåëåííàÿ ñèñòåìà Ñèíõðîííîå ïðîòàëêèâàíèå èçìåíåíèÿ íà âñå ðåïëèêè ñëèøêîì äîëãî Ñ ó÷åòîì ïàäåíèé óçëîâ âñå åùå õóæå Ëåíü ïèñàòü ñëîæíûé êîä :)
  • 43. Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü Ñóäÿ ïî âñåìó, îäèí èç ìîùíåéøèõ ïðèåìîâ ïðîåêòèðîâàíèÿ íåêîòîðûõ êëàññîâ ìíîãîçàäà÷íûõ ñèñòåì. Îíà æå ¾eventual consistency¿. Ñóòü: ” Ñîñòîÿíèå ñèñòåìû âñåãäà öåëîñòíî“ î÷åíü òðóäíî è íå âñåãäà íóæíî. ” Ñîñòîÿíèå ñèñòåìû âñå öåëîñòíåå è öåëîñòíåå“ ëåãêî îáåñïå÷èòü, ÷àñòî äîñòàòî÷íî. Äåëàåì ñèñòåìó ëèøü ñòðåìÿùåéñÿ ê ñîñòîÿíèþ öåëîñòíîñòè.
  • 44. Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü Ïðèìåð ñòðóêòóðû: Ñèñòåìà ïåðèîäè÷åñêè ïðîñûïàåòñÿ è îñìàòðèâàåòñÿ Âû÷èñëÿåò, ÷åì ìèð îòëè÷àåòñÿ îò ” èäåàëà“ ÊàêèåEòî äàííûå ñ ÷åìEòî íå ñîãëàñîâàíû ÊàêèåEòî ãîòîâûå ê îáðàáîòêå äàííûå åùå íå îáðàáàòûâàþòñÿ ÊàêèåEòî äàííûå îáðàáàòûâàþòñÿ óæå ñëèøêîì äîëãîY íàâåðíîåD îáðàáîò÷èê óìåð F F F Âûïîëíÿåò äåéñòâèÿ.
  • 45. Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü Ïëþñû ïîäõîäà ” ñèñòåìà êàê ñõîäÿùèéñÿ ïðîöåññ“: Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü Ïîñëåäñòâèÿ áîëüøèíñòâà ïðîáëåì ðàíî èëè ïîçäíî èñ÷åçíóòF Âûñîêàÿ ìîäóëüíîñòü Ñèñòåìà ðàñïàäàåòñÿ íà íàáîð ÷èñòî ëèíåéíûõ àâòîìàòîâE ” îáðàáîò÷èêîâ“F Î÷åíü ïðîñòàÿ îòëàäêà è òåñòèðîâàíèå Åñëè ÷òîEòî íå òàê ñèñòåìà ïðîñòî ïðèíÿëà íåïðàâèëüíîå ðåøåíèå â îäíîì èç ñîñòîÿíèéF ÌîæåòD ñàìî ðàññîñåòñÿD ìîæíî íå ôèêñèòü
  • 46. Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü Âûñîêàÿ óñòîé÷èâîñòü Ñèñòåìà íåóÿçâèìà äëÿ ” ñìåðòåëüíûõ“ áàãîâ @™orrupted ñèíãëòîíûD óòå÷êè ðåñóðñîâAF Ñäåëàòü ñîñòîÿíèå persistentD ïåðåçàïóñêàòü ïðîöåññF Ãîòîâíîñòü ê ðàñïðåäåëåííîé ðàáîòå Ñäåëàòü ñîñòîÿíèå ãëîáàëüíî âèäèìûì è îáåñïå÷èòü ïðîñòåéøóþ áëîêèðîâêóF
  • 47. Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü Ïðèìåíèìîñòü: Dataow-like çàäà÷è (äàííûå òåêóò ïî ñèñòåìå ñ ðÿäîì ýòàïîâ îáðàáîòêè) Ðåïëèêàöèÿ è ñèíõðîíèçàöèÿ Àðáèòðàæ ðåñóðñîâ è load balancing . . .
  • 48. Further reading http://www.webperformancematters.com/journal/2007/8/ 21/asynchronous-architectures-4.html î ìàñøòàáèðîâàíèè â em—zonF Î÷åíü ïîëåçíûå ñîâåòûF http://www.infoq.com/interviews/ dan-pritchett-ebay-architecture î ìàñøòàáèðîâàíèè â ef—y http://roc.cs.berkeley.edu/ Èññëåäîâàòåëüñêèé ïðîåêò ‚e™overyEyriented gomputing Áîðîòüñÿ ñ ïîñëåäñòâèÿìè îøèáîêD ïîñêîëüêó èñêîðåíèòü âñå ïðè÷èíû íåâîçìîæíî Íåñêîëüêî îñíîâíûõ ïðèíöèïîâ @èçîëÿöèÿD èçáûòî÷íîñòüD undoD ñàìîäèàãíîñòèêàD ïåðåçàïóñêàåìîñòüA Î÷åíü ðàçóìíîD åñëè ïîäóìàòüF
  • 49. Àáñòðàãèðîâàíèå Ìíîãîïîòî÷íóþ ïðîãðàììó íàìíîãî ëåã÷å íàïèñàòü è îòëàäèòü, åñëè â íåé íåò íè÷åãî, êðîìå ñàìîé ñóòè. Áàãè âûëåçàþò íà ïîâåðõíîñòü, íåò ñîáëàçíà ñêàçàòü  íàøåé çàäà÷å òàêàÿ ñèòóàöèÿ íåâîçìîæíà. Àëãîðèòìû ëåã÷å îòëàæèâàòü ïî îòäåëüíîñòè. Íå áëîêèðîâêà èíäåêñà íà ÷òåíèå èëè çàïèñü, à ïðîñòî áëîêèðîâêà íà ÷òåíèå èëè çàïèñü Íå î÷åðåäü e-mail'îâ, à îòêàçîóñòîé÷èâàÿ î÷åðåäü çàäà÷ Íå ïàðàëëåëüíûé ïîäñ÷åò ñëîâ, à MapReduce Íå ïàðàëëåëüíàÿ ôèëüòðàöèÿ ìàññèâà, à ParallelArray Ìîæåò îêàçàòüñÿ, ÷òî òàêàÿ øòóêà óæå åñòü.
  • 50. Àáñòðàãèðîâàíèå À êàêèå øòóêè óæå åñòü? Îá ýòîì ïîçæå.
  • 51. Àáñòðàãèðîâàíèå: ïðèìåð Ïðèâÿçêà ê âíåøíåé ñèñòåìå ñêà÷èâàíèÿ óðëîâ. Çàäàíèÿ ïèøóòñÿ â ôàéëû Âíåøíÿÿ ñèñòåìà èõ ïîäõâàòûâàåò Îòâåòû òîæå ïèøóòñÿ â ôàéëû Íàäî ïðåäîñòàâèòü àñèíõðîííûé API void loadPage(url, onOk, onError)
  • 52. Àáñòðàãèðîâàíèå: ïðèìåð Devil in the details: Íå çàôëóäèòü ñèñòåìó (áëîêèðîâàòüñÿ, åñëè ìíîãî çàäàíèé ” â ïîëåòå“) Ñëåäèòü çà òàéìàóòàìè (äîëãî íå îòâå÷àåò → onError) Íå äîïóñêàòü ãîíîê ìåæäó îòâåòàìè è òàéìàóòàìè Áåðå÷ü íèòêó ñëåæåíèÿ çà îòâåòàìè (âûçûâàòü onOk,onError â îòäåëüíûõ íèòÿõ) Îáðàáàòûâàòü ðåäèðåêòû
  • 53. Àáñòðàãèðîâàíèå: ïðèìåð Áûëî: Íåòåñòèðóåìàÿ êàøà, äåëàþùàÿ âñå ñðàçó.
  • 54. Àáñòðàãèðîâàíèå: ïðèìåð Ñòàëî: Ñåìàôîð äëÿ îãðàíè÷åíèÿ ÷èñëà çàäàíèé ” â ïîëåòå“ Àáñòðàêòíûé ” áàò÷åð“ Àáñòðàêòíûé ” ïîëëåð“ Àáñòðàêòíûé ” òàéìàóòåð“ Âñ¼ ýëåìåíòàðíî òåñòèðóåòñÿ (íàøëèñü áàãè) Âñ¼ ïîëåçíî è ïîâòîðíî èñïîëüçóåìî
  • 55. Àáñòðàãèðîâàíèå: ïðèìåð class BatcherT { Batcher(int periodMs); Stoppable start(); abstract void flush(T[] ts); void submit(T t); }
  • 56. Àáñòðàãèðîâàíèå: ïðèìåð class PollerT { Poller(int periodMs); Stoppable start(); abstract @Nullable T poll(); abstract void process(@NotNull T t); }
  • 57. Àáñòðàãèðîâàíèå: ïðèìåð class TimeouterT { Poller(int periodMs); Stoppable start(); void submit(T t, int timeoutMs); abstract void onTimedOut(T t); }
  • 58. Àáñòðàãèðîâàíèå: ïðèìåð Èòîã: Èç áèçíåñ-ëîãèêè ïîëíîñòüþ ïðîïàë ìíîãîïîòî÷íûé êîä.
  • 59. ×àñòü 2. Ïàòòåðíû è ïîäõîäû.
  • 60. Ñîäåðæàíèå Êîððåêòíîñòü Ïðè÷èíû áàãîâ Äîêàçàòåëüñòâî êîððåêòíîñòè Óëó÷øåíèå êîððåêòíîñòè Ïàòòåðíû è ïîäõîäû Ïàðàëëåëèçì Concurrency Cutting edge Haskell Erlang .NET Clojure Çàêëþ÷åíèå
  • 61. Ìîäåëè ìíîãîïîòî÷íûõ âû÷èñëåíèé Ïàðàëëåëèçì: MapReduce: Îãðîìíûå îáúåìû äàííûõ, ðàñïðåäåëåííàÿ îáðàáîòêà Fork/Join: Çàäà÷è ñ ðåêóðñèâíîé ñòðóêòóðîé Âåêòîðíûå ìîäåëè: huge-scale SIMD Êîíâåéåð / data ow . . . Concurrency: Message-passing (actor model) Event loop (message-passing ñ îäíèì / íåñêîëüêèìè îäèíàêîâûìè àêòîðàìè) ÑåðâåðàD áîëüøèíñòâî q…sEáèáëèîòåêD â òF÷F ƒwing Software Transactional Memory Àñèíõðîííîå ïðîãðàììèðîâàíèå
  • 62. MapReduce Ñëèøêîì èçâåñòíî, ÷òîáû íà íåì îñòàíàâëèâàòüñÿ Ðåàëèçàöèÿ äëÿ Java: Hadoop
  • 63. Fork/join Ïîõîæå íà MapReduce. Fork: ïîäåëèòü íà òàêèå æå çàäà÷è, íî ïîìåíüøå Âûïîëíèòü ïîäçàäà÷è ïàðàëëåëüíî Join: Ñëèòü ðåçóëüòàòû ïîäçàäà÷ Ïðèìåðû: Øàõìàòû: fork âîçìîæíûå õîäû, join âûáîð ëó÷øåãî Óìíîæåíèå ìàòðèö: fork ðàçáèåíèå ïî ñòðîêàì/ñòîëáöàì, join NOP Èíòåãðèðîâàíèå: fork ðàçáèåíèå îáëàñòè, join ñëîæåíèå
  • 64. Âåêòîðíûå àëãîðèòìû Huge-scale SIMD: Ïðèìèòèâíûå îïåðàöèè îïåðèðóþò ñðàçó íàä áîëüøèìè ìàññèâàìè. Ñàìîå òî äëÿ GPU. Map: Ïðèìåíåíèå ôóíêöèè ê êàæäîìó ýëåìåíòó / ñêëåéêà N ìàññèâîâ ïî N-àðíîé îïåðàöèè Fold: Àññîöèàòèâíàÿ ñâåðòêà â ìîíîèäå. àññîöèàòèâíà: a (b c) = (a b) c u åäèíèöà : a u = u a = a fold u [x0, x1, . . . , xn] = u x0 x1 . . . xn Scan (Prex sum): Ïðîáåã (Ïðåôèêñíàÿ ñóììà) scan u [x0, x1, . . . , xn] = [u, u x0, u x0 x1, . . . , u . . . xn]
  • 65. Âåêòîðíûå ìîäåëè Ïðåëåñòè: Ñâåðòêà ïàðàëëåëèçóåòñÿ: Óñêîðåíèå O(P/log P) íà P ïðîöåññîðàõ (â log P ðàç õóæå ëèíåéíîãî) Ïðîáåã òàê æå ïàðàëëåëèçóåòñÿ Óäèâèòåëüíî ìîùíûå è óíèâåðñàëüíûå îïåðàöèè
  • 66. Ïðåôèêñíûå ñóììû ×òî ìîæíî ñäåëàòü ñâåðòêîé/ïðîáåãîì (ò.å. ïàðàëëåëüíî): sum,min,max,avg,. . . Radix sort, Quicksort Ñëîæåíèå äëèííûõ ÷èñåë Âûïóêëàÿ îáîëî÷êà Ìíîãèå àëãîðèòìû íà ãðàôàõ Ìíîãèå ðåêóððåíòíûå ïîñëåäîâàòåëüíîñòè n-ãî ïîðÿäêà Òðåõäèàãîíàëüíûå ñèñòåìû óðàâíåíèé . . .
  • 67. Ïðåôèêñíûå ñóììû Îñîáåííî èíòåðåñíî, êàê ýòî äåëàåòñÿ. Áàçîâûå îïåðàöèè ïîâåðõ ïðîáåãà: Ðåêóððåíòíàÿ ïîñëåäîâàòåëüíîñòü 1ãî ïîðÿäêà Óïàêîâêà ìàññèâà Ñîðòèðîâêà ìàññèâà ïî 1-áèòíîìó ôëàãó (ðàçáèåíèå) Ñåãìåíòèðîâàííûé ïðîáåã (ïðîáåã ñî ñáðîñàìè)
  • 68. Ïðåôèêñíûå ñóììû Óïàêîâêà ìàññèâà (pack, lter).
  • 69. Ïðåôèêñíûå ñóììû Ñîðòèðîâêà ïî 1-áèòíîìó ôëàãó (ðàçáèåíèå, partition). Radixsort òðèâèàëåí.
  • 70. Ïðåôèêñíûå ñóììû Ñåãìåíòèðîâàííûé ïðîáåã (Segmented scan). Ïîçâîëÿåò ðåàëèçîâàòü ðåêóðñèþ áåç ðåêóðñèè.
  • 71. Ïðåôèêñíûå ñóììû  öåëîì êðàñèâûé, ìîùíûé, ïðîñòîé â ðåàëèçàöèè è íåîáû÷íûé âåêòîðíûé ÿçûê. http://sourceforge.net/projects/amino-cbbs/ ðåàëèçàöèÿ íà t—v— @ñîäåðæèò ìíîãî äðóãèõ ãîòîâûõ ïàðàëëåëüíûõ àëãîðèòìîâAF http://www.cs.cmu.edu/~blelloch/papers/Ble93.pdf ñòàòüÿ €re(x sums —nd their —ppli™—tionsX îáçîð òåõíèê è ïðèìåíåíèéF http://www.cs.cmu.edu/~blelloch/papers/Ble90.pdf †e™tor models for d—t—Ep—r—llel ™omputingD öåëàÿ êíèãà ïðî òî æåF Ñòðîæàéøå ðåêîìåíäóþF
  • 72. Message-passing concurrency Ôàêòè÷åñêè åäèíñòâåííûé ïîäõîä â ðàñïðåäåëåííûõ ñèñòåìàõ. Âîîáùå íåò ðàçäåëÿåìîãî ñîñòîÿíèÿ Àêòîðû îáìåíèâàþòñÿ ñîîáùåíèÿìè Ó êàæäîãî àêòîðà åñòü mailbox (FIFO-î÷åðåäü ñîîáùåíèé) Îòñûëêà ñîîáùåíèé àñèíõðîííàÿ è íåáëîêèðóþùàÿ
  • 73. Message-passing concurrency Íå ïàíàöåÿ: äåäëîêè åñòü (íî äðóãèå) Òåì íå ìåíåå, íàïèñàòü êîððåêòíóþ ïðîãðàììó ïðîùå Åñòü ôîðìàëüíûå ìîäåëè (CSP) ⇒ ïîääàåòñÿ âåðèôèêàöèè
  • 74. Message-passing concurrency Ðåàëèçàöèè: Êó÷à ÿçûêîâ: MPI Termite Scheme Clojure: agents Î÷åíü èíòåðåñíàÿ è ìîùíàÿ âàðèàöèÿF he(nitely worth seeingF http://clojure.org/agents glojure is to ™on™urrent progr—mming —s t—v— w—s to yy€ Scala: actors Java: Kilim Haskell: CHP (Communicating Haskell Processes) È, êîíå÷íî, Erlang uiller fe—tureX ƒele™tive re™eive
  • 75. Message-passing concurrency Kilim: Ëåãêîâåñíûå íèòè (1ìëí â ïîðÿäêå âåùåé, ñâåðõáûñòðîå ïåðåêëþ÷åíèå) Î÷åíü áûñòðûé message passing (óòâåðæäàåòñÿ, ÷òî 3x Erlang) Ïîñòïðîöåññèò áàéò-êîä (CPS transform äëÿ ìåòîäîâ, àííîòèðîâàííûõ @pausable).
  • 76. Message-passing concurrency Further reading: http://kilim.malhar.net/ http://www.cl.cam.ac.uk/research/srg/opera/publications/ papers/kilim_ecoop08.pdf íàó÷íàÿ ñòàòüÿF Íå äëÿ ðîáêèõD íî ÷èòàòü ìîæíîF Ìíîãî èíòåðåñíûõ èäåéF http://eprints.kfupm.edu.sa/30514/1/30514.pdf îðèãèíàëüíàÿ êíèãà Òîíè Õîàðà ïðî gommuni™—ting ƒequenti—l €ro™esses òåîðåòè÷åñêàÿ îñíîâà mess—geEp—ssing
  • 77. Event loop Âàðèàöèÿ íà òåìó message passing, íî íå ìíîãî âçàèìîäåéñòâóþùèõ àêòîðîâ, à îäèí (èëè íåñêîëüêî îäèíàêîâûõ) æèðíûé è âñåìîãóùèé. Ñåðâåðû (è accept, è select/poll/... ñþäà îòíîñÿòñÿ) GUI-ôðåéìâîðêè Ïðåëåñòè: Ýòî íå ôðåéìâîðê, íî ïàòòåðí: ëåãêî ðåàëèçîâàòü è èñïîëüçîâàòü äàæå íà ìèêðîóðîâíå Ê íåìó ñâîäèòñÿ êó÷à çàäà÷ Î÷åíü ëåãêî ïèøåòñÿ Áîëüøèíñòâî ìíîãîïîòî÷íûõ ïðîáëåì îòñóòñòâóþò
  • 78. Event loop private BlockingQueueOurEvent events = new LinkedBlockingQueueOurEvent(); void mainLoop() { while(true) { processEvent(events.poll()); } } public class OurEvent {...}
  • 79. Software Transactional Memory Òðàíçàêöèè íà óðîâíå ïàìÿòè; àòîìàðíûå êóñêè êîäà. Ïîëíîöåííûé commit/rollback, ïîëíàÿ àòîìàðíîñòü Òðàíçàêöèè ïîâòîðÿåìû retry ïðè êîììèòåD åñëè èçâíå èçìåíåíà ïðî÷òåííàÿ ïåðåìåííàÿ Òðàíçàêöèîííûå ïðîãðàììû êîìáèíèðóåìû!  îòëè÷èå îò sh—red st—te @ïðàâèëüíîCïðàâèëüíî=ïðàâèëüíîA Íå äîëæíî áûòü íèêàêèõ ïîáî÷íûõ ýôôåêòîâ, êðîìå îáðàùåíèé ê òðàíçàêöèîííîé ïàìÿòè
  • 80. Software Transactional Memory Ïñåâäîêîä: // Insert a node into a doubly-linked list atomically atomic { newNode-prev = node; newNode-next = node-next; node-next-prev = newNode; node-next = newNode; }
  • 81. Software Transactional Memory Ïñåâäîêîä (âïåðâûå ïðåäëîæåíî â ðåàëèçàöèè â Haskell): atomic { if (queueSize 0) { remove item from queue and use it } else { retry } } retry ïåðåçàïóñêàåò òðàíçàêöèþ â ìîìåíò, êîãäà èçìåíèòñÿ îäíà èç ïðî÷èòàííûõ åþ ïåðåìåííûõ.
  • 82. Software Transactional Memory Ðåàëèçàöèè: Haskell: ïîëíîöåííàÿ è áåçîïàñíàÿ ïîääåðæêà Clojure: ïîëíîöåííàÿ è íåáåçîïàñíàÿ ïîääåðæêà Java: Deuce, JSTM, . . . Ìíîãî áèáëèîòåê äëÿ C è C++, â ò.÷. äàæå êîìïèëÿòîðû ñ êëþ÷åâûì ñëîâîì atomic Íå çíàþD èñïîëüçóþò ëè èõ
  • 83. Software Transactional Memory Further reading: http://research.microsoft.com/Users/simonpj/papers/stm/ stm.pdf gompos—˜le wemory „r—ns—™tionsF http: //themonadreader.files.wordpress.com/2010/01/issue15.pdf Æóðíàë won—dF‚e—der sssue ISD ñîäåðæèò ñòàòüþ smplementing ƒ„w in pure r—skellD èíòåðåñíîå îáñóæäåíèå âîïðîñîâ ðåàëèçàöèè ƒ„wF
  • 84. Àñèíõðîííîå ïðîãðàììèðîâàíèå Íàáèðàåò îáîðîòû áëàãîäàðÿ âåáó (AJAX) è áîëüøèì ðàñïðåäåëåííûì ñèñòåìàì, ãäå ñèíõðîííûé RPC ñëèøêîì äîðîã. Quite a challenge.
  • 85. Àñèíõðîííîå ïðîãðàììèðîâàíèå Ñèíõðîííûé API: interface API { Answer compute(Question request) throws Whoops; } Àñèíõðîííûé API: interface API { void compute(Question request, {Answer = void} onReady, {Whoops = void} onWhoops) }
  • 86. Àñèíõðîííîå ïðîãðàììèðîâàíèå Ïðè÷èíû: Áëîêèðóþùèå âûçîâû íåóäîáíû èëè íå ïîääåðæèâàþòñÿ eteˆ q…s @ ” àñèíõðîííî ïîëó÷èòü ðåçóëüòàò äèàëîãà“ è òFïFA Àñèíõðîííûé API äîïóñêàåò áîëåå ýôôåêòèâíóþ ðåàëèçàöèþ Àñèíõðîííûé ââîäEâûâîä Àñèíõðîííûé äîñòóï ê õðàíèëèùàì äàííûõ F F F Àêòèâíàÿ ñòîðîíà @ñåðâåðD ñåòåâîé äðàéâåð ÎÑ F F F A ìîæåò ðåøàòüD êîãäà è â êàêîì ïîðÿäêå îòâå÷àòü íà çàïðîñû
  • 87. Àñèíõðîííîå ïðîãðàììèðîâàíèå Ïðîáëåìû: Íåëèíåéíûé ïîòîê èñïîëíåíèÿ Î÷åíü íåóäîáíî îòëàæèâàòü Ïîøàãîâîå âûïîëíåíèå â îòëàä÷èêå äåëàåò íå òî Íåò àíàëîãîâ ïðèâû÷íûõ êîíñòðóêöèé óïðàâëåíèÿ (öèêëû, try..finally . . . ) Äàæå ñýìóëèðîâàòü èõ íåëåãêî  áîëüøèíñòâå ßÏ àñèíõðîííûé êîä êðàéíå ãðîìîçäîê
  • 88. Àñèíõðîííîå ïðîãðàììèðîâàíèå public void requestInit() { AdminConsoleService.App.getInstance().getLoadGeneratorServersInfo( new AcAsyncCallbackListServerInfo() { public void doOnSuccess(final ListServerInfo loadGenerators) { AdminConsoleService.App.getInstance().getApplicationServersInfo( new AcAsyncCallbackListServerInfo() { public void doOnSuccess(ListServerInfo appServers) { init(appServers, loadGenerators); } }); } }); } (c) ru_java.
  • 89. Àñèíõðîííîå ïðîãðàììèðîâàíèå Êàê æå áûòü?
  • 90. Àñèíõðîííîå ïðîãðàììèðîâàíèå Êàê æå áûòü? Âñïîìèíàåì óðîêè ôóíêöèîíàëüíîãî ïðîãðàììèðîâàíèÿ. Èçáàâèòüñÿ îò ñèíòàêñè÷åñêîãî ìóñîðà Àñèíõðîííûå çíà÷åíèÿ ïåðâîêëàññíûå îáúåêòû @ñìF äàëååA Íóæåí ÿçûê ñ çàìûêàíèÿìèF ƒorry guysF Ðåàëèçîâàòü ñòðóêòóðû óïðàâëåíèÿ Íå ñîéòè ñ óìà îò ñëîæíîñòè
  • 91. Àñèíõðîííîå ïðîãðàììèðîâàíèå Êàê æå áûòü? Âñïîìèíàåì óðîêè ôóíêöèîíàëüíîãî ïðîãðàììèðîâàíèÿ. Èçáàâèòüñÿ îò ñèíòàêñè÷åñêîãî ìóñîðà Ðåàëèçîâàòü ñòðóêòóðû óïðàâëåíèÿ  âèäå ôóíêöèé âûñøåãî ïîðÿäêà Öèêëû ÷åðåç ðåêóðñèþ Ýìóëÿöèÿ õâîñòîâûõ âûçîâîâ Âñå ýòî ñòîèò àáñòðàãèðîâàòü â ” êîìáèí¡àòîðíóþ áèáëèîòåêó“ Íå ñîéòè ñ óìà îò ñëîæíîñòè
  • 92. Àñèíõðîííîå ïðîãðàììèðîâàíèå Êàê æå áûòü? Âñïîìèíàåì óðîêè ôóíêöèîíàëüíîãî ïðîãðàììèðîâàíèÿ. Èçáàâèòüñÿ îò ñèíòàêñè÷åñêîãî ìóñîðà Ðåàëèçîâàòü ñòðóêòóðû óïðàâëåíèÿ Íå ñîéòè ñ óìà îò ñëîæíîñòè Öåëûé êëàññ ïðîáëåìD ñïåöèôè÷íûõ äëÿ ýòîãî ïîäõîäà Áîëüøèíñòâî ñâÿçàíî ñ mut—˜le st—te Íåèññëåäîâàííàÿ îáëàñòüc
  • 93. Àñèíõðîííîå ïðîãðàììèðîâàíèå Once again: interface AsyncT { void run(CallbackT onOk, CallbackThrowable onError); } Ýòè îáúåêòû êîìáèíèðóåìû.
  • 94. Àñèíõðîííîå ïðîãðàììèðîâàíèå Ó÷èìñÿ ó .NET âîîáùå è F# â ÷àñòíîñòè. let AsyncHttp(url:string) = async { let req = WebRequest.Create(url) let! rsp = req.GetResponseAsync() use stream = rsp.GetResponseStream() use reader = new System.IO.StreamReader(stream) return reader.ReadToEnd() } Ýòî íàçûâàåòñÿ ” asynchronous workows“. Workow êðàñèâûé ñèíîíèì äëÿ ñëîâà ” Ìîíàäà“ (google://workow, monad). http://blogs.msdn.com/dsyme/archive/2007/10/11/ introducing-f-asynchronous-workflows.aspx
  • 95. Àñèíõðîííîå ïðîãðàììèðîâàíèå class AsyncPrimitives { AsyncT succeed(T value) {...} AsyncT failwith(Throwable error) {...} AsyncU bind(AsyncT at, FuncT,AsyncU fau) {...} } Ýòîãî äîñòàòî÷íî äëÿ áîëüøèíñòâà ñòðóêòóð óïðàâëåíèÿ 1. Ýòî íàçûâàåòñÿ ” ìîíàäà“. 1 Ïðè ïîääåðæêå îïòèìèçàöèè õâîñòîâûõ âûçîâîâ
  • 96. Àñèíõðîííîå ïðîãðàììèðîâàíèå Ìîíàäû ïðîíèêëè â ìåéíñòðèì: ó C# òåïåðü òîæå ó÷èìñÿ (LINQ). var requests = new[] { WebRequest.Create(http://www.google.com/), WebRequest.Create(http://www.yahoo.com/), WebRequest.Create(http://channel9.msdn.com/) }; http://www.aboutcode.net/2008/01/14/Async+WebRequest+ Using+LINQ+Syntax.aspx
  • 97. Àñèíõðîííîå ïðîãðàììèðîâàíèå Ìîíàäû ïðîíèêëè â ìåéíñòðèì: ó C# òåïåðü òîæå ó÷èìñÿ (LINQ). var pages = from request in requests select from response in request.GetResponseAsync() let stream = response.GetResponseStream() from html in stream.ReadToEndAsync() select new { html, response }; http://www.aboutcode.net/2008/01/14/Async+WebRequest+ Using+LINQ+Syntax.aspx ÌîðàëüX Ïîçíàéòå ìîíàäû ñòàíåò ëåã÷å ïèñàòü àñèíõðîííûé êîäF
  • 98. Àñèíõðîííîå ïðîãðàììèðîâàíèå Further reading: Î÷åíü èíòåðåñíûé ïîäõîä ñ èñïîëüçîâàíèåì yield return: http://tomasp.net/blog/csharp-async.aspxF ‡es hyer îáúÿñíåíèå ìîíàäû gont íà g5X http://blogs.msdn. com/wesdyer/archive/2008/01/11/the-marvels-of-monads.aspx ×òî òàêîå êîìáèíàòîðíàÿ áèáëèîòåêàX http://fprog.ru/2009/issue3D ñòàòüÿ ” Ýëåìåíòû ôóíêöèîíàëüíûõ ÿçûêîâ“ Àñèíõðîííûå êîìáèíàòîðû íà t—v—X http://spbhug.folding-maps.org/wiki/EugeneKirpichovD ñëàéäû ïðî t—v— è p€F
  • 99. Further reading Ðàçíûå ïàòòåðíû ìíîãîïîòî÷íîãî è ðàñïðåäåëåííîãî ïðîãðàììèðîâàíèÿ. Î÷åíü ìíîãî è èíòåðåñíî. http://www.cs.wustl.edu/~schmidt/patterns-ace.html http: //parlab.eecs.berkeley.edu/wiki/patterns/patterns åùå êðó÷å
  • 100. Ñîäåðæàíèå Êîððåêòíîñòü Ïðè÷èíû áàãîâ Äîêàçàòåëüñòâî êîððåêòíîñòè Óëó÷øåíèå êîððåêòíîñòè Ïàòòåðíû è ïîäõîäû Ïàðàëëåëèçì Concurrency Cutting edge Haskell Erlang .NET Clojure Çàêëþ÷åíèå
  • 101. Cutting edge ×òî óìååò Haskell: Âñå ïîáî÷íûå ýôôåêòû êîíòðîëèðóþòñÿ Íåò íåêîíòðîëèðóåìûõ ïðîáëåì èç-çà èõ íàëè÷èÿ Ïîçâîëÿåò íåìûñëèìûå â äðóãèõ ÿçûêàõ âåùè
  • 102. Cutting edge ×òî óìååò Haskell: Ñàìûå áûñòðûå â ìèðå ëåãêîâåñíûå íèòè è ïðèìèòèâû ñèíõðîíèçàöèè I ìåñòî íà v—ngu—ge ƒhootoutD THx áûñòðåå íàòèâíûõ …˜untuD Sõ áûñòðåå irl—ng3 Ïàðàëëåëüíûå ñòðàòåãèè Ïðîñòûå ïàðàëëåëüíûå âû÷èñëåíèÿX íåò àíàëîãîâ â äðóãèõ ÿçûêàõ Data Parallel Haskell Àâòîìàòè÷åñêè ðàñïàðàëëåëèâàåìûå âåêòîðíûå âû÷èñëåíèÿ Òðàíçàêöèîííàÿ ïàìÿòü Ðàáîòà â íàïðàâëåíèè GPU Ìîùíûå áèáëèîòåêè
  • 103. Ëåãêîâåñíûå íèòè Nothing special, ïðîñòî î÷åíü áûñòðûå è ïî÷òè 0 ñèíòàêñè÷åñêîãî îâåðõåäà. C++0x futures/promises and more â 60 ñòðîê.
  • 104. Ïàðàëëåëüíûå ñòðàòåãèè Ëåíèâîñòü ïîçâîëÿåò îòäåëèòü àëãîðèòì è ñïîñîá ðàñïàðàëëåëèâàíèÿ. Ðåçóëüòàò àëãîðèòìà ñòðóêòóðà, ïîëíàÿ ” îáåùàíèé“. Îáåùàíèÿ ” èñïîëíÿþòñÿ“ (ôîðñèðóþòñÿ) ñ ïîìîùüþ ñòðàòåãèè. Ñòðàòåãèÿ ýòî îáûêíîâåííàÿ, ïðîñòàÿ ôóíêöèÿ. Èäåÿ ÿäåðíàÿ. Ýòî ìîæíî ðåàëèçîâàòü è íà Java, åñëè
  • 105. Ïàðàëëåëüíûå ñòðàòåãèè Íàïðèìåð, ñòðàòåãèÿ ” ïàðàëëåëüíî ôîðñèðîâàòü âñå ýëåìåíòû ñïèñêà“: parList :: Strategy a - Strategy [a] parList strat [] = () parList strat (x:xs) = strat x `par` (parList strat xs)
  • 106. Data Parallel Haskell Âåêòîðèçàòîð (òðàíñëèðóåò äàæå ðåêóðñèâíûå ôóíêöèè â âåêòîðíûå îïåðàöèè) Áèáëèîòåêà ïàðàëëåëüíûõ âåêòîðíûõ îïåðàöèé dotp_double :: [:Double:] - [:Double:] - Double dotp_double xs ys = sumP [:x * y | x - xs | y - ys:] smMul :: [:[:(Int,Float):]:] - [:Float:] - Float smMul sm v = sumP [: svMul sv v | sv - sm :] http://research.microsoft.com/en-us/um/people/simonpj/ papers/ndp/NdpSlides.pdf ñëàéäû
  • 107. Data Parallel Haskell sort :: [:Float:] - [:Float:] sort a = if (length a = 1) then a else sa!0 +++ eq +++ sa!1 where m = a!0 lt = [: f | f-a, fm :] eq = [: f | f-a, f==m :] gr = [: f | f-a, fm :] sa = [: sort a | a - [:lt,gr:] :] Âåêòîðèçóåòñÿ è ïàðàëëåëèçóåòñÿ.
  • 108. Repa Regular, shape-polymorphic, parallel arrays in Haskell. The Haskell code transparently makes use of multicore hardware Ñäåëàíî ãðóïïîé Ìàíóýëÿ ×àêðàâàðòè ýòî îäèí èç êðóòåéøèõ èìïëåìåíòîðîâ Õàñêåëëà. http://justtesting.org/ regular-shape-polymorphic-parallel-arrays-in
  • 109. Òðàíçàêöèîííàÿ ïàìÿòü transfer :: Account - Account - Int - IO () transfer from to amount = atomically do deposit to amount withdraw from amount
  • 110. Òðàíçàêöèîííàÿ ïàìÿòü check True = return () check False = retry limitedWithdraw :: Account - Int - STM () limitedWithdraw acc amount = do bal - readTVar acc check (amount = 0 || amount = bal) writeTVar acc (bal - amount) ×åòêîå ðàçäåëåíèå ìåæäó: IO êîä ñ ïðîèçâîëüíûìè ïîáî÷íûìè ýôôåêòàìè STM êîä, åäèíñòâåííûé ýôôåêò êîòîðîãî ðàáîòà ñ òðàíçàêöèîííîé ïàìÿòüþ atomically :: STM t - IO t (íàîáîðîò íåëüçÿ)
  • 111. Erlang Ñâÿçü ïðîöåññîâ òîëüêî ÷åðåç îáìåí ñîîáùåíèÿìè. Selective receive (èçáèðàòåëüíàÿ âûáîðêà èç mailbox). Ìîùíàÿ ôè÷àF Ïðîçðà÷íàÿ ðàñïðåäåëåííîñòü. Î÷åíü ýôôåêòèâíàÿ ðåàëèçàöèÿ íèòåé è message passing. Î÷åíü êðóòàÿ è ïðîäóìàííàÿ èíôðàñòðóêòóðà. Î÷åíü ïðîñòîé ÿçûê. Àêòèâíî ïðèìåíÿåòñÿ â èíäóñòðèè (â ò.÷. Amazon, Facebook, Yahoo, . . . ). http://spbhug.folding-maps.org/wiki/Erlang ñàìîïèàð YA
  • 112. F# Asynchronous workows: óæå ðàññìîòðåëè.
  • 113. C# Asynchronous LINQ (ìîæíî ñäåëàòü ñàìîìó: LINQ = ìîíàäû) Óæå ðàññìîòðåëè Parallel LINQ
  • 114. Parallel LINQ (PLINQ) IEnumerableT, IParallelEnumerableT AsParallel http://msdn.microsoft.com/en-us/magazine/cc163329.aspx
  • 115. Parallel LINQ (PLINQ) IEnumerableT data = ...; var q = from x in data.AsParallel() where p(x) orderby k(x) select f(x); foreach (var e in q) a(e); Òðàíñëèðóåòñÿ â êîìáèíàöèþ ParallelEnumerable.{Select,Where,OrderBy} è ò.ï.
  • 116. Parallel LINQ (PLINQ) IEnumerableT leftData = ..., rightData = ...; var q = from x in leftData.AsParallel() join y in rightData on x.a == y.b select f(x, y);
  • 117. Clojure Clojure is to concurrent programming as Java was to OOP Áèáëèîòåêà ÷èñòî ôóíêöèîíàëüíûõ ñòðóêòóð äàííûõ 4 ìåõàíèçìà concurrency: Atoms, Vars, Agents, Refs Âñå îíè îïåðèðóþò íàä immutable çíà÷åíèÿìè è ÷èñòûìè ôóíêöèÿìè fe™—use this is the w—y to goF
  • 118. Atoms Áîëåå èëè ìåíåå îáû÷íûå atomic ïåðåìåííûå. (swap! atom f) ” Àòîìàðíî çàìåíèòü x íà f (x), âåðíóòü ñòàðûé x (compare-and-exchange)“ f îáÿçàíà áûòü ÷èñòîé: åå ìîãóò âûçâàòü íåñêîëüêî ðàç http://clojure.org/atoms
  • 119. Vars Thread-local, dynamically scoped ïåðåìåííûå. Îáëàñòü âèäèìîñòè îïðåäåëÿåòñÿ íå ñèíòàêñè÷åñêîé âëîæåííîñòüþ, à ñòåêîì âûçîâîâ. (def x 0) îáúÿâèòü x ñ ãëîáàëüíûì çíà÷åíèåì ïî óìîë÷àíèþ 0. x ïðî÷èòàòü çíà÷åíèå x. (set! x 5) ïðèñâîèòü x = 5 â ðàìêàõ òåêóùåé íèòè. (binding [x 5] (do-something)) âûïîëíèòü do-something, ïîëàãàÿ x = 5 â ðàìêàõ òåêóùåé íèòè. http://clojure.org/vars
  • 120. Agents Àñèíõðîííî èçìåíÿåìûå ïåðåìåííûå. Êàê àêòîðû, íî ïàññèâíûå (àãåíòàì ñíàðóæè ãîâîðÿò, ÷òî èì ñ ñîáîé ñäåëàòü). (agent 0) àãåíò ñ íà÷àëüíûì çíà÷åíèåì 0 (deref x) òåêóùåå çíà÷åíèå (send x f) àñèíõðîííî çàìåíèòü x íà f (x) (await x) äîæäàòüñÿ îêîí÷àíèÿ âñåõ äåéñòâèé íàä àãåíòîì (set-validator x f) ïîâåñèòü âàëèäàòîð ñîñòîÿíèÿ (add-watch x f) ïîâåñèòü ñëóøàòåëÿ http://clojure.org/agents
  • 121. Refs Òðàíçàêöèîííàÿ ïàìÿòü (STM). Äîâîëüíî îáû÷íàÿ Òðàíçàêöèè äîëæíû áûòü áåç ïîáî÷íûõ ýôôåêòîâ Ëþáîïûòíî: (commute x f): çàìåíèòü x íà f (x), ïðåäïîëàãàÿ ÷òî f êîììóòèðóåò ñ îñòàëüíûìè. ÍàïðèìåðD (commute counter inc) ïîäîéäåò Ðàáîòàåò ñëåãêà áûñòðååD ÷åì äðóãèå ôóíêöèèEìóòàòîðû http://clojure.org/refs
  • 122. Ñîäåðæàíèå Êîððåêòíîñòü Ïðè÷èíû áàãîâ Äîêàçàòåëüñòâî êîððåêòíîñòè Óëó÷øåíèå êîððåêòíîñòè Ïàòòåðíû è ïîäõîäû Ïàðàëëåëèçì Concurrency Cutting edge Haskell Erlang .NET Clojure Çàêëþ÷åíèå
  • 123. ×òî áûëî Êëàññèôèêàöèÿ ìíîãîïîòî÷íûõ ïðîãðàìì Ôîðìàëüíûå ìåòîäû (LTL) è òóëû (SPIN,JPF,CheckThread) Êîððåêòíîñòü: èíêàïñóëÿöèÿ, âûñîêîóðîâíåâûå îïåðàöèè, ôàêòîðèçàöèÿ, äåäëîêè, àòîìàðíûå è èäåìïîòåíòíûå îïåðàöèè, îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü Ìåòîäèêè: fork/join, âåêòîðíûå àëãîðèòìû, message-passing, event-driven, STM, àñèíõðîííîå ïðîãðàììèðîâàíèå Haskell: ëåãêèå íèòè, ïàðàëëåëüíûå ñòðàòåãèè, âåêòîðèçàöèÿ, STM Erlang: ìîùíàÿ èíôðàñòðóêòóðà Clojure: Atoms, Vars, Agents, Refs C#: PLINQ
  • 124. ×åãî íå áûëî Ðàñïðåäåëåíùèíà gonsensusD P€gD ve—der ele™tionF F F hr„ et™F wess—ging p—tterns Íåáëîêèðóþùèå àëãîðèòìû „here9s more to itF
  • 125. The end Ñïàñèáî! Âîïðîñû?

×