SlideShare a Scribd company logo
Ìíîãîïîòî÷íîå ïðîãðàììèðîâàíèå
Êîððåêòíîñòü, ïàòòåðíû, ïîäõîäû
Åâãåíèé Êèðïè÷¼â
24 ñåíòÿáðÿ 2010 ã.
Öåëü äîêëàäà
Ðàñøèðèòü êðóãîçîð â îáëàñòè ìíîãîïîòî÷íîãî
ïðîãðàììèðîâàíèÿ âîîáùå.
Êîððåêòíîñòü
Êàê ñôîðìóëèðîâàòüD ïîâûñèòüD ãàðàíòèðîâàòü
Èíñòðóìåíòû
Ïàòòåðíû è âåëîñèïåäû
Ïîäõîäû è ôèøêè ðàçíûõ ÿçûêîâ
Êëàññèôèêàöèÿ ìíîãîïîòî÷íûõ ïðîãðàìì
Parallelism vs Concurrency
Parallel Îäíà çàäà÷à áüåòñÿ íà ìíîãî ÷àñòåé
Concurrent Ìíîãî ðàçíûõ çàäà÷ (ñëîæíåå)
Ñåãîäíÿ  â îñíîâíîì î concurrency.
×àñòü 1. Êîððåêòíîñòü.
Ñîäåðæàíèå
Êîððåêòíîñòü
Ïðè÷èíû áàãîâ
Äîêàçàòåëüñòâî êîððåêòíîñòè
Óëó÷øåíèå êîððåêòíîñòè
Ïàòòåðíû è ïîäõîäû
Ïàðàëëåëèçì
Concurrency
Cutting edge
Haskell
Erlang
.NET
Clojure
Çàêëþ÷åíèå
Ïðè÷èíû áàãîâ
Êîðåíü âñåõ çîë  èçìåíÿåìîå âî âðåìåíè ñîñòîÿíèå.
N íèòåé, K ñîñòîÿíèé ⇒ O(KN) ïåðåïëåòåíèé
Ïðîìåæóòî÷íûå ñîñòîÿíèÿ âèäèìû
Äàæå âûçîâ ìåòîäà  ýòî áîëüøå íå ÷åðíûé ÿùèê
Åãî òåëî áîëüøå íå àòîìàðíî
Êîððåêòíûå ìíîãîïîòî÷íûå ïðîãðàììû íå ìîäóëüíû
ƒequenti—ly ™orre™t + ƒequenti—lly ™orre™t = gon™urrently
™orre™t
Ïðè÷èíû áàãîâ
Sequentialy correct + Sequentially correct =
Concurrently correct
Äîêàçóåìàÿ êîððåêòíîñòü
Face it:
Ïðîãðàììà íå áûâàåò ¾ïî÷òè êîððåêòíà¿.
Ïóñòü âåðîÿòíîñòü áàãà 10−8
109 âûçîâîâ çà íåäåëþ  è âåðîÿòíîñòü 1 − e−10 ≈ 1
Ïðè íåïðåðûâíîì òåñòèðîâàíèè îøèáêà òîæå âñïëûâåò
òîëüêî ÷åðåç íåäåëþ
Ðàáîòàåò èäåàëüíî (äîêàçóåìî) èëè íå ðàáîòàåò âîîáùå
Äîêàçóåìàÿ êîððåêòíîñòü
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.
Ôîðìàëüíûå ìåòîäû
Ïðèìåíÿòü íå îáÿçàòåëüíî.
Ôîðìàëüíûå ìåòîäû
À çà÷åì òîãäà îíè âîîáùå íóæíû?
×òîáû îïèñûâàòü ñèñòåìó ïîëóôîðìàëüíî
×òîáû ÷óÿòü: ôîðìàëèçóåìà ëè ñèñòåìà â ïðèíöèïå?
Åñëè íåò @ñèñòåìà ñëèøêîì çàïóòàíàA  î êîððåêòíîñòè
ìîæíî çàáûòüF
Ôîðìàëüíûå ìåòîäû
Ìîé îïûò: äîñòàòî÷íî ïîïûòàòüñÿ ôîðìàëèçîâàòü ñèñòåìó:
Âñïëûâàþò ïðîòèâîðå÷èÿ, íåäîãîâîðêè â òðåáîâàíèÿõ
Âûäåëÿþòñÿ êîìïîíåíòû áåç ÷åòêîé ñïåöèôèêàöèè
ÁëàæåíD êòî âåðóåòD ÷òî îíè
”
è òàê“ ðàáîòàþò
Ôîðìàëüíûå ìåòîäû
×òî æå ýòî çà ìåòîäû?
Íàïðèìåð, ëèíåéíàÿ òåìïîðàëüíàÿ ëîãèêà.
×òî òàêîå LTL
Ëèíåéíàÿ òåìïîðàëüíàÿ ëîãèêà  ñïîñîá ðàññóæäàòü î
ïîñëåäîâàòåëüíîñòÿõ ñîáûòèé.
Ïðîãðàììà ìîäåëèðóåòñÿ àâòîìàòîì (
”
ñòðóêòóðîé Êðèïêå“).
Èññëåäóþòñÿ âîçìîæíûå ïîñëåäîâàòåëüíîñòè ñîñòîÿíèé.
Çà÷åì LTL â ýòîì äîêëàäå
×òîáû ëó÷øå ôîðìóëèðîâàòü ñâîéñòâà ñâîèõ ïðîãðàìì.
×òîáû, â êðàéíåì ñëó÷àå, ñóìåòü èõ äîêàçàòü.
Âðó÷íóþ
Èëè èíñòðóìåíòàìè
Ñòðóêòóðà Êðèïêå
Ñòðóêòóðà Êðèïêå ≈ ãðàô ñîñòîÿíèé.
Ìíîæåñòâî ñîñòîÿíèé
Íåêîòîðûå íà÷àëüíûå
Íåêîòîðûå ñîåäèíåíû ïåðåõîäîì
Ïåðåõîä áåçóñëîâíûé
Ìíîæåñòâî ôàêòîâ
 êàæäîì ñîñòîÿíèè âåðíû íåêîòîðûå ôàêòû.
