Používám MATLAB více než 25 let. (A předtím jsem dokonce používal MATRIXx, pozdní, neúspěšný pokus o spin-off, nebo možná rip-off). Není to první jazyk, ve kterém jsem se naučil programovat, ale je to jazyk, se kterým jsem matematicky dospěl. Znalost MATLABu byla pro mou kariéru velmi přínosná.
Není však možné ignorovat vzestup Pythonu ve vědeckých výpočtech. Společnost MathWorks to musí cítit stejně: nejenže přidala možnost volat Python přímo z MATLABu, ale převzala některé vlastnosti jeho jazyka, například agresivnější vysílání operandů binárních operátorů.
Dospělo to do bodu, kdy jsem zpochybňoval své další používání MATLABu ve výzkumu i výuce. Přesto mi v něm mnohé přijde tak snadné a do materiálů k němu jsem tolik investoval, že bylo těžké shromáždit motivaci k tomu, abych se opravdu naučil něco nového.
Vstupte do učebnice založené na MATLABu, kterou jsem spoluvytvořil pro úvodní kurz výpočetní matematiky. Kniha obsahuje přes 40 funkcí a 160 výpočetních příkladů a pokrývá to, co považuji za důkladný základ v používání MATLABu pro numerické vědecké výpočty. Částečně v rámci sebezdokonalování a částečně proto, abych zvýšil užitečnost knihy, jsem se letos rozhodl přeložit kódy do jazyků Julia a Python. Tato zkušenost mě přivedla ke zvláštnímu pohledu na tyto tři jazyky ve vztahu k vědeckým výpočtům, který se pokusím zachytit níže.
Otázky nákladů a otevřenosti nechám většinou stranou. MATLAB, na rozdíl od Pythonu a Julie, není ani bez piva, ani bez řečí. To je vskutku velký rozdíl – pro někoho dispozitivní – ale chci se zabývat technickými přednostmi. Po mnoho let byl MATLAB v řadě vysoce užitečných ohledů daleko za jakýmkoli bezplatným produktem, a pokud jste chtěli být produktivní, pak náklady vem čert. Je to oddělená úvaha od platonické přitažlivosti jazyka a ekosystému.
Když necháte náklady stranou, užitečný rámec pro mnoho rozdílů mezi těmito jazyky spočívá v jejich původu. MATLAB, nejstarší z těchto snah, upřednostňoval matematiku, zejména numericky orientovanou matematiku. Python, který začal vážně vznikat koncem 80. let, se zaměřil především na informatiku. Julia, která začala vznikat v roce 2009, si dala za cíl najít mezi těmito stranami větší rovnováhu.
MATLAB
Původně byla každá hodnota v MATLABu polem čísel s plovoucí desetinnou čárkou s dvojitou přesností. Oba aspekty této volby, pole i plovoucí desetinná čárka, byly inspirovanými návrhovými rozhodnutími.
Standard IEEE 754 pro plovoucí desetinnou čárku byl dokonce přijat až v roce 1985 a paměť se měřila v K, nikoli v G. Dvojciferná čísla s plovoucí desetinnou čárkou nebyla nejefektivnějším způsobem reprezentace znaků nebo celých čísel, ale vědci, inženýři a stále častěji i matematici je chtěli používat po většinu času. Navíc se proměnné nemusely deklarovat a paměť se nemusela explicitně alokovat. Přenechání těchto úkolů počítači a odstranění datových typů z cesty uvolnilo mozek k přemýšlení o algoritmech, které budou s daty pracovat.
Mřížky byly důležité, protože se začaly používat numerické algoritmy v lineární algebře v podobě LINPACK a EISPACK. Ale přístup k nim pomocí standardního nosiče vědeckých výpočtů, jazyka FORTRAN 77, byl několikastupňový proces, který zahrnoval deklarování proměnných, volání krypticky pojmenovaných rutin, kompilaci kódu a následné zkoumání dat a výstupních souborů. Napsat násobení matice jako A*B
a hned dostat vytištěnou odpověď bylo převratné.
MATLAB také usnadnil a daleko více zpřístupnil grafiku. Žádné složité strojově specifické knihovny s nízkoúrovňovými voláními, prostě plot(x,y)
a viděli jste v podstatě to, co by viděl kdokoli jiný s MATLABem. Byly tu další inovace, jako například zapracovaná komplexní čísla, řídké matice, nástroje pro vytváření grafických uživatelských rozhraní napříč platformami a špičková sada řešičů ODE, které z MATLABu udělaly místo pro vědecké výpočty rychlostí myšlenky.
Naproti tomu návrh, který byl ideální pro interaktivní výpočty, dokonce i pro ty dlouhé, ne vždy přispíval k psaní dobrého a výkonného softwaru. Přesouvání dat mezi mnoha funkcemi vyžadovalo žonglování se spoustou proměnných a časté nahlížení do dokumentace o vstupních a výstupních argumentech. Jedna funkce na jeden diskový soubor v plochém jmenném prostoru byla osvěžujícím způsobem jednoduchá pro malý projekt, ale pro velký projekt představovala bolest hlavy. Pokud jste se chtěli vyhnout úzkým místům v rychlosti, bylo nutné použít určité programovací vzory (vektorizace, předalokování paměti). Vědecké výpočty se nyní používaly v mnohem více oblastech s obrovským množstvím různých nativních typů dat. Atd.
MathWorks na to reagoval pokračujícími inovacemi v rámci MATLABu: inline funkce, vnořené funkce, uzávěry proměnných, četné datové typy, objektově orientované funkce, rámce pro unit testing a tak dále a tak dále. Každá inovace byla pravděpodobně řešením důležitého problému. Kumulace 40 let těchto změn však měla vedlejší efekt v podobě narušení jednoduchosti a jednotnosti koncepce. V roce 2009 jsem napsal knihu, která na necelých 100 stranách docela dobře pokrývala to, co jsem považoval za základní prvky MATLABu. Pokud vím, všechny tyto věci jsou stále k dispozici. Ale abyste se mohli nazývat zběhlými, musíte toho dnes umět mnohem víc.
Python
V jistém smyslu se zdá, že historie Pythonu je téměř zrcadlovým obrazem historie MATLABu. Oba se vyznačovaly interaktivním příkazovým řádkem (dnes se všeobecně nazývá REPL, zkratka pro „read-eval-print loop“) a svobodou od deklarací proměnných a kompilace. MATLAB však vznikl jako hřiště pro numerické analytiky, zatímco Python byl vytvořen s ohledem na hackery. Každý z nich pak prostřednictvím revizí a rozšíření rostl směrem k druhému publiku.
Podle mého názoru Python stále postrádá matematickou přitažlivost. Máte tu ošklivost a drobné nepříjemnosti jako **
místo ^
, @
pro násobení matic (nedávná novinka!), shape
místo velikosti matice, řádkově orientované ukládání atd. Pokud se domníváte, že V.conj().T@D**3@V
je elegantní způsob zápisu $V^*D^3V$, pak možná budete muset navštívit lékaře. A ještě je tu nulové indexování (na rozdíl od indexů, které začínají na 1). Přečetl jsem si argumenty a nepovažuji je za rozhodující. Je to zjevně otázka preferencí – náplň internetových svatých válek – protože pro obě konvence můžete uvádět neobratné příklady. Co považuji za rozhodující, je to, že máme desítky let matematické praxe indexování vektorů a matic od jedničky a většina pseudokódu to předpokládá.
Kromě drobných nepříjemností považuji ekosystém Python+NumPy+SciPy za nepřehledný a nekonzistentní. Důkazem A je fakt, že přestože se jazyk věnuje spíše objektové orientaci, existuje třída matrix, a přesto se její používání nedoporučuje a bude deprecated. Možná mě MATLAB prostě zkazil, ale matice považuji za dostatečně důležitý typ objektu, který je třeba udržovat a podporovat. Není hlavní výhodou OOP to, že můžete mít *
pro pole a matice různé věci? V tomto ohledu existuje mnoho dalších nedokonalostí. (Proč potřebuji příkaz s názvem spsolve? Nemůžu prostě zavolat solve
na řídkou matici? A tak dále a tak dále.“)
Jsou také místa, kde mi číselný ekosystém připadá poněkud řídký. Například kvadraturní a ODE solvery vypadají v roce 2019 jako minimální sada. AFAICT neexistují žádné metody pro DAE, DDE, symplektické solvery ani implicitní solvery, které by umožňovaly vnitřní Krylovovy iterace. Podívejte se na odkazy na tyto funkce; jsou většinou 30 a více let staré – stále dobré, ale velmi vzdálené od úplnosti. Balík Matplotlib je úžasný kus práce a nějakou dobu vypadal lépe než MATLAB, ale v 3D mi stále dost chybí.
Někteří odborníci tvrdí, že existují hluboké důvody, proč kód Pythonu těžko drží krok v rychlosti provádění s kompilovanými jazyky. Pobavily mě výsledky vyhledávání „python je příliš pomalý“. Obhájci Pythonu uvádějí spoustu stejných argumentů/omluv, jaké svého času uváděli lidé pro MATLAB. To neznamená, že se mýlí, ale je v tom víc než jen problém s vnímáním.
Myslím, že chápu, proč byl Python pro mnoho lidí ve vědeckých výpočtech tak vzrušující. Má určitou syntaxi a výkon podobný MATLABu, dostupný z REPL. Má kolem sebe skvělé nástroje a dobře si pohrává s jinými jazyky a oblastmi výpočetní techniky. Nabídl to bez nákladů a s mnohem lepší dlouhodobou reprodukovatelností. Je zřejmé, že funguje dobře pro spoustu lidí, kteří pravděpodobně nevidí důvod ke změně.
Ale pro věci, které umím dělat ve vědeckých výpočtech, mi Python připadá mnohem náročnější na učení a používání, než jsem zvyklý. Ještě nějakou dobu nebudeme vědět, jestli bude komunitou dál procházet, nebo se už přiblížil svému vrcholu. Nemám žádné zvláštní předpovědní schopnosti, ale jsem medvěd.“
Julia
Julia má výhody i nevýhody toho, že je opožděná. Chválím tvůrce Julie za to, že si myslí, že by to mohli udělat lépe:
Chceme jazyk s otevřeným zdrojovým kódem a liberální licencí. Chceme rychlost jazyka C s dynamikou jazyka Ruby. Chceme jazyk, který je homoikonický, s opravdovými makry jako Lisp, ale se zřejmou, známou matematickou notací jako Matlab. Chceme něco stejně použitelného pro obecné programování jako Python, stejně snadného pro statistiku jako R, stejně přirozeného pro zpracování řetězců jako Perl, stejně výkonného pro lineární algebru jako Matlab, stejně dobrého pro slepování programů jako shell. Něco, co se dá jednoduše naučit, a přitom s tím budou spokojeni i ti největší hackeři. Chceme to interaktivní a chceme to zkompilované.
Myslím, že se jim to do značné míry podařilo. Později na cestě k verzi 1.0 se zdálo, že REPL trochu bagatelizují, a došlo k několika téměř bezdůvodným odklonům od MATLABu. (V čem přesně je LinRange
lepší než linspace
?) To jsou ale hádky.
Je to první jazyk, který používám a který přesahuje ASCII. Stále mám nepřiměřené uspokojení z používání proměnných jako ϕ
a operátorů jako ≈
. Je to víc než kosmetické; možnost vypadat více jako matematické výrazy, které píšeme, je skutečné plus, i když to trochu komplikuje výuku a dokumentaci.
Práce v Julii mi odhalila, že některé programovací návyky jsem si osvojil díky volbám MATLABu, nikoliv díky jeho vrozené nadřazenosti. Vektorizace není pro mnoho věcí přirozená. V Julii mi otevřelo oči zjištění, že jakoukoli funkci můžete vektorizovat pouhým přidáním tečky k jejímu názvu. Při konstrukci matice pomocí porozumění vypadají vnořené smyčky (nebo triky meshgrid
) ve srovnání s tím jako bič na chyby a úplné vyhnutí se matici pomocí generátoru pro jednoduchý součet působí jako získání něčeho za nic. (Jsem si vědom, že Python má podobné vlastnosti jazyka.)
Velká vlastnost vícenásobného odesílání dělá některé věci mnohem jednodušší a přehlednější než objektová orientace. Předpokládejme například, že v tradičním objektově orientovaném jazyce máte třídy Wall a Ball. Která třída má detekovat kolizi koule se zdí? Nebo potřebujete třídu Room, která bude hrát rozhodčího? Otázky tohoto typu mě dokážou vyvést z míry. Při vícenásobném odesílání jsou data zabalena do objektových typů, ale metody, které s daty pracují, nejsou vázány na třídu. Takže
function detect_collision(B::Ball,W::Wall)
ví o typech, ale je definována nezávisle na nich. Trvalo mi poměrně dlouho, než jsem při programování docenil, jak zajímavý a potenciálně důležitý je pojem vícenásobné depeše pro rozšíření jazyka.
Číslicový ekosystém se rychle vyvíjí. Mým příkladem číslo jedna je DifferentialEquations.jl, který napsal úžasný Chris Rackauckas. Pokud tento software brzy nezíská Wilkinsonovu cenu, je systém rozbitý. Stačí jít na stránky a připravit se na konverzi.
Ještě jsem neviděl velký nárůst rychlosti oproti MATLABu, který slibuje Julia. Částečně je to mou relativní nezkušeností a druhem úloh, které dělám, ale částečně také tím, že MathWorks odvedl neuvěřitelnou práci při automatické optimalizaci kódu. Stejně to není aspekt kódování, na který bych se většinu času soustředil.
Programování v Julii mi chvíli trvalo, než jsem se cítil pohodlně (možná jen stárnu a krystalizuji). Nutí mě to přemýšlet o datových typech víc, než bych chtěl, a vždycky se mi vkrádá podezření, že jsem přehlédl Správný způsob, jak něco udělat. Ale pro každodenní použití se teď asi stejně často obrátím na Julii jako na MATLAB.
Pointa
MATLAB je firemní řešení, zejména pro inženýrství. Pro základní numerické úlohy je pravděpodobně stále nejjednodušší se ho naučit. Pečlivá dokumentace a desítky let přispívané nástroje pro učení mají rozhodně význam.
MATLAB je sedan BMW ve světě vědeckých výpočtů. Je drahý, a to ještě předtím, než začnete mluvit o příslušenství (toolboxech). Platíte za solidní, bezproblémový výkon a servis. Přitahuje také neúměrné množství nenávisti.
Python je pickup od Fordu. Je všudypřítomný a mnohými (v USA) oblíbený. Umí všechno, co si přejete, a je konstruován tak, aby zvládl některé věci, které jiná vozidla nezvládnou. Je pravděpodobné, že si ho budete chtít čas od času půjčit. Ale nenabízí skvělý čistý zážitek z jízdy.
Julia je Tesla. Je postavena s odvážným cílem změnit budoucnost, a to by mohla. Může se také stát pouhou poznámkou pod čarou. Ale mezitím se dostanete tam, kam máte namířeno, stylově a s výkonem na rozdávání.