Paralelní svět
June 30th, 2008 V poslední době se hodně mluví o Erlangu. No a protože jsem slaměný vdovec a u žehlení se nudím, pustil jsem si přednášku od otce Erlangu Joe Armstronga. V tomto zápisku se chci o své dojmy z této přednášky podělit s vámi, mými oddanými fanoušky. Chci předem upozornit, že to jsou jen dojmy, pořádně ještě nemám na věc ujasněný názor.
Začátek přednášky je relativně zajímavý. Už jsem nejméně stokrát slyšel, že se programátoři musí začít chovat jinak, protože se objevily vícejádrové procesory. Ale vždy jsem si říkal, že tu máme přeci víceprocesorové stroje už hodně dlouho, tak jakápak změna. Až díky této přednášce jsem mi došlo, že změna není v tom, že máme více jader. Změna je v tom, že se sekvenční zpracování procesorů nezrychluje tak, jak jsme byli zvyklí. Od jisté doby roste rychlost hlavně díky paralelizaci. Všimněte si, že taktovací frekvence procesorů se v poslední době zas tak zásadně nemění. Naopak se objevují X jádrové procesory. Už prý existuje 1000 jádrový procesor, pokud bude růst počet jader exponenciálně, můžeme se v nedaleké budoucnosti dostat na zajímavá čísla. Předpokládejme, že je takový nárůst počtu jader možný. Dosud jsme byly zvyklí, že naše programy automaticky s novým procesorem zrychlí. Od příště už to tak být nemusí. To že klient můj sekvenční program nasadí na procesor s miliónem jader, neznamená, že bude milionkrát rychlejší. Spíš bude pomalejší než na jednojádrovém.
Tak a teď mé dojmy. Jak to ovlivňuje programátory? Protože jsem zvyklý na serverovou Javu, budu psát hlavně o ní. Představme si, že máme 1000 jádrový procesor. Jak budeme muset změnit svůj kód, aby běžel efektivně? Představme si pro začátek, že mám jednoduchou aplikaci založenou na servletech. Přijde dotaz, já ho v jenom vlákně zpracuji a v tom samém vlákně pošlu odpověď. Abych si to zkomplikoval, budu předpokládat, že ne všechna práce je výpočetně náročná, občas budu čekat na disk, databázi na jiném stroji atp. To znamená, že potřebuji mít víc vláken než procesorů (jader), abych byl schopen je vytížit. To znamená, že potřebuji víc než tisíc současných požadavků, aby ta vlákna měla co dělat (tady to trochu moc zjednodušuji, ale snad mi to prominete). Pokud je tento předpoklad splněn, nemusím svoji aplikaci měnit vůbec. Tedy za předpokladu, že JVM zvládne 1000 jádrový procesor.
Pokud mám méně než několik tisíc současných dotazů, procesor plně nevyužiji. Musím práci rozsekat na víc kousků. Jde to v Javě vůbec? Pan Armstrong tvrdí, že ne. Tvrdí, že Java je staromódní jazyk, který se spoléhá na sdílenou paměť, sdílený stav, zámky, transakce a podobná zvěrstva. Naproti tomu je Erlang moderní jazyk, který je navržen s tím, aby skvěle fungoval paralelně, který nemá problém s miliónem běžících pidiprocesů, které žádný stav nesdílejí, jenom si předávají zprávy. Tvrdí navíc, že problém Javy a podobných jazyků je přímo v jejich pojetí. Že jsou to jazyky sekvenční, kdežto Erlang je jazyk paralelní. Tvrdí navíc, že svět jako takový, je paralelní, tudíž je těžké ho popsat sekvenčním jazykem. Abych pravdu řekl, nevím jestli je svět paralelní nebo sekvenční. Na jednu stranu se každý člověk stará sám o sebe a rozhodně nesdílí svůj stav s ostatními. Jenom jim posílá všelijaké zprávy. To by nahrávalo paralelnímu pohledu. Jen ovšem do té doby, než se octnete v dopravní zácpě, která je podle mě silně sekvenční.
A v tom je právě zakopaný pes. Potíž není v jazyku, ale v řešeném problému. V Javě také nemusím sdílet žádný stav. Každé vlákno může mít svoji logicky oddělenou paměť. Když se nad tím zamyslím, tak už se to dávno děje. Proto jsou tak populární řešení založená na JMS. Jednotlivé oddělené procesy si jenom předávají zprávy. To je přesně to, co mi poskytuje Erlang. V Javě to jenom není zakomponováno přímo v jazyku. Je to v ní na logicky vyšší úrovni. A tedy i s mnohem vyšší režií.
Ano je to tak, pokud mám problém, který se dá rozseknout na hodně malých úkolů, je snadné ho paralelizovat. Ale na to není nutné měnit jazyk. Mohu použít JMS, JINI nebo jiné jednodušší mechanizmy. Stále tu ale ještě máme spoustu aplikací, které prostě vyžadují sdílený stav, jejichž doména je sekvenční, které se paralelizovat nedají. Jsem rád, že mohu používat jazyk, který mi to umožňuje.
Bylo by samozřejmě pěkné, kdyby Java umožňovala snazší spouštění paralelních úloh. Na druhou stranu k tomu už spěje. V Javě 5 byly zavedeny executory (spouštěče?), Futures a datové struktury, které nevyžadují synchronizaci. Možná není paralelní programování v Javě tak přímočaré jako v Erlangu, ale relativně jednoduché je. Takže můj závěr je následující – pokud máte problém, který je principiálně podobný telefonní ústředně, zkuste Erlang. Pokud píšete obecnou aplikaci, zůstaňte u Javy.