Ñòðóêòóðà Êðèïêå
Ìèêðîâîëíîâêà.
Ñòðóêòóðà Êðèïêå
Ïåðåõîäû íå ïîäïèñàíû, ïîòîìó ÷òî:
Íîìåð ñîñòîÿíèÿ ïîëíîñòüþ îïèñûâàåò ñîñòîÿíèå
ïðîãðàììû
Åñëè ïåðåõîä óñëîâíûé  íàäî ïîäåëèòü ñîñòîÿíèå íà äâà
ÒîD â êîòîðîì óñëîâèå âåðíî @ïåðåõîä ìîæåò ïðîèçîéòèA
ÒîD â êîòîðîì óñëîâèå íåâåðíî @ïåðåõîä íå ìîæåò
ïðîèçîéòèA
Ïðîãðàììó ìîæíî ñòðàíñëèðîâàòü â ñòðóêòóðó Êðèïêå
Ñòðóêòóðû Êðèïêå ïðåêðàñíî ïîääàþòñÿ âåðèôèêàöèè
LTL
Ëèíåéíàÿ òåìïîðàëüíàÿ ëîãèêà (Linear Temporal Logic).
Ðàññóæäàåò î ïîñëåäîâàòåëüíîñòÿõ ñîñòîÿíèé ìèðà âî âðåìåíè.
Åñòü çàïðîñ ⇒ êîãäà-íèáóäü áóäåò îòâåò
Áëîêèðîâêà çàïðîøåíà ⇒ êëèåíò áóäåò îáñëóæåí ñêîëü
óãîäíî áîëüøîå ÷èñëî ðàç, ïîêà íå îòïóñòèò åå
. . .
Ïðåëåñòè:
Êðàòêàÿ, ïîíÿòíàÿ, ìîùíàÿ è îäíîçíà÷íàÿ
LTL-ñâîéñòâà ëåãêî âåðèôèöèðóþòñÿ äàæå âðó÷íóþ
Îòíîñèòåëüíî ñòðóêòóð Êðèïêå
Ìíîãî ìîùíûõ èíñòðóìåíòîâ
Ôîðìóëû LTL
p1, p2, . . . Ïåðåìåííûå
A ∧ B, ¬A. . . Ëîãè÷åñêèå ñâÿçêè
XA Â ñëåäóþùèé ìîìåíò A (neXt)
GA ≡ A Âñåãäà A (Globally)
FA ≡ ♦A Êîãäà-íèáóäü A (Future)
AUB A, ïî êðàéíåé ìåðå äî íàñòóïëåíèÿ B
Áåñêîíå÷íîñòè
Íà÷èíàÿ ñ íåêîòîðîãî ìîìåíòà, íàâñåãäà: FG A ≡ ♦ A
Áåñêîíå÷íî ÷àñòî: GF A ≡ ♦A
Èëëþñòðàöèÿ ôîðìóë LTL
Ñâîéñòâà ìíîãîïîòî÷íûõ ïðîãðàìì
Åñòü ðÿä î÷åíü ÷àñòî âñòðå÷àþùèõñÿ ñâîéñòâ.
Ýòî ïðîñòî òåðìèíîëîãèÿ. Íî òåðìèíîëîãèÿ âàæíà.
Êàê îíè íàçûâàþòñÿ?
Êàê îíè ôîðìóëèðóþòñÿ â LTL?
Ñâîéñòâà
Æèâîñòü (liveness)
×òîEòî õîðîøåå êîãäàEíèáóäü ïðîèçîéäåòX ♦Alive
Çàäàíèå êîãäàEíèáóäü íà÷íåòñÿ
Áåçîïàñíîñòü (safety)
×òîEòî ïëîõîå íèêîãäà íå ïðîèçîéäåòX ¬Dead
Çàäàíèå íèêîãäà íå ïîòåðïèò êðàõ
Ñâîéñòâà
Ñïðàâåäëèâîñòü (fairness)
Òî, ÷òî ìîæåò ïðîèçîéòè  ïðîèçîéäåò
Ñëàáàÿ: ♦ Req → ♦Ack
Ðåñóðñ çàïðîøåí @è îñòàåòñÿ çàïðîøåííûìA →
êîãäàEíèáóäü áóäåò âûäàí
Ñèëüíàÿ: ♦Req → ♦Ack
Íèòü áåñêîíå÷íî ìíîãî ðàç èñïîëíèìà @èìååò íå ñàìûé
íèçêèé ïðèîðèòåò èç íåáëîêèðîâàííûõA → êîãäàEíèáóäü
ïîëó÷èò êâàíò
Àíòîíèì  starvation (ãîëîäàíèå)
Ïðèìåðû LTL-ñâîéñòâ
Óñòðîéñòâî íå âûêëþ÷àåòñÿ ñàìî ïî ñåáå
(isOn → (isOn U (turnOPressed ∨ noBattery))
Íå ðåæå ÷åì ðàç â 5 òàêòîâ âêëþ÷àåòñÿ êîíòðîëëåð
äâèãàòåëÿ
¬F5(activeThread = ENGINE_CONTROLLER)
Model checking
Íàóêà î ïðîâåðêå ñâîéñòâ ïðîãðàìì (íàïðèìåð, LTL) íà îñíîâå
èõ ìîäåëåé (íàïðèìåð, ñòðóêòóð Êðèïêå)  Model checking.
Ïðåìèÿ Òüþðèíãà 2007  çà äîñòèæåíèÿ â îáëàñòè model
checking, ñäåëàâøèå åãî ïðèìåíèìûì äëÿ ïðîåêòîâ ðåàëüíîãî
ðàçìåðà.
Èíñòðóìåíò: SPIN
Ïîâñåìåñòíî èñïîëüçóåìûé ÿçûê + âåðèôèêàòîð LTL-ñâîéñòâ
äëÿ ìíîãîçàäà÷íûõ ñèñòåì.
Ëàóðåàò ACM Software System award (2001) (äðóãèå ëàóðåàòû:
Unix, TeX, Java, Apache, TCP/IP, . . . ).
Ñè-ïîäîáíûé ñèíòàêñèñ
Äëÿ íàðóøåííûõ ñâîéñòâ ãåíåðèðóåòñÿ íàðóøàþùàÿ èõ
òðàññà
(óðîäëèâûé, íî òåðïèìûé) GUI
ß ïðîâåðÿë: Ïðèãîäíî äëÿ ïðèìåíåíèÿ íà ïðàêòèêå.
http://spinroot.com/spin/whatispin.html  îôèöèàëüíûé ñàéòF
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
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
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
Ôèëîñîôñêîå èçáàâëåíèå îò áàãîâ
Íàäî óìåíüøèòü O(KN).
Óìåíüøèòü ÷èñëî íàáëþäàåìûõ ñîñòîÿíèé (K)
smmut—˜ility
Èíêàïñóëÿöèÿ ñîñòîÿíèÿ
Âûñîêîóðîâíåâûå îïåðàöèè
Ôàêòîðèçàöèÿ
Ñèíõðîíèçàöèÿ
Íàâÿçàòü òðàññàì ýêâèâàëåíòíîñòü
Èäåìïîòåíòíûå îïåðàöèè
foo();foo(); ∼ foo();
Êîììóòàòèâíûå @íåçàâèñèìûåA îïåðàöèè
foo();bar(); ∼ bar();foo();
 ò.÷. èíêàïñóëÿöèÿ è íåçàâèñèìûå îáúåêòû
Ñ÷èòàòü áîëüøåå ÷èñëî òðàññ êîððåêòíûìè (îñëàáèòü
òðåáîâàíèÿ)
Immutability
Íåëüçÿ èçìåíèòü âîîáùå ⇒ íåëüçÿ èçìåíèòü íåïðàâèëüíî, íå â
òîì ïîðÿäêå . . .
Äîëæíà ñîáëþäàòüñÿ ðåêóðñèâíî ïî ïîëÿì îáúåêòà è ïî
öåïî÷êå íàñëåäîâàíèÿ â îáå ñòîðîíû.
Èíêàïñóëÿöèÿ ñîñòîÿíèÿ
Ïðîãðàììà êîððåêòíà ðîâíî íàñòîëüêî, íàñêîëüêî êîððåêòíû è
ñêîîðäèíèðîâàíû âñå, êòî ìîãóò ïîâëèÿòü íà ñîñòîÿíèå
îáúåêòà.
Ìîðàëü: ×åì ìåíüøå ñïîñîáîâ ïîâëèÿòü íà ñîñòîÿíèå, òåì
ëó÷øå.
Ìàëî êîìó äàâàòü ê íåìó äîñòóï
Ìàëî êîãî íàäî áóäåò êîîðäèíèðîâàòü
Äàâàòü äîñòóï â òåðìèíàõ ìàëîãî ÷èñëà âûñîêîóðîâíåâûõ
îïåðàöèé
Ìàëî êîìáèíàöèé îïåðàöèé íàäî ðàññìàòðèâàòü
Ìåíüøå íàðóøàåòñÿ öåëîñòíîñòü ìåæäó îïåðàöèÿìè
Âûñîêîóðîâíåâûå îïåðàöèè
Îïðåäåëåíèå: Âûñîêîóðîâíåâàÿ îïåðàöèÿ  îïåðàöèÿ, íå
íàðóøàþùàÿ öåëîñòíîñòü ñèñòåìû.
AtomicInteger.getAndIncrement
ConcurrentMap.putIfAbsent
Bank.transfer
Äîñòàòî÷íî ïðàâèëüíî ðåàëèçîâàòü ñàìó îïåðàöèþ.
Ïðîåêòèðóéòå API â òàêîì ñòèëå, åñëè ýòî âîçìîæíî.
Âûñîêîóðîâíåâûå îïåðàöèè
×àñòíûé ñëó÷àé:
Ó îáúåêòà â ìåðó áîëüøîå ñîñòîÿíèå
Õî÷åòñÿ àòîìàðíî ïîìåíÿòü íåñêîëüêî åãî ÷àñòåé
Çàïèõíèòå ñîñòîÿíèå â îáúåêò è ïîìåíÿéòå àòîìàðíî
ññûëêó íà ýòîò îáúåêò
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
Ôàêòîðèçàöèÿ
Ïðîãðàììà êîððåêòíà ðîâíî íàñòîëüêî, íàñêîëüêî êîððåêòíû è
ñêîîðäèíèðîâàíû âñå, êòî ìîãóò ïîâëèÿòü íà ñîñòîÿíèå
îáúåêòà.
Ìîðàëü: Íåçàâèñèìûå àñïåêòû ñîñòîÿíèÿ âûíîñèòü â
íåçàâèñèìûå îáúåêòû.
Ñëîæíîñòü ïàäàåò ñ (K1 + K2)N äî KN
1 + KN
2 (áðåä, íî ñóòü
ïðèìåðíî òàêàÿ).
Ôàêòîðèçàöèÿ
class DataLoader {
ClientToken beginLoad(Client client);
void writeData(ClientToken token, Data data);
void commit(ClientToken token);
void rollback(ClientToken token);
}
Ôàêòîðèçàöèÿ
Ãðÿçíûé êîä:
Òàáëèöà ClientToken/òðàíçàêöèÿ
(ìíîãîïîòî÷íûå êëèåíòû)
synchronized(locks.get(token))
Îáå òàáëèöû íàäî òîæå îõðàíÿòü
Ôàêòîðèçàöèÿ
Ðàçîðâåì ëèøíþþ çàâèñèìîñòü ìåæäó íåçàâèñèìûìè
çàäà÷àìè.
class DataLoader {
PerClientLoader beginLoad(Client client);
}
class PerClientLoader {
void writeData(Data data);
void commit();
void rollback();
}
Ôàêòîðèçàöèÿ
Ïðîñòîé è íåçàãðÿçíåííûé êîä
Ñèíõðîíèçàöèÿ ïðîñòûì synchronized
Íèêàêèõ òàáëèö
Íèêàêèõ ïðîáëåì ñ îõðàíîé òàáëèö îò ìíîãîïîòî÷íîãî
äîñòóïà
Îñëàáëåíèå òðåáîâàíèé
Èíîãäà îáåñïå÷èòü æåñòêèå èíâàðèàíòû öåëîñòíîñòè
íåâîçìîæíî.
Îíè ìîãóò íàðóøàòüñÿ èçâíå
Åñòü âíåøíèå ïðîöåññûD íàðóøàþùèå öåëîñòíîñòü
Îíè íàì íå ïîäêîíòðîëüíû
ÍàïðèìåðX ñèíõðîíèçàöèÿ ôàéëîâD èçìåíÿåìûõ âíåøíèìè
ïðîöåññàìè
Èõ ñëèøêîì äîðîãî ïîääåðæèâàòü
ÍàïðèìåðD áîëüøàÿ ðàñïðåäåëåííàÿ ñèñòåìà
Ñèíõðîííîå ïðîòàëêèâàíèå èçìåíåíèÿ íà âñå ðåïëèêè 
ñëèøêîì äîëãî
Ñ ó÷åòîì ïàäåíèé óçëîâ âñå åùå õóæå
Ëåíü ïèñàòü ñëîæíûé êîä :)
Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü
Ñóäÿ ïî âñåìó, îäèí èç ìîùíåéøèõ ïðèåìîâ ïðîåêòèðîâàíèÿ
íåêîòîðûõ êëàññîâ ìíîãîçàäà÷íûõ ñèñòåì.
Îíà æå ¾eventual consistency¿.
Ñóòü:
”
Ñîñòîÿíèå ñèñòåìû âñåãäà öåëîñòíî“  î÷åíü òðóäíî è íå
âñåãäà íóæíî.
”
Ñîñòîÿíèå ñèñòåìû âñå öåëîñòíåå è öåëîñòíåå“  ëåãêî
îáåñïå÷èòü, ÷àñòî äîñòàòî÷íî.
Äåëàåì ñèñòåìó ëèøü ñòðåìÿùåéñÿ ê ñîñòîÿíèþ öåëîñòíîñòè.
Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü
Ïðèìåð ñòðóêòóðû:
Ñèñòåìà ïåðèîäè÷åñêè ïðîñûïàåòñÿ è îñìàòðèâàåòñÿ
Âû÷èñëÿåò, ÷åì ìèð îòëè÷àåòñÿ îò
”
èäåàëà“
ÊàêèåEòî äàííûå ñ ÷åìEòî íå ñîãëàñîâàíû
ÊàêèåEòî ãîòîâûå ê îáðàáîòêå äàííûå åùå íå
îáðàáàòûâàþòñÿ
ÊàêèåEòî äàííûå îáðàáàòûâàþòñÿ óæå ñëèøêîì äîëãîY
íàâåðíîåD îáðàáîò÷èê óìåð
F F F
Âûïîëíÿåò äåéñòâèÿ.
Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü
Ïëþñû ïîäõîäà
”
ñèñòåìà êàê ñõîäÿùèéñÿ ïðîöåññ“:
Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü
Ïîñëåäñòâèÿ áîëüøèíñòâà ïðîáëåì ðàíî èëè ïîçäíî
èñ÷åçíóòF
Âûñîêàÿ ìîäóëüíîñòü
Ñèñòåìà ðàñïàäàåòñÿ íà íàáîð ÷èñòî ëèíåéíûõ
àâòîìàòîâE
”
îáðàáîò÷èêîâ“F
Î÷åíü ïðîñòàÿ îòëàäêà è òåñòèðîâàíèå
Åñëè ÷òîEòî íå òàê  ñèñòåìà ïðîñòî ïðèíÿëà
íåïðàâèëüíîå ðåøåíèå â îäíîì èç ñîñòîÿíèéF
ÌîæåòD ñàìî ðàññîñåòñÿD ìîæíî íå ôèêñèòü
Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü
Âûñîêàÿ óñòîé÷èâîñòü
Ñèñòåìà íåóÿçâèìà äëÿ
”
ñìåðòåëüíûõ“ áàãîâ @™orrupted
ñèíãëòîíûD óòå÷êè ðåñóðñîâAF
Ñäåëàòü ñîñòîÿíèå persistentD ïåðåçàïóñêàòü ïðîöåññF
Ãîòîâíîñòü ê ðàñïðåäåëåííîé ðàáîòå
Ñäåëàòü ñîñòîÿíèå ãëîáàëüíî âèäèìûì è îáåñïå÷èòü
ïðîñòåéøóþ áëîêèðîâêóF
Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü
Ïðèìåíèìîñòü:
Dataow-like çàäà÷è (äàííûå òåêóò ïî ñèñòåìå ñ ðÿäîì
ýòàïîâ îáðàáîòêè)
Ðåïëèêàöèÿ è ñèíõðîíèçàöèÿ
Àðáèòðàæ ðåñóðñîâ è load balancing
. . .
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
Àáñòðàãèðîâàíèå
Ìíîãîïîòî÷íóþ ïðîãðàììó íàìíîãî ëåã÷å íàïèñàòü è îòëàäèòü,
åñëè â íåé íåò íè÷åãî, êðîìå ñàìîé ñóòè.
Áàãè âûëåçàþò íà ïîâåðõíîñòü, íåò ñîáëàçíà ñêàçàòü Â íàøåé
çàäà÷å òàêàÿ ñèòóàöèÿ íåâîçìîæíà.
Àëãîðèòìû ëåã÷å îòëàæèâàòü ïî îòäåëüíîñòè.
Íå áëîêèðîâêà èíäåêñà íà ÷òåíèå èëè çàïèñü, à ïðîñòî
áëîêèðîâêà íà ÷òåíèå èëè çàïèñü
Íå î÷åðåäü e-mail'îâ, à îòêàçîóñòîé÷èâàÿ î÷åðåäü çàäà÷
Íå ïàðàëëåëüíûé ïîäñ÷åò ñëîâ, à MapReduce
Íå ïàðàëëåëüíàÿ ôèëüòðàöèÿ ìàññèâà, à ParallelArray
Ìîæåò îêàçàòüñÿ, ÷òî òàêàÿ øòóêà óæå åñòü.
Àáñòðàãèðîâàíèå
À êàêèå øòóêè óæå åñòü?
Îá ýòîì  ïîçæå.
Àáñòðàãèðîâàíèå: ïðèìåð
Ïðèâÿçêà ê âíåøíåé ñèñòåìå ñêà÷èâàíèÿ óðëîâ.
Çàäàíèÿ ïèøóòñÿ â ôàéëû
Âíåøíÿÿ ñèñòåìà èõ ïîäõâàòûâàåò
Îòâåòû òîæå ïèøóòñÿ â ôàéëû
Íàäî ïðåäîñòàâèòü àñèíõðîííûé API
void loadPage(url, onOk, onError)
Àáñòðàãèðîâàíèå: ïðèìåð
Devil in the details:
Íå çàôëóäèòü ñèñòåìó (áëîêèðîâàòüñÿ, åñëè ìíîãî çàäàíèé
”
â ïîëåòå“)
Ñëåäèòü çà òàéìàóòàìè (äîëãî íå îòâå÷àåò → onError)
Íå äîïóñêàòü ãîíîê ìåæäó îòâåòàìè è òàéìàóòàìè
Áåðå÷ü íèòêó ñëåæåíèÿ çà îòâåòàìè (âûçûâàòü
onOk,onError â îòäåëüíûõ íèòÿõ)
Îáðàáàòûâàòü ðåäèðåêòû
Àáñòðàãèðîâàíèå: ïðèìåð
Áûëî: Íåòåñòèðóåìàÿ êàøà, äåëàþùàÿ âñå ñðàçó.
Àáñòðàãèðîâàíèå: ïðèìåð
Ñòàëî:
Ñåìàôîð äëÿ îãðàíè÷åíèÿ ÷èñëà çàäàíèé
”
â ïîëåòå“
Àáñòðàêòíûé
”
áàò÷åð“
Àáñòðàêòíûé
”
ïîëëåð“
Àáñòðàêòíûé
”
òàéìàóòåð“
Âñ¼ ýëåìåíòàðíî òåñòèðóåòñÿ (íàøëèñü áàãè)
Âñ¼ ïîëåçíî è ïîâòîðíî èñïîëüçóåìî
Àáñòðàãèðîâàíèå: ïðèìåð
class BatcherT {
Batcher(int periodMs);
Stoppable start();
abstract void flush(T[] ts);
void submit(T t);
}
Àáñòðàãèðîâàíèå: ïðèìåð
class PollerT {
Poller(int periodMs);
Stoppable start();
abstract @Nullable T poll();
abstract void process(@NotNull T t);
}
Àáñòðàãèðîâàíèå: ïðèìåð
class TimeouterT {
Poller(int periodMs);
Stoppable start();
void submit(T t, int timeoutMs);
abstract void onTimedOut(T t);
}
Àáñòðàãèðîâàíèå: ïðèìåð
Èòîã: Èç áèçíåñ-ëîãèêè ïîëíîñòüþ ïðîïàë ìíîãîïîòî÷íûé êîä.
×àñòü 2. Ïàòòåðíû è ïîäõîäû.
Ñîäåðæàíèå
Êîððåêòíîñòü
Ïðè÷èíû áàãîâ
Äîêàçàòåëüñòâî êîððåêòíîñòè
Óëó÷øåíèå êîððåêòíîñòè
Ïàòòåðíû è ïîäõîäû
Ïàðàëëåëèçì
Concurrency
Cutting edge
Haskell
Erlang
.NET
Clojure
Çàêëþ÷åíèå
Ìîäåëè ìíîãîïîòî÷íûõ âû÷èñëåíèé
Ïàðàëëåëèçì:
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
Àñèíõðîííîå ïðîãðàììèðîâàíèå
MapReduce
Ñëèøêîì èçâåñòíî, ÷òîáû íà íåì îñòàíàâëèâàòüñÿ
Ðåàëèçàöèÿ äëÿ Java: Hadoop
Fork/join
Ïîõîæå íà MapReduce.
Fork: ïîäåëèòü íà òàêèå æå çàäà÷è, íî ïîìåíüøå
Âûïîëíèòü ïîäçàäà÷è ïàðàëëåëüíî
Join: Ñëèòü ðåçóëüòàòû ïîäçàäà÷
Ïðèìåðû:
Øàõìàòû: fork  âîçìîæíûå õîäû, join  âûáîð ëó÷øåãî
Óìíîæåíèå ìàòðèö: fork  ðàçáèåíèå ïî
ñòðîêàì/ñòîëáöàì, join  NOP
Èíòåãðèðîâàíèå: fork  ðàçáèåíèå îáëàñòè, join 
ñëîæåíèå
Âåêòîðíûå àëãîðèòìû
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]
Âåêòîðíûå ìîäåëè
Ïðåëåñòè:
Ñâåðòêà ïàðàëëåëèçóåòñÿ: Óñêîðåíèå O(P/log P) íà P
ïðîöåññîðàõ (â log P ðàç õóæå ëèíåéíîãî)
Ïðîáåã òàê æå ïàðàëëåëèçóåòñÿ
Óäèâèòåëüíî ìîùíûå è óíèâåðñàëüíûå îïåðàöèè
Ïðåôèêñíûå ñóììû
×òî ìîæíî ñäåëàòü ñâåðòêîé/ïðîáåãîì (ò.å. ïàðàëëåëüíî):
sum,min,max,avg,. . .
Radix sort, Quicksort
Ñëîæåíèå äëèííûõ ÷èñåë
Âûïóêëàÿ îáîëî÷êà
Ìíîãèå àëãîðèòìû íà ãðàôàõ
Ìíîãèå ðåêóððåíòíûå ïîñëåäîâàòåëüíîñòè n-ãî ïîðÿäêà
Òðåõäèàãîíàëüíûå ñèñòåìû óðàâíåíèé
. . .
Ïðåôèêñíûå ñóììû
Îñîáåííî èíòåðåñíî, êàê ýòî äåëàåòñÿ. Áàçîâûå îïåðàöèè
ïîâåðõ ïðîáåãà:
Ðåêóððåíòíàÿ ïîñëåäîâàòåëüíîñòü 1ãî ïîðÿäêà
Óïàêîâêà ìàññèâà
Ñîðòèðîâêà ìàññèâà ïî 1-áèòíîìó ôëàãó (ðàçáèåíèå)
Ñåãìåíòèðîâàííûé ïðîáåã (ïðîáåã ñî ñáðîñàìè)
Ïðåôèêñíûå ñóììû
Óïàêîâêà ìàññèâà (pack, lter).
Ïðåôèêñíûå ñóììû
Ñîðòèðîâêà ïî 1-áèòíîìó ôëàãó (ðàçáèåíèå, partition).
Radixsort òðèâèàëåí.
Ïðåôèêñíûå ñóììû
Ñåãìåíòèðîâàííûé ïðîáåã (Segmented scan).
Ïîçâîëÿåò ðåàëèçîâàòü ðåêóðñèþ áåç ðåêóðñèè.
Ïðåôèêñíûå ñóììû
 öåëîì  êðàñèâûé, ìîùíûé, ïðîñòîé â ðåàëèçàöèè è
