Евгений Кирпичёв Многопоточное программирование2. Öåëü äîêëàäà
Ðàñøèðèòü êðóãîçîð â îáëàñòè ìíîãîïîòî÷íîãî
ïðîãðàììèðîâàíèÿ âîîáùå.
Êîððåêòíîñòü
Êàê ñôîðìóëèðîâàòüD ïîâûñèòüD ãàðàíòèðîâàòü
Èíñòðóìåíòû
Ïàòòåðíû è âåëîñèïåäû
Ïîäõîäû è ôèøêè ðàçíûõ ÿçûêîâ
6. Ïðè÷èíû áàãîâ
Êîðåíü âñåõ çîë èçìåíÿåìîå âî âðåìåíè ñîñòîÿíèå.
N íèòåé, K ñîñòîÿíèé ⇒ O(KN) ïåðåïëåòåíèé
Ïðîìåæóòî÷íûå ñîñòîÿíèÿ âèäèìû
Äàæå âûçîâ ìåòîäà ýòî áîëüøå íå ÷åðíûé ÿùèê
Åãî òåëî áîëüøå íå àòîìàðíî
Êîððåêòíûå ìíîãîïîòî÷íûå ïðîãðàììû íå ìîäóëüíû
ƒequenti—ly ™orre™t + ƒequenti—lly ™orre™t = gon™urrently
™orre™t
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 ÷òî îíè
”
è òàê“ ðàáîòàþò
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
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
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 (áðåä, íî ñóòü
ïðèìåðíî òàêàÿ).
40. Ôàêòîðèçàöèÿ
Ðàçîðâåì ëèøíþþ çàâèñèìîñòü ìåæäó íåçàâèñèìûìè
çàäà÷àìè.
class DataLoader {
PerClientLoader beginLoad(Client client);
}
class PerClientLoader {
void writeData(Data data);
void commit();
void rollback();
}
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
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
Ìîæåò îêàçàòüñÿ, ÷òî òàêàÿ øòóêà óæå åñòü.
51. Àáñòðàãèðîâàíèå: ïðèìåð
Ïðèâÿçêà ê âíåøíåé ñèñòåìå ñêà÷èâàíèÿ óðëîâ.
Çàäàíèÿ ïèøóòñÿ â ôàéëû
Âíåøíÿÿ ñèñòåìà èõ ïîäõâàòûâàåò
Îòâåòû òîæå ïèøóòñÿ â ôàéëû
Íàäî ïðåäîñòàâèòü àñèíõðîííûé API
void loadPage(url, onOk, onError)
53. Àáñòðàãèðîâàíèå: ïðèìåð
Devil in the details:
Íå çàôëóäèòü ñèñòåìó (áëîêèðîâàòüñÿ, åñëè ìíîãî çàäàíèé
”
â ïîëåòå“)
Ñëåäèòü çà òàéìàóòàìè (äîëãî íå îòâå÷àåò → onError)
Íå äîïóñêàòü ãîíîê ìåæäó îòâåòàìè è òàéìàóòàìè
Áåðå÷ü íèòêó ñëåæåíèÿ çà îòâåòàìè (âûçûâàòü
onOk,onError â îòäåëüíûõ íèòÿõ)
Îáðàáàòûâàòü ðåäèðåêòû
56. Àáñòðàãèðîâàíèå: ïðèìåð
Ñòàëî:
Ñåìàôîð äëÿ îãðàíè÷åíèÿ ÷èñëà çàäàíèé
”
â ïîëåòå“
Àáñòðàêòíûé
”
áàò÷åð“
Àáñòðàêòíûé
”
ïîëëåð“
Àáñòðàêòíûé
”
òàéìàóòåð“
Âñ¼ ýëåìåíòàðíî òåñòèðóåòñÿ (íàøëèñü áàãè)
Âñ¼ ïîëåçíî è ïîâòîðíî èñïîëüçóåìî
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
Àñèíõðîííîå ïðîãðàììèðîâàíèå
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]
68. Ïðåôèêñíûå ñóììû
×òî ìîæíî ñäåëàòü ñâåðòêîé/ïðîáåãîì (ò.å. ïàðàëëåëüíî):
sum,min,max,avg,. . .
Radix sort, Quicksort
Ñëîæåíèå äëèííûõ ÷èñåë
Âûïóêëàÿ îáîëî÷êà
Ìíîãèå àëãîðèòìû íà ãðàôàõ
Ìíîãèå ðåêóððåíòíûå ïîñëåäîâàòåëüíîñòè n-ãî ïîðÿäêà
Òðåõäèàãîíàëüíûå ñèñòåìû óðàâíåíèé
. . .
69. Ïðåôèêñíûå ñóììû
Îñîáåííî èíòåðåñíî, êàê ýòî äåëàåòñÿ. Áàçîâûå îïåðàöèè
ïîâåðõ ïðîáåãà:
Ðåêóððåíòíàÿ ïîñëåäîâàòåëüíîñòü 1ãî ïîðÿäêà
Óïàêîâêà ìàññèâà
Ñîðòèðîâêà ìàññèâà ïî 1-áèòíîìó ôëàãó (ðàçáèåíèå)
Ñåãìåíòèðîâàííûé ïðîáåã (ïðîáåã ñî ñáðîñàìè)
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-î÷åðåäü ñîîáùåíèé)
Îòñûëêà ñîîáùåíèé àñèíõðîííàÿ è íåáëîêèðóþùàÿ
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
79. Event loop
Âàðèàöèÿ íà òåìó message passing, íî íå ìíîãî
âçàèìîäåéñòâóþùèõ àêòîðîâ, à îäèí (èëè íåñêîëüêî
îäèíàêîâûõ) æèðíûé è âñåìîãóùèé.
Ñåðâåðû (è accept, è select/poll/... ñþäà îòíîñÿòñÿ)
GUI-ôðåéìâîðêè
Ïðåëåñòè:
Ýòî íå ôðåéìâîðê, íî ïàòòåðí: ëåãêî ðåàëèçîâàòü è
èñïîëüçîâàòü äàæå íà ìèêðîóðîâíå
Ê íåìó ñâîäèòñÿ êó÷à çàäà÷
Î÷åíü ëåãêî ïèøåòñÿ
Áîëüøèíñòâî ìíîãîïîòî÷íûõ ïðîáëåì îòñóòñòâóþò
81. Software Transactional Memory
Òðàíçàêöèè íà óðîâíå ïàìÿòè; àòîìàðíûå êóñêè êîäà.
Ïîëíîöåííûé commit/rollback, ïîëíàÿ àòîìàðíîñòü
Òðàíçàêöèè ïîâòîðÿåìû
retry ïðè êîììèòåD åñëè èçâíå èçìåíåíà ïðî÷òåííàÿ
ïåðåìåííàÿ
Òðàíçàêöèîííûå ïðîãðàììû êîìáèíèðóåìû!
 îòëè÷èå îò sh—red st—te
