Rozhodování v distribuovaných systémech

Už několik let pracuji na tradingu ČEZ, kde jsme na zelené louce postavili platformu pro algoritmický trading na energetických burzách a ještě jsem tu nepublikoval žádný článek přímo z toho oboru, tak to dnes napravím. Možná se to podle nadpisu nezdá, ale burzy a obchodníci na nich působící jsou naprosto archetypálním příkladem distribuovaného systému se všemi těžkostmi, které to s sebou může nést. Provádět na burzách jakákoli automatizovaná rozhodnutí znamená nutnost si je uvědomovat a vypořádat se s nimi.

Prokletí distribuovaných systémů však je, že jejich těžkosti se na první pohled zdají tak malicherně titěrné, že je bez mnoha vlastních bolestivých zkušeností obtížné uvěřit, že se nedají vyřešit nějakou drobnou inženýrskou zkratkou. U počítačů k tomu dojmu obzvlášť přispívají mikroskopické časové jednotky, ve kterých se rozhodování odehrává, vždyť jaký problém může být jestli nějaké rozhodnutí uděláme třeba teď nebo až za 1 milisekundu?

Právě na burzách a v algoritmickém obchodování zvlášť však platí, že rozhodnutí správné právě teď může být zcela vadné za 1 milisekundu úplně stejně jako až za 1 rok. Co je rozhodující není ani v nejmenším fyzický čas, ale distribuce informací v systému. Díky tomu můžu tyto těžkosti v dalším textu představit na příkladech v lidských rozměrech, kterým by mohlo být trochu jednodušší uvěřit. Nenechte se zmást jejich banalitou, staly se nám ve finanční podobě prakticky všechny a zahučely na nich nepředstavitelné peníze.

Už jste někdy v práci pochcali šéfovi nohy?

Sedíme si takhle ve své kanceláři v prvním patře naší firmy a začne se nám chtít čůrat. Dejme tomu, že záchody v prvním a druhém patře jsou kvůli nějaké havárii uzavřeny a nejbližší toalety jsou tak až ve třetím patře a proto je potřeba si připravit celý řetězec kroků, kterým dosáhneme cíle “vyčůrat se”, který jsme si právě vytyčili. Postup bude vypadat nějak takhle banálně:

  • Dojít k výtahu
  • Nastoupit a zmáčknout tlačítko 3
  • Vystoupit a dojít ke dveřím na konci chodby
  • Vejít do dveří a začít čůrat

Výsledek akce v reálném světě nemusí odpovídat očekáváním…

…a vůbec to nemusí být chyba, takže nás na ni neupozorní žádné houkající sirény ani červené majáčky. Třeba moderní výtahy mají svojí hlavu a jezdí a zastavují podle vlastní logiky. To, že jsme zmáčkli tlačítko 3 neznamená, že s námi výtah dojede hned do 3. patra. Z různých důvodů může náš výtah zastavit nejdřív ve 2. patře, kde na konci chodby není WC, ale kancelář našeho šéfa a pokud bychom bezhlavě následovali vytyčený postup (tak jak to dělají všechny stroje), nebudeme močit do pisoáru, ale na šéfovy nohy.

Rozhodování výhradně podle aktuálního stavu

Nejjednodušší taktika, jak těmto neblahým faux pas v distribuovaných systémech zamezit, je formulovat svá rozhodnutní nikoli jako dopředný řetězec kroků, které chceme udělat, ale jako jednotlivé reakce na nějaké dosažené stavy. Přitom doufáme, že dosažený stav ve většině případů reflektuje rozhodnutí učiněné ve stavu předchozím a ten zase v tom před ním a tak dál až na samý začátek našeho snažení.

Ne vždy to jde, ale dejme tomu, že v našem případě do 2. patra jezdíme výhradně odevzdávat reporty šéfovi a do 3. patra jezdíme výhradně na záchod a proto se můžeme pokusit definovat naše rozhodování (pokud už se ocitneme ve výtahu) na tom, ve kterém patře se nám otevřou dveře:

  • Chce se nám čůrat: dojít do výtahu a zmáčknout 3
  • Šéf si zavolá o reporty: dojít do výtahu a zmáčknout 2
  • Dveře výtahu se otevřely v 1. patře: vrátit se ke svému stolu
  • Dveře výtahu se otevřely ve 2. patře: dojít na konec chodby, vejít a odevzdat reporty
  • Dveře výtahu se otevřely ve 3. patře: dojít na konec chodby, vejít a čůrat

Tohle zajišťuje, že se v žádném případě nevyčůráme svému šéfovi na nohy, ale moc funkční to taky není. Svůj cíl jít na záchod sice iniciujeme v prvním kroku zmáčknutím tlačítka 3 ve výtahu, ale při stejném překvapivém zastavení ve 2. patře jako v předchozí kapitole dojdeme podle svých pravidel k šéfovi a ukážeme mu prázdné ruce, protože svůj stůl jsme opustili se záměrem jít čůrat, ne odevzdat reporty.

Původní cíl je důležitý