íåîáû÷íûé âåêòîðíûé ÿçûê.
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
Message-passing concurrency
Ôàêòè÷åñêè åäèíñòâåííûé ïîäõîä â ðàñïðåäåëåííûõ ñèñòåìàõ.
Âîîáùå íåò ðàçäåëÿåìîãî ñîñòîÿíèÿ
Àêòîðû îáìåíèâàþòñÿ ñîîáùåíèÿìè
Ó êàæäîãî àêòîðà åñòü mailbox (FIFO-î÷åðåäü ñîîáùåíèé)
Îòñûëêà ñîîáùåíèé àñèíõðîííàÿ è íåáëîêèðóþùàÿ
Message-passing concurrency
Íå ïàíàöåÿ: äåäëîêè åñòü (íî äðóãèå)
Òåì íå ìåíåå, íàïèñàòü êîððåêòíóþ ïðîãðàììó  ïðîùå
Åñòü ôîðìàëüíûå ìîäåëè (CSP) ⇒ ïîääàåòñÿ
âåðèôèêàöèè
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
Message-passing concurrency
Kilim:
Ëåãêîâåñíûå íèòè (1ìëí â ïîðÿäêå âåùåé, ñâåðõáûñòðîå
ïåðåêëþ÷åíèå)
Î÷åíü áûñòðûé message passing (óòâåðæäàåòñÿ, ÷òî 3x
Erlang)
Ïîñòïðîöåññèò áàéò-êîä (CPS transform äëÿ ìåòîäîâ,
àííîòèðîâàííûõ @pausable).
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
Event loop
Âàðèàöèÿ íà òåìó message passing, íî  íå ìíîãî
âçàèìîäåéñòâóþùèõ àêòîðîâ, à îäèí (èëè íåñêîëüêî
îäèíàêîâûõ) æèðíûé è âñåìîãóùèé.
Ñåðâåðû (è accept, è select/poll/... ñþäà îòíîñÿòñÿ)
GUI-ôðåéìâîðêè
Ïðåëåñòè:
Ýòî íå ôðåéìâîðê, íî ïàòòåðí: ëåãêî ðåàëèçîâàòü è
èñïîëüçîâàòü äàæå íà ìèêðîóðîâíå
Ê íåìó ñâîäèòñÿ êó÷à çàäà÷
Î÷åíü ëåãêî ïèøåòñÿ
Áîëüøèíñòâî ìíîãîïîòî÷íûõ ïðîáëåì îòñóòñòâóþò
Event loop
private BlockingQueueOurEvent events =
new LinkedBlockingQueueOurEvent();
void mainLoop() {
while(true) {
processEvent(events.poll());
}
}
public class OurEvent {...}
Software Transactional Memory
Òðàíçàêöèè íà óðîâíå ïàìÿòè; àòîìàðíûå êóñêè êîäà.
Ïîëíîöåííûé commit/rollback, ïîëíàÿ àòîìàðíîñòü
Òðàíçàêöèè ïîâòîðÿåìû
retry ïðè êîììèòåD åñëè èçâíå èçìåíåíà ïðî÷òåííàÿ
ïåðåìåííàÿ
Òðàíçàêöèîííûå ïðîãðàììû êîìáèíèðóåìû!
 îòëè÷èå îò sh—red st—te