@ïðàâèëüíîCïðàâèëüíî=ïðàâèëüíîA
Íå äîëæíî áûòü íèêàêèõ ïîáî÷íûõ ýôôåêòîâ, êðîìå
îáðàùåíèé ê òðàíçàêöèîííîé ïàìÿòè
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
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
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
åùå êðó÷å
103. Cutting edge
×òî óìååò Haskell:
Âñå ïîáî÷íûå ýôôåêòû êîíòðîëèðóþòñÿ
Íåò íåêîíòðîëèðóåìûõ ïðîáëåì èç-çà èõ íàëè÷èÿ
Ïîçâîëÿåò íåìûñëèìûå â äðóãèõ ÿçûêàõ âåùè
104. Cutting edge
×òî óìååò Haskell:
Ñàìûå áûñòðûå â ìèðå ëåãêîâåñíûå íèòè è ïðèìèòèâû
ñèíõðîíèçàöèè
I ìåñòî íà v—ngu—ge ƒhootoutD THx áûñòðåå íàòèâíûõ
…˜untuD Sõ áûñòðåå irl—ng3
Ïàðàëëåëüíûå ñòðàòåãèè
Ïðîñòûå ïàðàëëåëüíûå âû÷èñëåíèÿX íåò àíàëîãîâ â äðóãèõ
ÿçûêàõ
Data Parallel Haskell
Àâòîìàòè÷åñêè ðàñïàðàëëåëèâàåìûå âåêòîðíûå
âû÷èñëåíèÿ
Òðàíçàêöèîííàÿ ïàìÿòü
Ðàáîòà â íàïðàâëåíèè GPU
Ìîùíûå áèáëèîòåêè
106. Ïàðàëëåëüíûå ñòðàòåãèè
Ëåíèâîñòü ïîçâîëÿåò îòäåëèòü àëãîðèòì è ñïîñîá
ðàñïàðàëëåëèâàíèÿ.
Ðåçóëüòàò àëãîðèòìà ñòðóêòóðà, ïîëíàÿ
”
îáåùàíèé“.
Îáåùàíèÿ
”
èñïîëíÿþòñÿ“ (ôîðñèðóþòñÿ) ñ ïîìîùüþ
ñòðàòåãèè.
Ñòðàòåãèÿ ýòî îáûêíîâåííàÿ, ïðîñòàÿ ôóíêöèÿ.
Èäåÿ ÿäåðíàÿ. Ýòî ìîæíî ðåàëèçîâàòü è íà Java, åñëè
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
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
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} è ò.ï.
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
125. ×òî áûëî
Êëàññèôèêàöèÿ ìíîãîïîòî÷íûõ ïðîãðàìì
Ôîðìàëüíûå ìåòîäû (LTL) è òóëû (SPIN,JPF,CheckThread)
Êîððåêòíîñòü: èíêàïñóëÿöèÿ, âûñîêîóðîâíåâûå îïåðàöèè,
ôàêòîðèçàöèÿ, äåäëîêè, àòîìàðíûå è èäåìïîòåíòíûå
îïåðàöèè, îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü
Ìåòîäèêè: fork/join, âåêòîðíûå àëãîðèòìû,
message-passing, event-driven, STM, àñèíõðîííîå
ïðîãðàììèðîâàíèå
Haskell: ëåãêèå íèòè, ïàðàëëåëüíûå ñòðàòåãèè,
âåêòîðèçàöèÿ, STM
Erlang: ìîùíàÿ èíôðàñòðóêòóðà
Clojure: Atoms, Vars, Agents, Refs
C#: PLINQ