Zakládat rozhodnutí pouze na aktuálním stavu tedy taky není všespásné a je potřeba si původní záměr pamatovat. Pravidla pohybu po budově v závislosti na záměru a aktuálním stavu proto upravíme následovně:

  • 2. patro, záměr jít čůrat: zůstat ve výtahu
  • 3. patro, záměr odevzdat reporty: zůstat ve výtahu
  • 2. patro, záměr odevzdat reporty: dojít ke dveřím na konci chodby
  • 3. patro, záměr jít čůrat: dojít ke dveřím na konci chodby
  • dveře na konci chodby, záměr odevzdat reporty: vejít a odevzdat reporty
  • dveře na konci chodby, záměr jít čůrat: vejít a čůrat

Okolnosti mění i naše cíle

Tohle začíná vypadat slibně, ale pamatovat si záměr není jen tak. Pokud si ho budeme pamatovat vždy, když nás k němu nasměrují okolnosti, překvapí nás tento scénář:

  • Šéf zavolá, že mu máme přinést reporty - zapamatujeme si záměr odevzdat reporty
  • Výtah zastaví správně ve druhém patře, proto vystoupíme a dojdeme na konec chodby
  • Během chůze se nám začne chtít čůrat - zapamatujeme si záměr jít čůrat
  • U dveří na konci chodby se podle posledního pravidla z předchozího seznamu rozhodneme vejít a počůrat šéfovi nohy

Reálný svět není zákeřný jen proto, že mění výsledky akcí, které jsme započali. Ještě horší je, že na základně okolností reálného světa měníme i my cíle, kterých chceme dosáhnout.

Ti pozornější by měli namítnout, že trochu podvádím a v posledních dvou nových pravidlech jsem ve skutečnosti vynechal jednu z podmínek aktuálního stavu (dveře na konci chodby ve kterém patře?), což je právě to, co umožnilo toto selhání a co bylo řešeno už v předchozích kapitolách. To je pravda, ale nechť je to memento toho, že v distribuovaných systémech není v základu atomické vůbec nic a to ani provedení kontroly stavu a následné akce. Vždy se najde nějaký předpoklad, který jsme nevědomky udělali, jehož neplatnost dovolí paralelní události se vměstnat na nějaké neočekávané místo v našem plánu.

Realita na nikoho nečeká

Z předchozího je jasné, že nemůžeme měnit aktuální cíl pokaždé, když nás to napadne. Můžeme si třeba své cíle pamatovat v pořadí jak nás napadnou a vyřizovat je jeden po druhém až do konce. I když se nám tedy jako v předchozím případě začne chtít čůrat cestou k šéfovi, cíl “vyčůrat se” jen postavíme do hypotetické fronty a budeme pokračovat v plnění cíle “odevzdat reporty šéfovi”.

Vstoupíme tedy do jeho kanceláře … a pochčijem mu nohy, protože se nám chce fakt strašně moc a už to nejde vydržet. Někdy se sice realita nechá usměrnit podle našeho plánu, ale někdy taky ne a když se pak naopak nepřizpůsobí plán, špatně to dopadne.

Obecná abstrakce reality neexistuje

Špatně to může dopadnout s jakýmikoli naivně obecnými pravidly rozhodování. I kdybychom třeba v předchozím příkladu naopak všechny nové cíle začali řešit prioritně, byl by to problém v nějaké jiné situaci (stačí si představit, jak by to probíhalo u starších pánů se špatnou prostatou).

Laická reakce na tyto zjištění je většinou bohužel vykopat ten hrob ještě hlubší. Začít si třeba u všeho zapisovat časové značky a dál se rozhodovat podle jejich porovnávání a nebo velikostí jejich rozdílů. Nebo začít stanovovat nějaké třídy priorit a předpokládat, že když bude taková abstrakce dostatečně složitá, podaří se pak do ní nějak namapovat jakoukoli realitu.

Zkušenost z oboru, kterou jsem už zmínil, je, že realita je plná situací, které jsme jako okrajové ignorovali a které jsou proto skrze naše abstraktní atributy nerozpoznatelné. Skutečně správné rozhodnutí může vyžadovat znalost nejen jakéhokoli detailu aktuálního stavu, ale i veškeré historie rozhodnutí, provedených akcí a jejich výsledků, které k němu vedly.

Limity automatizace

V tuto chvíli je potřeba si připomenout, co je vlastně podstatou automatizace. Její smysl spočívá v případech, kdy je potřeba stejným postupem odbavit velké množství v principu stejných situací. Udělat něco pomocí počítače je totiž vždy mnohem složitější, než to udělat ručně a tuto složitost musíme amortizovat přes velké množství takových situací vyřešených stejným postupem automaticky.

Tohle je bohužel tak nějak v přímém rozporu s konstatováním z předchozí kapitoly, které naznačuje, že množství situací, které je potřeba řešit zvlášť, je exponenciální vzhledem k množství akcí a mezistavů, které mohou nastat. Otázka, zda vůbec má smysl to automatizovat, je pak zcela relevantní.

Prvotní chybu, ze které se snažíme celou dobu vyhrabat, jsme totiž udělali hned v úvodu. Ten banální postup, jak si dojít na záchod, to je algoritmus, který má jen jednoho aktéra - nás. Pokud se chceme vyhnout výše popsané exponenciální složitosti, pak se ale na automatizaci v distribuovaných systémech musí podílet všichni aktéři, ať už přímo nebo v zastoupení, podle společných pravidel. Algoritmy, ve kterých vystupuje více aktérů se nazývají “protokoly”, ale to už je téma na další článek.