@ïðàâèëüíîCïðàâèëüíî=ïðàâèëüíîA
Íå äîëæíî áûòü íèêàêèõ ïîáî÷íûõ ýôôåêòîâ, êðîìå
îáðàùåíèé ê òðàíçàêöèîííîé ïàìÿòè
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;
}
Software Transactional Memory
Ïñåâäîêîä (âïåðâûå ïðåäëîæåíî â ðåàëèçàöèè â Haskell):
atomic {
if (queueSize  0) {
remove item from queue and use it
} else {
retry
}
}
retry ïåðåçàïóñêàåò òðàíçàêöèþ â ìîìåíò, êîãäà èçìåíèòñÿ
îäíà èç ïðî÷èòàííûõ åþ ïåðåìåííûõ.
Software Transactional Memory
Ðåàëèçàöèè:
Haskell: ïîëíîöåííàÿ è áåçîïàñíàÿ ïîääåðæêà
Clojure: ïîëíîöåííàÿ è íåáåçîïàñíàÿ ïîääåðæêà
Java: Deuce, JSTM, . . .
Ìíîãî áèáëèîòåê äëÿ C è C++, â ò.÷. äàæå êîìïèëÿòîðû ñ
êëþ÷åâûì ñëîâîì atomic
Íå çíàþD èñïîëüçóþò ëè èõ
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
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Íàáèðàåò îáîðîòû áëàãîäàðÿ âåáó (AJAX) è áîëüøèì
ðàñïðåäåëåííûì ñèñòåìàì, ãäå ñèíõðîííûé RPC ñëèøêîì
äîðîã.
Quite a challenge.
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Ñèíõðîííûé API:
interface API {
Answer compute(Question request) throws Whoops;
}
Àñèíõðîííûé API:
interface API {
void compute(Question request,
{Answer = void} onReady,
{Whoops = void} onWhoops)
}
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Ïðè÷èíû:
Áëîêèðóþùèå âûçîâû íåóäîáíû èëè íå ïîääåðæèâàþòñÿ
eteˆ
q…s @
”
àñèíõðîííî ïîëó÷èòü ðåçóëüòàò äèàëîãà“ è òFïFA
Àñèíõðîííûé API äîïóñêàåò áîëåå ýôôåêòèâíóþ
ðåàëèçàöèþ
Àñèíõðîííûé ââîäEâûâîä
Àñèíõðîííûé äîñòóï ê õðàíèëèùàì äàííûõ F F F
Àêòèâíàÿ ñòîðîíà @ñåðâåðD ñåòåâîé äðàéâåð ÎÑ F F F A ìîæåò
ðåøàòüD êîãäà è â êàêîì ïîðÿäêå îòâå÷àòü íà çàïðîñû
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Ïðîáëåìû:
Íåëèíåéíûé ïîòîê èñïîëíåíèÿ
Î÷åíü íåóäîáíî îòëàæèâàòü
Ïîøàãîâîå âûïîëíåíèå â îòëàä÷èêå äåëàåò íå òî
Íåò àíàëîãîâ ïðèâû÷íûõ êîíñòðóêöèé óïðàâëåíèÿ (öèêëû,
try..finally . . . )
Äàæå ñýìóëèðîâàòü èõ íåëåãêî
 áîëüøèíñòâå ßÏ àñèíõðîííûé êîä êðàéíå ãðîìîçäîê
Àñèíõðîííîå ïðîãðàììèðîâàíèå
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.
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Êàê æå áûòü?
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Êàê æå áûòü? Âñïîìèíàåì óðîêè ôóíêöèîíàëüíîãî
ïðîãðàììèðîâàíèÿ.
Èçáàâèòüñÿ îò ñèíòàêñè÷åñêîãî ìóñîðà
Àñèíõðîííûå çíà÷åíèÿ  ïåðâîêëàññíûå îáúåêòû @ñìF
äàëååA
Íóæåí ÿçûê ñ çàìûêàíèÿìèF ƒorry guysF
Ðåàëèçîâàòü ñòðóêòóðû óïðàâëåíèÿ
Íå ñîéòè ñ óìà îò ñëîæíîñòè
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Êàê æå áûòü? Âñïîìèíàåì óðîêè ôóíêöèîíàëüíîãî
ïðîãðàììèðîâàíèÿ.
Èçáàâèòüñÿ îò ñèíòàêñè÷åñêîãî ìóñîðà
Ðåàëèçîâàòü ñòðóêòóðû óïðàâëåíèÿ
 âèäå ôóíêöèé âûñøåãî ïîðÿäêà
Öèêëû ÷åðåç ðåêóðñèþ
Ýìóëÿöèÿ õâîñòîâûõ âûçîâîâ
Âñå ýòî ñòîèò àáñòðàãèðîâàòü â
”
êîìáèí¡àòîðíóþ
áèáëèîòåêó“
Íå ñîéòè ñ óìà îò ñëîæíîñòè
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Êàê æå áûòü? Âñïîìèíàåì óðîêè ôóíêöèîíàëüíîãî
ïðîãðàììèðîâàíèÿ.
Èçáàâèòüñÿ îò ñèíòàêñè÷åñêîãî ìóñîðà
Ðåàëèçîâàòü ñòðóêòóðû óïðàâëåíèÿ
Íå ñîéòè ñ óìà îò ñëîæíîñòè
Öåëûé êëàññ ïðîáëåìD ñïåöèôè÷íûõ äëÿ ýòîãî ïîäõîäà
Áîëüøèíñòâî ñâÿçàíî ñ mut—˜le st—te
Íåèññëåäîâàííàÿ îáëàñòüc
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Once again:
interface AsyncT {
void run(CallbackT onOk, CallbackThrowable onError);
}
Ýòè îáúåêòû êîìáèíèðóåìû.
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Ó÷èìñÿ ó .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
Àñèíõðîííîå ïðîãðàììèðîâàíèå
class AsyncPrimitives {
AsyncT succeed(T value) {...}
AsyncT failwith(Throwable error) {...}
AsyncU bind(AsyncT at, FuncT,AsyncU fau) {...}
}
Ýòîãî äîñòàòî÷íî äëÿ áîëüøèíñòâà ñòðóêòóð óïðàâëåíèÿ
1.
Ýòî íàçûâàåòñÿ
”
ìîíàäà“.
1
Ïðè ïîääåðæêå îïòèìèçàöèè õâîñòîâûõ âûçîâîâ
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Ìîíàäû ïðîíèêëè â ìåéíñòðèì: ó 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
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Ìîíàäû ïðîíèêëè â ìåéíñòðèì: ó 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
Àñèíõðîííîå ïðîãðàììèðîâàíèå
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
Further reading
Ðàçíûå ïàòòåðíû ìíîãîïîòî÷íîãî è ðàñïðåäåëåííîãî
ïðîãðàììèðîâàíèÿ. Î÷åíü ìíîãî è èíòåðåñíî.
http://www.cs.wustl.edu/~schmidt/patterns-ace.html
http:
//parlab.eecs.berkeley.edu/wiki/patterns/patterns 
åùå êðó÷å
Ñîäåðæàíèå
Êîððåêòíîñòü
Ïðè÷èíû áàãîâ
Äîêàçàòåëüñòâî êîððåêòíîñòè
Óëó÷øåíèå êîððåêòíîñòè
Ïàòòåðíû è ïîäõîäû
Ïàðàëëåëèçì
Concurrency
Cutting edge
Haskell
Erlang
.NET
Clojure
Çàêëþ÷åíèå
Cutting edge
×òî óìååò Haskell:
Âñå ïîáî÷íûå ýôôåêòû êîíòðîëèðóþòñÿ
Íåò íåêîíòðîëèðóåìûõ ïðîáëåì èç-çà èõ íàëè÷èÿ
Ïîçâîëÿåò íåìûñëèìûå â äðóãèõ ÿçûêàõ âåùè
Cutting edge
×òî óìååò Haskell:
Ñàìûå áûñòðûå â ìèðå ëåãêîâåñíûå íèòè è ïðèìèòèâû
ñèíõðîíèçàöèè
I ìåñòî íà v—ngu—ge ƒhootoutD THx áûñòðåå íàòèâíûõ
…˜untuD Sõ áûñòðåå irl—ng3
Ïàðàëëåëüíûå ñòðàòåãèè
Ïðîñòûå ïàðàëëåëüíûå âû÷èñëåíèÿX íåò àíàëîãîâ â äðóãèõ
ÿçûêàõ
Data Parallel Haskell
Àâòîìàòè÷åñêè ðàñïàðàëëåëèâàåìûå âåêòîðíûå
âû÷èñëåíèÿ
Òðàíçàêöèîííàÿ ïàìÿòü
Ðàáîòà â íàïðàâëåíèè GPU
Ìîùíûå áèáëèîòåêè
Ëåãêîâåñíûå íèòè
Nothing special, ïðîñòî î÷åíü áûñòðûå è ïî÷òè 0
ñèíòàêñè÷åñêîãî îâåðõåäà.
C++0x futures/promises and more â 60 ñòðîê.
Ïàðàëëåëüíûå ñòðàòåãèè
Ëåíèâîñòü ïîçâîëÿåò îòäåëèòü àëãîðèòì è ñïîñîá
ðàñïàðàëëåëèâàíèÿ.
Ðåçóëüòàò àëãîðèòìà  ñòðóêòóðà, ïîëíàÿ
”
îáåùàíèé“.
Îáåùàíèÿ
”
èñïîëíÿþòñÿ“ (ôîðñèðóþòñÿ) ñ ïîìîùüþ
ñòðàòåãèè.
Ñòðàòåãèÿ  ýòî îáûêíîâåííàÿ, ïðîñòàÿ ôóíêöèÿ.
Èäåÿ  ÿäåðíàÿ. Ýòî ìîæíî ðåàëèçîâàòü è íà Java, åñëè
Ïàðàëëåëüíûå ñòðàòåãèè
Íàïðèìåð, ñòðàòåãèÿ
”
ïàðàëëåëüíî ôîðñèðîâàòü âñå ýëåìåíòû
ñïèñêà“:
parList :: Strategy a - Strategy [a]
parList strat [] = ()
parList strat (x:xs) = strat x `par` (parList strat xs)
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  ñëàéäû
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:] :]
Âåêòîðèçóåòñÿ è ïàðàëëåëèçóåòñÿ.
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
Òðàíçàêöèîííàÿ ïàìÿòü
transfer :: Account - Account - Int - IO ()
transfer from to amount = atomically do
deposit to amount
withdraw from amount
Òðàíçàêöèîííàÿ ïàìÿòü
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 (íàîáîðîò íåëüçÿ)
Erlang
Ñâÿçü ïðîöåññîâ òîëüêî ÷åðåç îáìåí ñîîáùåíèÿìè.
Selective receive (èçáèðàòåëüíàÿ âûáîðêà èç mailbox).
Ìîùíàÿ ôè÷àF
Ïðîçðà÷íàÿ ðàñïðåäåëåííîñòü.
Î÷åíü ýôôåêòèâíàÿ ðåàëèçàöèÿ íèòåé è message passing.
Î÷åíü êðóòàÿ è ïðîäóìàííàÿ èíôðàñòðóêòóðà.
Î÷åíü ïðîñòîé ÿçûê.
Àêòèâíî ïðèìåíÿåòñÿ â èíäóñòðèè (â ò.÷. Amazon,
Facebook, Yahoo, . . . ).
http://spbhug.folding-maps.org/wiki/Erlang  ñàìîïèàð YA
F#
Asynchronous workows: óæå ðàññìîòðåëè.
C#
Asynchronous LINQ (ìîæíî ñäåëàòü ñàìîìó: LINQ =
ìîíàäû)
Óæå ðàññìîòðåëè
Parallel LINQ
Parallel LINQ (PLINQ)
IEnumerableT, IParallelEnumerableT
AsParallel
http://msdn.microsoft.com/en-us/magazine/cc163329.aspx
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} è ò.ï.
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);
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
Atoms
Áîëåå èëè ìåíåå îáû÷íûå atomic ïåðåìåííûå.
(swap! atom f)
”
Àòîìàðíî çàìåíèòü x íà f (x), âåðíóòü
ñòàðûé x (compare-and-exchange)“
f îáÿçàíà áûòü ÷èñòîé: åå ìîãóò âûçâàòü
íåñêîëüêî ðàç
http://clojure.org/atoms
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
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
Refs
Òðàíçàêöèîííàÿ ïàìÿòü (STM).
Äîâîëüíî îáû÷íàÿ
Òðàíçàêöèè äîëæíû áûòü áåç ïîáî÷íûõ ýôôåêòîâ
Ëþáîïûòíî: (commute x f): çàìåíèòü x íà f (x),
ïðåäïîëàãàÿ ÷òî f êîììóòèðóåò ñ îñòàëüíûìè.
ÍàïðèìåðD (commute counter inc)  ïîäîéäåò
Ðàáîòàåò ñëåãêà áûñòðååD ÷åì äðóãèå ôóíêöèèEìóòàòîðû
http://clojure.org/refs
Ñîäåðæàíèå
Êîððåêòíîñòü
Ïðè÷èíû áàãîâ
Äîêàçàòåëüñòâî êîððåêòíîñòè
Óëó÷øåíèå êîððåêòíîñòè
Ïàòòåðíû è ïîäõîäû
Ïàðàëëåëèçì
Concurrency
Cutting edge
Haskell
Erlang
.NET
Clojure
Çàêëþ÷åíèå
×òî áûëî
Êëàññèôèêàöèÿ ìíîãîïîòî÷íûõ ïðîãðàìì
Ôîðìàëüíûå ìåòîäû (LTL) è òóëû (SPIN,JPF,CheckThread)
Êîððåêòíîñòü: èíêàïñóëÿöèÿ, âûñîêîóðîâíåâûå îïåðàöèè,
ôàêòîðèçàöèÿ, äåäëîêè, àòîìàðíûå è èäåìïîòåíòíûå
îïåðàöèè, îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü
Ìåòîäèêè: fork/join, âåêòîðíûå àëãîðèòìû,
message-passing, event-driven, STM, àñèíõðîííîå
ïðîãðàììèðîâàíèå
Haskell: ëåãêèå íèòè, ïàðàëëåëüíûå ñòðàòåãèè,
âåêòîðèçàöèÿ, STM
Erlang: ìîùíàÿ èíôðàñòðóêòóðà
Clojure: Atoms, Vars, Agents, Refs
C#: PLINQ
×åãî íå áûëî
Ðàñïðåäåëåíùèíà
gonsensusD P€gD ve—der ele™tionF F F
hr„ et™F
wess—ging p—tterns
Íåáëîêèðóþùèå àëãîðèòìû
„here9s more to itF
The end
Ñïàñèáî! Âîïðîñû?

More Related Content

Viewers also liked

Endangered species
Endangered speciesEndangered species
Endangered species
Sarah Buckmaster
 
01 lb report_presentation
01 lb report_presentation01 lb report_presentation
01 lb report_presentation
Zla Nala
 
Social Media Board 2010
Social Media Board 2010Social Media Board 2010
Social Media Board 2010
Pace
 
Key note Manish and Deepa
Key note Manish and DeepaKey note Manish and Deepa
Key note Manish and Deepa
vodQA
 
Why Average Response Time is not a right measure of your web application's pe...
Why Average Response Time is not a right measure of your web application's pe...Why Average Response Time is not a right measure of your web application's pe...
Why Average Response Time is not a right measure of your web application's pe...
vodQA
 
Checkmyschool presentation bbl
Checkmyschool presentation bblCheckmyschool presentation bbl
Checkmyschool presentation bbl
Jhon Manuncia
 
Me gusta tejer
Me gusta tejerMe gusta tejer
Me gusta tejer
Laura De Isla
 
Power point 5 media
Power point 5 mediaPower point 5 media
Power point 5 media
jackthompson
 
Czy opłaciło się nam wejść do unii europejskiej
Czy opłaciło się nam wejść do unii europejskiejCzy opłaciło się nam wejść do unii europejskiej
Czy opłaciło się nam wejść do unii europejskiejsknsz
 
Power point 3 media
Power point 3 mediaPower point 3 media
Power point 3 media
jackthompson
 
Web
WebWeb
Web
Anam
 
Pengajaran adalah proses di mana kegiata
Pengajaran adalah proses di mana kegiataPengajaran adalah proses di mana kegiata
Pengajaran adalah proses di mana kegiataMohd Fahiz
 
MOSER BAER
MOSER BAERMOSER BAER
MOSER BAER
Deepavali Vankalu
 
Estrategias para publicaciones internacionales mesa de investigaciones
Estrategias para publicaciones internacionales mesa de investigacionesEstrategias para publicaciones internacionales mesa de investigaciones
Estrategias para publicaciones internacionales mesa de investigaciones
Universidad Técnica de Manabí
 
2004 este general
2004 este general2004 este general
2004 este general
Anam
 
Pr1
Pr1Pr1
Pr1
Anam
 
The Other Half of WWII
The Other Half of WWIIThe Other Half of WWII
The Other Half of WWII
Eddie Koelzer
 

Viewers also liked (20)

Endangered species
Endangered speciesEndangered species
Endangered species
 
01 lb report_presentation
01 lb report_presentation01 lb report_presentation
01 lb report_presentation
 
Social Media Board 2010
Social Media Board 2010Social Media Board 2010
Social Media Board 2010
 
Key note Manish and Deepa
Key note Manish and DeepaKey note Manish and Deepa
Key note Manish and Deepa
 
Why Average Response Time is not a right measure of your web application's pe...
Why Average Response Time is not a right measure of your web application's pe...Why Average Response Time is not a right measure of your web application's pe...
Why Average Response Time is not a right measure of your web application's pe...
 
3 d tv
3 d tv3 d tv
3 d tv
 
Checkmyschool presentation bbl
Checkmyschool presentation bblCheckmyschool presentation bbl
Checkmyschool presentation bbl
 
Me gusta tejer
Me gusta tejerMe gusta tejer
Me gusta tejer
 
Power point 5 media
Power point 5 mediaPower point 5 media
Power point 5 media
 
Czy opłaciło się nam wejść do unii europejskiej
Czy opłaciło się nam wejść do unii europejskiejCzy opłaciło się nam wejść do unii europejskiej
Czy opłaciło się nam wejść do unii europejskiej
 
Power point 3 media
Power point 3 mediaPower point 3 media
Power point 3 media
 
Web
WebWeb
Web
 
55ph
55ph55ph
55ph
 
Pengajaran adalah proses di mana kegiata
Pengajaran adalah proses di mana kegiataPengajaran adalah proses di mana kegiata
Pengajaran adalah proses di mana kegiata
 
MOSER BAER
MOSER BAERMOSER BAER
MOSER BAER
 
Presentation3
Presentation3Presentation3
Presentation3
 
Estrategias para publicaciones internacionales mesa de investigaciones
Estrategias para publicaciones internacionales mesa de investigacionesEstrategias para publicaciones internacionales mesa de investigaciones
Estrategias para publicaciones internacionales mesa de investigaciones
 
2004 este general
2004 este general2004 este general
2004 este general
 
Pr1
Pr1Pr1
Pr1
 
The Other Half of WWII
The Other Half of WWIIThe Other Half of WWII
The Other Half of WWII
 

More from Siel01

Евгений Кирпичёв Многопоточное программирование (Full)
Евгений Кирпичёв   Многопоточное программирование (Full)Евгений Кирпичёв   Многопоточное программирование (Full)
Евгений Кирпичёв Многопоточное программирование (Full)Siel01
 
Макс Лапшин Erlyvideo
Макс Лапшин   ErlyvideoМакс Лапшин   Erlyvideo
Макс Лапшин ErlyvideoSiel01
 
Никита Фролов Разработка приложений под iPhone
Никита Фролов   Разработка приложений под iPhoneНикита Фролов   Разработка приложений под iPhone
Никита Фролов Разработка приложений под iPhoneSiel01
 
Михаил Черномордиков Ie9
Михаил Черномордиков   Ie9Михаил Черномордиков   Ie9
Михаил Черномордиков Ie9Siel01
 
Олег Царев, Кирилл Коринский Сравнительный анализ хранилищ данных
Олег Царев, Кирилл Коринский   Сравнительный анализ хранилищ данныхОлег Царев, Кирилл Коринский   Сравнительный анализ хранилищ данных
Олег Царев, Кирилл Коринский Сравнительный анализ хранилищ данныхSiel01
 
Ольга Кочкина Что творится на рынке труда в сфере IT
Ольга Кочкина Что творится на рынке труда в сфере ITОльга Кочкина Что творится на рынке труда в сфере IT
Ольга Кочкина Что творится на рынке труда в сфере IT
Siel01
 
Николай Мациевский Насколько открыт Open source ADD-2010
Николай Мациевский   Насколько открыт Open source ADD-2010Николай Мациевский   Насколько открыт Open source ADD-2010
Николай Мациевский Насколько открыт Open source ADD-2010
Siel01
 

More from Siel01 (7)

Евгений Кирпичёв Многопоточное программирование (Full)
Евгений Кирпичёв   Многопоточное программирование (Full)Евгений Кирпичёв   Многопоточное программирование (Full)
Евгений Кирпичёв Многопоточное программирование (Full)
 
Макс Лапшин Erlyvideo
Макс Лапшин   ErlyvideoМакс Лапшин   Erlyvideo
Макс Лапшин Erlyvideo
 
Никита Фролов Разработка приложений под iPhone
Никита Фролов   Разработка приложений под iPhoneНикита Фролов   Разработка приложений под iPhone
Никита Фролов Разработка приложений под iPhone
 
Михаил Черномордиков Ie9
Михаил Черномордиков   Ie9Михаил Черномордиков   Ie9
Михаил Черномордиков Ie9
 
Олег Царев, Кирилл Коринский Сравнительный анализ хранилищ данных
Олег Царев, Кирилл Коринский   Сравнительный анализ хранилищ данныхОлег Царев, Кирилл Коринский   Сравнительный анализ хранилищ данных
Олег Царев, Кирилл Коринский Сравнительный анализ хранилищ данных
 
Ольга Кочкина Что творится на рынке труда в сфере IT
Ольга Кочкина Что творится на рынке труда в сфере ITОльга Кочкина Что творится на рынке труда в сфере IT
Ольга Кочкина Что творится на рынке труда в сфере IT
 
Николай Мациевский Насколько открыт Open source ADD-2010
Николай Мациевский   Насколько открыт Open source ADD-2010Николай Мациевский   Насколько открыт Open source ADD-2010
Николай Мациевский Насколько открыт Open source ADD-2010
 

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

  • 1. Ìíîãîïîòî÷íîå ïðîãðàììèðîâàíèå Êîððåêòíîñòü, ïàòòåðíû, ïîäõîäû Åâãåíèé Êèðïè÷¼â 24 ñåíòÿáðÿ 2010 ã.
  • 2. Öåëü äîêëàäà Ðàñøèðèòü êðóãîçîð â îáëàñòè ìíîãîïîòî÷íîãî ïðîãðàììèðîâàíèÿ âîîáùå. Êîððåêòíîñòü Êàê ñôîðìóëèðîâàòüD ïîâûñèòüD ãàðàíòèðîâàòü Èíñòðóìåíòû Ïàòòåðíû è âåëîñèïåäû Ïîäõîäû è ôèøêè ðàçíûõ ÿçûêîâ
  • 3. Êëàññèôèêàöèÿ ìíîãîïîòî÷íûõ ïðîãðàìì Parallelism vs Concurrency Parallel Îäíà çàäà÷à áüåòñÿ íà ìíîãî ÷àñòåé Concurrent Ìíîãî ðàçíûõ çàäà÷ (ñëîæíåå) Ñåãîäíÿ â îñíîâíîì î concurrency.
  • 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.
  • 11. Ôîðìàëüíûå ìåòîäû À çà÷åì òîãäà îíè âîîáùå íóæíû? ×òîáû îïèñûâàòü ñèñòåìó ïîëóôîðìàëüíî ×òîáû ÷óÿòü: ôîðìàëèçóåìà ëè ñèñòåìà â ïðèíöèïå? Åñëè íåò @ñèñòåìà ñëèøêîì çàïóòàíàA î êîððåêòíîñòè ìîæíî çàáûòüF
  • 12. Ôîðìàëüíûå ìåòîäû Ìîé îïûò: äîñòàòî÷íî ïîïûòàòüñÿ ôîðìàëèçîâàòü ñèñòåìó: Âñïëûâàþò ïðîòèâîðå÷èÿ, íåäîãîâîðêè â òðåáîâàíèÿõ Âûäåëÿþòñÿ êîìïîíåíòû áåç ÷åòêîé ñïåöèôèêàöèè ÁëàæåíD êòî âåðóåòD ÷òî îíè ” è òàê“ ðàáîòàþò
  • 13. Ôîðìàëüíûå ìåòîäû ×òî æå ýòî çà ìåòîäû? Íàïðèìåð, ëèíåéíàÿ òåìïîðàëüíàÿ ëîãèêà.
  • 14. ×òî òàêîå LTL Ëèíåéíàÿ òåìïîðàëüíàÿ ëîãèêà ñïîñîá ðàññóæäàòü î ïîñëåäîâàòåëüíîñòÿõ ñîáûòèé. Ïðîãðàììà ìîäåëèðóåòñÿ àâòîìàòîì ( ” ñòðóêòóðîé Êðèïêå“). Èññëåäóþòñÿ âîçìîæíûå ïîñëåäîâàòåëüíîñòè ñîñòîÿíèé.
  • 15. Çà÷åì LTL â ýòîì äîêëàäå ×òîáû ëó÷øå ôîðìóëèðîâàòü ñâîéñòâà ñâîèõ ïðîãðàìì. ×òîáû, â êðàéíåì ñëó÷àå, ñóìåòü èõ äîêàçàòü. Âðó÷íóþ Èëè èíñòðóìåíòàìè
  • 16. Ñòðóêòóðà Êðèïêå Ñòðóêòóðà Êðèïêå ≈ ãðàô ñîñòîÿíèé. Ìíîæåñòâî ñîñòîÿíèé Íåêîòîðûå íà÷àëüíûå Íåêîòîðûå ñîåäèíåíû ïåðåõîäîì Ïåðåõîä áåçóñëîâíûé Ìíîæåñòâî ôàêòîâ  êàæäîì ñîñòîÿíèè âåðíû íåêîòîðûå ôàêòû.
  • 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
  • 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.
  • 53. Àáñòðàãèðîâàíèå: ïðèìåð Devil in the details: Íå çàôëóäèòü ñèñòåìó (áëîêèðîâàòüñÿ, åñëè ìíîãî çàäàíèé ” â ïîëåòå“) Ñëåäèòü çà òàéìàóòàìè (äîëãî íå îòâå÷àåò → onError) Íå äîïóñêàòü ãîíîê ìåæäó îòâåòàìè è òàéìàóòàìè Áåðå÷ü íèòêó ñëåæåíèÿ çà îòâåòàìè (âûçûâàòü onOk,onError â îòäåëüíûõ íèòÿõ) Îáðàáàòûâàòü ðåäèðåêòû
  • 55.
  • 56. Àáñòðàãèðîâàíèå: ïðèìåð Ñòàëî: Ñåìàôîð äëÿ îãðàíè÷åíèÿ ÷èñëà çàäàíèé ” â ïîëåòå“ Àáñòðàêòíûé ” áàò÷åð“ Àáñòðàêòíûé ” ïîëëåð“ Àáñòðàêòíûé ” òàéìàóòåð“ Âñ¼ ýëåìåíòàðíî òåñòèðóåòñÿ (íàøëèñü áàãè) Âñ¼ ïîëåçíî è ïîâòîðíî èñïîëüçóåìî
  • 57. Àáñòðàãèðîâàíèå: ïðèìåð class BatcherT { Batcher(int periodMs); Stoppable start(); abstract void flush(T[] ts); void submit(T t); }
  • 58. Àáñòðàãèðîâàíèå: ïðèìåð class PollerT { Poller(int periodMs); Stoppable start(); abstract @Nullable T poll(); abstract void process(@NotNull T t); }
  • 59. Àáñòðàãèðîâàíèå: ïðèìåð class TimeouterT { Poller(int periodMs); Stoppable start(); void submit(T t, int timeoutMs); abstract void onTimedOut(T t); }
  • 60. Àáñòðàãèðîâàíèå: ïðèìåð Èòîã: Èç áèçíåñ-ëîãèêè ïîëíîñòüþ ïðîïàë ìíîãîïîòî÷íûé êîä.
  • 61. ×àñòü 2. Ïàòòåðíû è ïîäõîäû.
  • 62. Ñîäåðæàíèå Êîððåêòíîñòü Ïðè÷èíû áàãîâ Äîêàçàòåëüñòâî êîððåêòíîñòè Óëó÷øåíèå êîððåêòíîñòè Ïàòòåðíû è ïîäõîäû Ïàðàëëåëèçì Concurrency Cutting edge Haskell Erlang .NET Clojure Çàêëþ÷åíèå
  • 63. Ìîäåëè ìíîãîïîòî÷íûõ âû÷èñëåíèé Ïàðàëëåëèçì: 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 Àñèíõðîííîå ïðîãðàììèðîâàíèå
  • 64. MapReduce Ñëèøêîì èçâåñòíî, ÷òîáû íà íåì îñòàíàâëèâàòüñÿ Ðåàëèçàöèÿ äëÿ Java: Hadoop
  • 65. Fork/join Ïîõîæå íà MapReduce. Fork: ïîäåëèòü íà òàêèå æå çàäà÷è, íî ïîìåíüøå Âûïîëíèòü ïîäçàäà÷è ïàðàëëåëüíî Join: Ñëèòü ðåçóëüòàòû ïîäçàäà÷ Ïðèìåðû: Øàõìàòû: fork âîçìîæíûå õîäû, join âûáîð ëó÷øåãî Óìíîæåíèå ìàòðèö: fork ðàçáèåíèå ïî ñòðîêàì/ñòîëáöàì, join NOP Èíòåãðèðîâàíèå: fork ðàçáèåíèå îáëàñòè, join ñëîæåíèå
  • 66. Âåêòîðíûå àëãîðèòìû 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]
  • 67. Âåêòîðíûå ìîäåëè Ïðåëåñòè: Ñâåðòêà ïàðàëëåëèçóåòñÿ: Óñêîðåíèå O(P/log P) íà P ïðîöåññîðàõ (â log P ðàç õóæå ëèíåéíîãî) Ïðîáåã òàê æå ïàðàëëåëèçóåòñÿ Óäèâèòåëüíî ìîùíûå è óíèâåðñàëüíûå îïåðàöèè
  • 68. Ïðåôèêñíûå ñóììû ×òî ìîæíî ñäåëàòü ñâåðòêîé/ïðîáåãîì (ò.å. ïàðàëëåëüíî): sum,min,max,avg,. . . Radix sort, Quicksort Ñëîæåíèå äëèííûõ ÷èñåë Âûïóêëàÿ îáîëî÷êà Ìíîãèå àëãîðèòìû íà ãðàôàõ Ìíîãèå ðåêóððåíòíûå ïîñëåäîâàòåëüíîñòè n-ãî ïîðÿäêà Òðåõäèàãîíàëüíûå ñèñòåìû óðàâíåíèé . . .
  • 69. Ïðåôèêñíûå ñóììû Îñîáåííî èíòåðåñíî, êàê ýòî äåëàåòñÿ. Áàçîâûå îïåðàöèè ïîâåðõ ïðîáåãà: Ðåêóððåíòíàÿ ïîñëåäîâàòåëüíîñòü 1ãî ïîðÿäêà Óïàêîâêà ìàññèâà Ñîðòèðîâêà ìàññèâà ïî 1-áèòíîìó ôëàãó (ðàçáèåíèå) Ñåãìåíòèðîâàííûé ïðîáåã (ïðîáåã ñî ñáðîñàìè)
  • 71. Ïðåôèêñíûå ñóììû Ñîðòèðîâêà ïî 1-áèòíîìó ôëàãó (ðàçáèåíèå, partition). Radixsort òðèâèàëåí.
  • 72. Ïðåôèêñíûå ñóììû Ñåãìåíòèðîâàííûé ïðîáåã (Segmented scan). Ïîçâîëÿåò ðåàëèçîâàòü ðåêóðñèþ áåç ðåêóðñèè.
  • 73. Ïðåôèêñíûå ñóììû  öåëîì êðàñèâûé, ìîùíûé, ïðîñòîé â ðåàëèçàöèè è íåîáû÷íûé âåêòîðíûé ÿçûê. 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
  • 74. Message-passing concurrency Ôàêòè÷åñêè åäèíñòâåííûé ïîäõîä â ðàñïðåäåëåííûõ ñèñòåìàõ. Âîîáùå íåò ðàçäåëÿåìîãî ñîñòîÿíèÿ Àêòîðû îáìåíèâàþòñÿ ñîîáùåíèÿìè Ó êàæäîãî àêòîðà åñòü mailbox (FIFO-î÷åðåäü ñîîáùåíèé) Îòñûëêà ñîîáùåíèé àñèíõðîííàÿ è íåáëîêèðóþùàÿ
  • 75. Message-passing concurrency Íå ïàíàöåÿ: äåäëîêè åñòü (íî äðóãèå) Òåì íå ìåíåå, íàïèñàòü êîððåêòíóþ ïðîãðàììó ïðîùå Åñòü ôîðìàëüíûå ìîäåëè (CSP) ⇒ ïîääàåòñÿ âåðèôèêàöèè
  • 76. 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
  • 77. Message-passing concurrency Kilim: Ëåãêîâåñíûå íèòè (1ìëí â ïîðÿäêå âåùåé, ñâåðõáûñòðîå ïåðåêëþ÷åíèå) Î÷åíü áûñòðûé message passing (óòâåðæäàåòñÿ, ÷òî 3x Erlang) Ïîñòïðîöåññèò áàéò-êîä (CPS transform äëÿ ìåòîäîâ, àííîòèðîâàííûõ @pausable).
  • 78. 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
  • 79. Event loop Âàðèàöèÿ íà òåìó message passing, íî íå ìíîãî âçàèìîäåéñòâóþùèõ àêòîðîâ, à îäèí (èëè íåñêîëüêî îäèíàêîâûõ) æèðíûé è âñåìîãóùèé. Ñåðâåðû (è accept, è select/poll/... ñþäà îòíîñÿòñÿ) GUI-ôðåéìâîðêè Ïðåëåñòè: Ýòî íå ôðåéìâîðê, íî ïàòòåðí: ëåãêî ðåàëèçîâàòü è èñïîëüçîâàòü äàæå íà ìèêðîóðîâíå Ê íåìó ñâîäèòñÿ êó÷à çàäà÷ Î÷åíü ëåãêî ïèøåòñÿ Áîëüøèíñòâî ìíîãîïîòî÷íûõ ïðîáëåì îòñóòñòâóþò
  • 80. Event loop private BlockingQueueOurEvent events = new LinkedBlockingQueueOurEvent(); void mainLoop() { while(true) { processEvent(events.poll()); } } public class OurEvent {...}
  • 81. Software Transactional Memory Òðàíçàêöèè íà óðîâíå ïàìÿòè; àòîìàðíûå êóñêè êîäà. Ïîëíîöåííûé commit/rollback, ïîëíàÿ àòîìàðíîñòü Òðàíçàêöèè ïîâòîðÿåìû retry ïðè êîììèòåD åñëè èçâíå èçìåíåíà ïðî÷òåííàÿ ïåðåìåííàÿ Òðàíçàêöèîííûå ïðîãðàììû êîìáèíèðóåìû!  îòëè÷èå îò sh—red st—te @ïðàâèëüíîCïðàâèëüíî=ïðàâèëüíîA Íå äîëæíî áûòü íèêàêèõ ïîáî÷íûõ ýôôåêòîâ, êðîìå îáðàùåíèé ê òðàíçàêöèîííîé ïàìÿòè
  • 82. 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; }
  • 83. Software Transactional Memory Ïñåâäîêîä (âïåðâûå ïðåäëîæåíî â ðåàëèçàöèè â Haskell): atomic { if (queueSize 0) { remove item from queue and use it } else { retry } } retry ïåðåçàïóñêàåò òðàíçàêöèþ â ìîìåíò, êîãäà èçìåíèòñÿ îäíà èç ïðî÷èòàííûõ åþ ïåðåìåííûõ.
  • 84. Software Transactional Memory Ðåàëèçàöèè: Haskell: ïîëíîöåííàÿ è áåçîïàñíàÿ ïîääåðæêà Clojure: ïîëíîöåííàÿ è íåáåçîïàñíàÿ ïîääåðæêà Java: Deuce, JSTM, . . . Ìíîãî áèáëèîòåê äëÿ C è C++, â ò.÷. äàæå êîìïèëÿòîðû ñ êëþ÷åâûì ñëîâîì atomic Íå çíàþD èñïîëüçóþò ëè èõ
  • 85. 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
  • 86. Àñèíõðîííîå ïðîãðàììèðîâàíèå Íàáèðàåò îáîðîòû áëàãîäàðÿ âåáó (AJAX) è áîëüøèì ðàñïðåäåëåííûì ñèñòåìàì, ãäå ñèíõðîííûé RPC ñëèøêîì äîðîã. Quite a challenge.
  • 87. Àñèíõðîííîå ïðîãðàììèðîâàíèå Ñèíõðîííûé API: interface API { Answer compute(Question request) throws Whoops; } Àñèíõðîííûé API: interface API { void compute(Question request, {Answer = void} onReady, {Whoops = void} onWhoops) }
  • 88. Àñèíõðîííîå ïðîãðàììèðîâàíèå Ïðè÷èíû: Áëîêèðóþùèå âûçîâû íåóäîáíû èëè íå ïîääåðæèâàþòñÿ eteˆ q…s @ ” àñèíõðîííî ïîëó÷èòü ðåçóëüòàò äèàëîãà“ è òFïFA Àñèíõðîííûé API äîïóñêàåò áîëåå ýôôåêòèâíóþ ðåàëèçàöèþ Àñèíõðîííûé ââîäEâûâîä Àñèíõðîííûé äîñòóï ê õðàíèëèùàì äàííûõ F F F Àêòèâíàÿ ñòîðîíà @ñåðâåðD ñåòåâîé äðàéâåð ÎÑ F F F A ìîæåò ðåøàòüD êîãäà è â êàêîì ïîðÿäêå îòâå÷àòü íà çàïðîñû
  • 89. Àñèíõðîííîå ïðîãðàììèðîâàíèå Ïðîáëåìû: Íåëèíåéíûé ïîòîê èñïîëíåíèÿ Î÷åíü íåóäîáíî îòëàæèâàòü Ïîøàãîâîå âûïîëíåíèå â îòëàä÷èêå äåëàåò íå òî Íåò àíàëîãîâ ïðèâû÷íûõ êîíñòðóêöèé óïðàâëåíèÿ (öèêëû, try..finally . . . ) Äàæå ñýìóëèðîâàòü èõ íåëåãêî  áîëüøèíñòâå ßÏ àñèíõðîííûé êîä êðàéíå ãðîìîçäîê
  • 90. Àñèíõðîííîå ïðîãðàììèðîâàíèå 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.
  • 92. Àñèíõðîííîå ïðîãðàììèðîâàíèå Êàê æå áûòü? Âñïîìèíàåì óðîêè ôóíêöèîíàëüíîãî ïðîãðàììèðîâàíèÿ. Èçáàâèòüñÿ îò ñèíòàêñè÷åñêîãî ìóñîðà Àñèíõðîííûå çíà÷åíèÿ ïåðâîêëàññíûå îáúåêòû @ñìF äàëååA Íóæåí ÿçûê ñ çàìûêàíèÿìèF ƒorry guysF Ðåàëèçîâàòü ñòðóêòóðû óïðàâëåíèÿ Íå ñîéòè ñ óìà îò ñëîæíîñòè
  • 93. Àñèíõðîííîå ïðîãðàììèðîâàíèå Êàê æå áûòü? Âñïîìèíàåì óðîêè ôóíêöèîíàëüíîãî ïðîãðàììèðîâàíèÿ. Èçáàâèòüñÿ îò ñèíòàêñè÷åñêîãî ìóñîðà Ðåàëèçîâàòü ñòðóêòóðû óïðàâëåíèÿ  âèäå ôóíêöèé âûñøåãî ïîðÿäêà Öèêëû ÷åðåç ðåêóðñèþ Ýìóëÿöèÿ õâîñòîâûõ âûçîâîâ Âñå ýòî ñòîèò àáñòðàãèðîâàòü â ” êîìáèí¡àòîðíóþ áèáëèîòåêó“ Íå ñîéòè ñ óìà îò ñëîæíîñòè
  • 94. Àñèíõðîííîå ïðîãðàììèðîâàíèå Êàê æå áûòü? Âñïîìèíàåì óðîêè ôóíêöèîíàëüíîãî ïðîãðàììèðîâàíèÿ. Èçáàâèòüñÿ îò ñèíòàêñè÷åñêîãî ìóñîðà Ðåàëèçîâàòü ñòðóêòóðû óïðàâëåíèÿ Íå ñîéòè ñ óìà îò ñëîæíîñòè Öåëûé êëàññ ïðîáëåìD ñïåöèôè÷íûõ äëÿ ýòîãî ïîäõîäà Áîëüøèíñòâî ñâÿçàíî ñ mut—˜le st—te Íåèññëåäîâàííàÿ îáëàñòüc
  • 95. Àñèíõðîííîå ïðîãðàììèðîâàíèå Once again: interface AsyncT { void run(CallbackT onOk, CallbackThrowable onError); } Ýòè îáúåêòû êîìáèíèðóåìû.
  • 96. Àñèíõðîííîå ïðîãðàììèðîâàíèå Ó÷èìñÿ ó .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
  • 97. Àñèíõðîííîå ïðîãðàììèðîâàíèå class AsyncPrimitives { AsyncT succeed(T value) {...} AsyncT failwith(Throwable error) {...} AsyncU bind(AsyncT at, FuncT,AsyncU fau) {...} } Ýòîãî äîñòàòî÷íî äëÿ áîëüøèíñòâà ñòðóêòóð óïðàâëåíèÿ 1. Ýòî íàçûâàåòñÿ ” ìîíàäà“. 1 Ïðè ïîääåðæêå îïòèìèçàöèè õâîñòîâûõ âûçîâîâ
  • 98. Àñèíõðîííîå ïðîãðàììèðîâàíèå Ìîíàäû ïðîíèêëè â ìåéíñòðèì: ó 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
  • 99. Àñèíõðîííîå ïðîãðàììèðîâàíèå Ìîíàäû ïðîíèêëè â ìåéíñòðèì: ó 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
  • 100. Àñèíõðîííîå ïðîãðàììèðîâàíèå 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
  • 101. Further reading Ðàçíûå ïàòòåðíû ìíîãîïîòî÷íîãî è ðàñïðåäåëåííîãî ïðîãðàììèðîâàíèÿ. Î÷åíü ìíîãî è èíòåðåñíî. http://www.cs.wustl.edu/~schmidt/patterns-ace.html http: //parlab.eecs.berkeley.edu/wiki/patterns/patterns åùå êðó÷å
  • 102. Ñîäåðæàíèå Êîððåêòíîñòü Ïðè÷èíû áàãîâ Äîêàçàòåëüñòâî êîððåêòíîñòè Óëó÷øåíèå êîððåêòíîñòè Ïàòòåðíû è ïîäõîäû Ïàðàëëåëèçì Concurrency Cutting edge Haskell Erlang .NET Clojure Çàêëþ÷åíèå
  • 103. Cutting edge ×òî óìååò Haskell: Âñå ïîáî÷íûå ýôôåêòû êîíòðîëèðóþòñÿ Íåò íåêîíòðîëèðóåìûõ ïðîáëåì èç-çà èõ íàëè÷èÿ Ïîçâîëÿåò íåìûñëèìûå â äðóãèõ ÿçûêàõ âåùè
  • 104. Cutting edge ×òî óìååò Haskell: Ñàìûå áûñòðûå â ìèðå ëåãêîâåñíûå íèòè è ïðèìèòèâû ñèíõðîíèçàöèè I ìåñòî íà v—ngu—ge ƒhootoutD THx áûñòðåå íàòèâíûõ …˜untuD Sõ áûñòðåå irl—ng3 Ïàðàëëåëüíûå ñòðàòåãèè Ïðîñòûå ïàðàëëåëüíûå âû÷èñëåíèÿX íåò àíàëîãîâ â äðóãèõ ÿçûêàõ Data Parallel Haskell Àâòîìàòè÷åñêè ðàñïàðàëëåëèâàåìûå âåêòîðíûå âû÷èñëåíèÿ Òðàíçàêöèîííàÿ ïàìÿòü Ðàáîòà â íàïðàâëåíèè GPU Ìîùíûå áèáëèîòåêè
  • 105. Ëåãêîâåñíûå íèòè Nothing special, ïðîñòî î÷åíü áûñòðûå è ïî÷òè 0 ñèíòàêñè÷åñêîãî îâåðõåäà. C++0x futures/promises and more â 60 ñòðîê.
  • 106. Ïàðàëëåëüíûå ñòðàòåãèè Ëåíèâîñòü ïîçâîëÿåò îòäåëèòü àëãîðèòì è ñïîñîá ðàñïàðàëëåëèâàíèÿ. Ðåçóëüòàò àëãîðèòìà ñòðóêòóðà, ïîëíàÿ ” îáåùàíèé“. Îáåùàíèÿ ” èñïîëíÿþòñÿ“ (ôîðñèðóþòñÿ) ñ ïîìîùüþ ñòðàòåãèè. Ñòðàòåãèÿ ýòî îáûêíîâåííàÿ, ïðîñòàÿ ôóíêöèÿ. Èäåÿ ÿäåðíàÿ. Ýòî ìîæíî ðåàëèçîâàòü è íà Java, åñëè
  • 107. Ïàðàëëåëüíûå ñòðàòåãèè Íàïðèìåð, ñòðàòåãèÿ ” ïàðàëëåëüíî ôîðñèðîâàòü âñå ýëåìåíòû ñïèñêà“: parList :: Strategy a - Strategy [a] parList strat [] = () parList strat (x:xs) = strat x `par` (parList strat xs)
  • 108. 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 ñëàéäû
  • 109. 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:] :] Âåêòîðèçóåòñÿ è ïàðàëëåëèçóåòñÿ.
  • 110. 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
  • 111. Òðàíçàêöèîííàÿ ïàìÿòü transfer :: Account - Account - Int - IO () transfer from to amount = atomically do deposit to amount withdraw from amount
  • 112. Òðàíçàêöèîííàÿ ïàìÿòü 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 (íàîáîðîò íåëüçÿ)
  • 113. Erlang Ñâÿçü ïðîöåññîâ òîëüêî ÷åðåç îáìåí ñîîáùåíèÿìè. Selective receive (èçáèðàòåëüíàÿ âûáîðêà èç mailbox). Ìîùíàÿ ôè÷àF Ïðîçðà÷íàÿ ðàñïðåäåëåííîñòü. Î÷åíü ýôôåêòèâíàÿ ðåàëèçàöèÿ íèòåé è message passing. Î÷åíü êðóòàÿ è ïðîäóìàííàÿ èíôðàñòðóêòóðà. Î÷åíü ïðîñòîé ÿçûê. Àêòèâíî ïðèìåíÿåòñÿ â èíäóñòðèè (â ò.÷. Amazon, Facebook, Yahoo, . . . ). http://spbhug.folding-maps.org/wiki/Erlang ñàìîïèàð YA
  • 114. F# Asynchronous workows: óæå ðàññìîòðåëè.
  • 115. C# Asynchronous LINQ (ìîæíî ñäåëàòü ñàìîìó: LINQ = ìîíàäû) Óæå ðàññìîòðåëè Parallel LINQ
  • 116. Parallel LINQ (PLINQ) IEnumerableT, IParallelEnumerableT AsParallel http://msdn.microsoft.com/en-us/magazine/cc163329.aspx
  • 117. 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} è ò.ï.
  • 118. 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);
  • 119. 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
  • 120. Atoms Áîëåå èëè ìåíåå îáû÷íûå atomic ïåðåìåííûå. (swap! atom f) ” Àòîìàðíî çàìåíèòü x íà f (x), âåðíóòü ñòàðûé x (compare-and-exchange)“ f îáÿçàíà áûòü ÷èñòîé: åå ìîãóò âûçâàòü íåñêîëüêî ðàç http://clojure.org/atoms
  • 121. 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
  • 122. 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
  • 123. Refs Òðàíçàêöèîííàÿ ïàìÿòü (STM). Äîâîëüíî îáû÷íàÿ Òðàíçàêöèè äîëæíû áûòü áåç ïîáî÷íûõ ýôôåêòîâ Ëþáîïûòíî: (commute x f): çàìåíèòü x íà f (x), ïðåäïîëàãàÿ ÷òî f êîììóòèðóåò ñ îñòàëüíûìè. ÍàïðèìåðD (commute counter inc) ïîäîéäåò Ðàáîòàåò ñëåãêà áûñòðååD ÷åì äðóãèå ôóíêöèèEìóòàòîðû http://clojure.org/refs
  • 124. Ñîäåðæàíèå Êîððåêòíîñòü Ïðè÷èíû áàãîâ Äîêàçàòåëüñòâî êîððåêòíîñòè Óëó÷øåíèå êîððåêòíîñòè Ïàòòåðíû è ïîäõîäû Ïàðàëëåëèçì Concurrency Cutting edge Haskell Erlang .NET Clojure Çàêëþ÷åíèå
  • 125. ×òî áûëî Êëàññèôèêàöèÿ ìíîãîïîòî÷íûõ ïðîãðàìì Ôîðìàëüíûå ìåòîäû (LTL) è òóëû (SPIN,JPF,CheckThread) Êîððåêòíîñòü: èíêàïñóëÿöèÿ, âûñîêîóðîâíåâûå îïåðàöèè, ôàêòîðèçàöèÿ, äåäëîêè, àòîìàðíûå è èäåìïîòåíòíûå îïåðàöèè, îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü Ìåòîäèêè: fork/join, âåêòîðíûå àëãîðèòìû, message-passing, event-driven, STM, àñèíõðîííîå ïðîãðàììèðîâàíèå Haskell: ëåãêèå íèòè, ïàðàëëåëüíûå ñòðàòåãèè, âåêòîðèçàöèÿ, STM Erlang: ìîùíàÿ èíôðàñòðóêòóðà Clojure: Atoms, Vars, Agents, Refs C#: PLINQ
  • 126. ×åãî íå áûëî Ðàñïðåäåëåíùèíà gonsensusD P€gD ve—der ele™tionF F F hr„ et™F wess—ging p—tterns Íåáëîêèðóþùèå àëãîðèòìû „here9s more to itF