Search

Jag har använt MATLAB i över 25 år. (Och innan dess använde jag till och med MATRIXx, ett sent och olyckligt försök till en spinoff, eller kanske en ripoff.) Det är inte det första språket jag lärde mig att programmera i, men det är det språk som jag kom upp i åldrarna med på det matematiska området. Att kunna MATLAB har varit mycket bra för min karriär.

Det är dock omöjligt att ignorera Pythons framväxt inom vetenskaplig databehandling. MathWorks måste känna likadant: de har inte bara lagt till möjligheten att anropa Python direkt från MATLAB, utan de har också lånat några av dess språkfunktioner, t.ex. mer aggressiva sändningar för operander i binära operatorer.

Det har nått en punkt där jag har ifrågasatt mitt fortsatta användande av MATLAB i både forskning och undervisning. Men så mycket är lätt för mig där, och jag har investerat så mycket i material för det, att det var svårt att samla motivation för att verkligen lära sig något nytt.

Enter den MATLAB-baserade lärobok som jag har varit med och skrivit för introduktion till beräkningsmatematik. Boken har över 40 funktioner och 160 beräkningsexempel, och den täcker vad jag tycker är en grundlig grund i användningen av MATLAB för numerisk vetenskaplig beräkning. Så dels för att förbättra mig själv, dels för att öka bokens användbarhet, har jag i år börjat översätta koderna till Julia och Python. Denna erfarenhet har lett mig till ett särskilt perspektiv på de tre språken i förhållande till vetenskaplig beräkning, vilket jag försöker fånga in nedan.

Jag kommer i huvudsak att bortse från frågor om kostnad och öppenhet. MATLAB är, till skillnad från Python och Julia, varken ölfritt eller talfritt. Detta är verkligen en stor skillnad – för vissa en avgörande skillnad – men jag vill överväga de tekniska fördelarna. Under många år var MATLAB långt bättre än någon gratisprodukt på ett antal mycket användbara sätt, och om man ville vara produktiv, så var kostnaderna fördömda. Det är ett separat övervägande från den platonska attraktionen av ett språk och ett ekosystem.

När man bortser från kostnaden finns det en användbar ram för många av skillnaderna mellan dessa språk i deras ursprung. MATLAB, som är det äldsta, prioriterade matematik, särskilt numeriskt orienterad matematik. Python, som började på allvar i slutet av 1980-talet, gjorde datavetenskap till sitt centrala fokus. Julia, som inleddes 2009, försökte hitta en bättre balans mellan dessa sidor.

MATLAB

Ursprungligen var varje värde i MATLAB en matris av dubbelprecisionsfrivata tal med flytande punkter. Båda aspekterna av detta val, matriser och flyttal, var inspirerade konstruktionsbeslut.

IEEE 754-standarden för flyttal antogs inte ens förrän 1985, och minnet mättes i K, inte G. Dubbeltal med flyttal var inte det effektivaste sättet att representera tecken eller heltal, men det var vad vetenskapsmän, ingenjörer och, i allt större utsträckning, matematiker ville använda för det mesta. Dessutom behövde variabler inte deklareras och minnet behövde inte uttryckligen allokeras. Genom att låta datorn sköta dessa uppgifter och ta bort datatyperna frigjorde man hjärnan för att tänka på de algoritmer som skulle bearbeta uppgifterna.

Arrayer var viktiga eftersom numeriska algoritmer inom linjär algebra höll på att komma till sin rätt, i form av LINPACK och EISPACK. Men att få tillgång till dem med standardflaggan inom vetenskaplig databehandling, FORTRAN 77, var en process i flera steg som innebar deklaration av variabler, anrop av kryptiskt namngivna rutiner, kompilering av kod och sedan granskning av data- och utdatafiler. Att skriva en matrismultiplikation som A*B och få svaret utskrivet direkt var en förändring i spelet.

MATLAB gjorde också grafik enkelt och mycket mer lättillgängligt. Inga krångliga maskinspecifika bibliotek med anrop på låg nivå, bara plot(x,y) och du såg i stort sett samma sak som alla andra med MATLAB skulle se. Det fanns fler innovationer, som inbakade komplexa tal, glesa matriser, verktyg för att bygga plattformsoberoende grafiska användargränssnitt och en ledande svit av ODE-lösare, som gjorde MATLAB till platsen för vetenskaplig beräkning i tankens hastighet.

Den utformning som var idealisk för interaktiva beräkningar, även långvariga sådana, var dock inte alltid gynnsam för att skriva bra och prestandakraftig programvara. Att flytta data mellan många funktioner krävde att man jonglerade med många variabler och att man ofta konsulterade dokumentationen om in- och utdataargument. En funktion per diskfil i ett platt namnområde var uppfriskande enkelt för ett litet projekt, men en huvudvärk för ett stort projekt. Vissa programmeringsmönster (vektorisering, förallokering av minne) måste tillämpas om man ville undvika flaskhalsar i hastigheten. Vetenskaplig databehandling tillämpades nu på betydligt fler områden, med stora mängder av olika typer av ursprungliga data. Etc.

MathWorks reagerade genom att fortsätta att förnya MATLAB: inline-funktioner, inbäddade funktioner, variabelslutningar, många datatyper, objektorienterade funktioner, ramar för enhetstestning, och så vidare och så vidare. Varje innovation var förmodligen en lösning på ett viktigt problem. Men ackumulationen av 40 år av dessa förändringar har haft som bieffekt att enkelheten och enhetligheten i konceptet har urholkats. År 2009 skrev jag en bok som på mindre än 100 sidor ganska väl täckte vad jag ansåg vara det väsentliga i MATLAB. Såvitt jag vet finns alla dessa saker fortfarande tillgängliga. Men du måste kunna mycket mer nu för att kalla dig skicklig.

Python

Pythons historia verkar på sätt och vis nästan vara en spegelbild av MATLAB:s historia. Båda hade en interaktiv kommandorad (numera allmänt kallad REPL, för ”read-eval-print loop”) och frihet från variabeldeklarationer och kompilering. Men MATLAB skapades som en lekplats för numeriska analytiker, medan Python skapades med hackare i åtanke. Var och en av dem växte sedan mot den andra publiken genom revideringar och utvidgningar.

För mig saknar Python fortfarande matematisk attraktionskraft. Du har fulhet och små irritationsmoment som ** istället för ^, @ för matrismultiplikation (en ny innovation!), ett shape istället för storlek på en matris, radorienterad lagring osv. Om du tror att V.conj().T@D**3@V är ett elegant sätt att skriva $V^*D^3V$ kan du behöva träffa en läkare. Och det finns nollindexering (i motsats till index som börjar vid 1). Jag har läst argumenten, och jag tycker inte att de är avgörande. Det är helt klart en fråga om preferens – en fråga om heliga krig på nätet – eftersom man kan anföra otympliga exempel för båda konventionerna. Vad jag tycker är avgörande är att vi har decennier av matematisk praxis för att indexera vektorer och matriser från ett, och att de flesta pseudokoder gör det antagandet.

Bortom de små irritationerna tycker jag att ekosystemet Python+NumPy+SciPy är klumpigt och inkonsekvent. Exempel A är det faktum att trots att språket är ganska inriktat på objektorientering finns det en matrisklass, och ändå avråds från att använda den och den kommer att bli föråldrad. Kanske har MATLAB helt enkelt korrumperat mig, men jag anser att matriser är en tillräckligt viktig typ av objekt för att finnas kvar och främjas. Är inte ett av OOP:s främsta försäljningsargument att man kan låta * göra olika saker för matriser och matriser? Det finns många andra oegentligheter i detta avseende. (Varför behöver jag ett kommando som heter spsolve? Kan jag inte bara anropa solve för en gles matris? Och så vidare och så vidare.)

Det finns också ställen där det numeriska ekosystemet ser lite tunt ut för mig. Till exempel ser kvadratur- och ODE-lösarna ut som en minimal uppsättning 2019. AFAICT det finns inga metoder för DAEs, DDEs, symplektiska lösare eller implicita lösare som tillåter inre Krylov-iterationer. Ta en titt på referenserna för dessa funktioner; de är för det mesta 30 eller fler år gamla – de är fortfarande bra, men långt ifrån kompletta. Matplotlib-paketet är ett fantastiskt arbete, och ett tag såg det bättre ut än MATLAB, men jag tycker att det fortfarande saknar 3D-paketet.

En del experter hävdar att det finns djupa orsaker till varför Python-kod kämpar för att hålla samma exekveringshastighet som kompilerade språk. Jag roas av resultaten av en sökning på ”python is too slow”. Pythons förkämpar framför många av samma argument/förlåtelser som folk gjorde för MATLAB på den tiden. Det betyder inte att de har fel, men det finns mer än bara ett uppfattningsproblem.

Jag tror att jag förstår varför Python har varit så spännande för många människor inom vetenskaplig databehandling. Det har en viss MATLAB-liknande syntax och kraft, tillgänglig från en REPL. Det har bra verktyg runt omkring sig och spelar bra med andra språk och områden inom databehandling. Det erbjöd detta utan kostnad och med mycket bättre långsiktig reproducerbarhet. Det är uppenbart att det fungerar bra för många människor som förmodligen inte ser någon större anledning att ändra sig.

Men för de saker som jag vet hur man gör inom vetenskaplig databehandling känns Python mycket mer som en syssla att lära sig och använda än vad jag är van vid. Vi kommer inte att få veta på ett tag om det kommer att fortsätta att svepa genom samhället eller om det redan har närmat sig sin höjdpunkt. Jag har inga särskilda förutsägande krafter, men jag är nedåtgående.

Julia

Julia har fördelarna och nackdelarna med att vara en eftersläntrare. Jag applåderar Julia-skaparna för att de trodde att de kunde göra det bättre:

Vi vill ha ett språk som är öppen källkod, med en liberal licens. Vi vill ha hastigheten hos C med dynamiken hos Ruby. Vi vill ha ett språk som är homoikoniskt, med riktiga makron som Lisp, men med uppenbar, välbekant matematisk notation som Matlab. Vi vill ha något som är lika användbart för allmän programmering som Python, lika enkelt för statistik som R, lika naturligt för strängbearbetning som Perl, lika kraftfullt för linjär algebra som Matlab, lika bra på att limma ihop program som skalet. Något som är smutsigt enkelt att lära sig, men som ändå gör de mest seriösa hackarna nöjda. Vi vill ha det interaktivt och vi vill ha det kompilerat.

I stor utsträckning tror jag att de har lyckats. Sent på vägen till version 1.0 verkade de tona ner REPL en aning, och det fanns några nästan gratis utvikningar bort från MATLAB. (Hur exakt är LinRange bättre än linspace?) Detta är dock småsaker.

Detta är det första språk jag har använt som går utöver ASCII. Jag får fortfarande en orimligt stor tillfredsställelse av att använda variabler som ϕ och operatörer som . Det är mer än kosmetiskt; att kunna se mer ut som de matematiska uttryck vi skriver är ett verkligt plus, även om det komplicerar undervisningen och dokumentationen lite.

Arbetet i Julia avslöjade för mig att jag plockade upp vissa programmeringsvanor på grund av MATLAB:s val, inte på grund av inneboende överlägsenhet. Vektorisering är inte naturligt för många saker. Det är uppseendeväckande att upptäcka i Julia att du kan vektorisera vilken funktion som helst bara genom att lägga till en punkt till dess namn. Att konstruera en matris genom en comprehension får inbäddade slingor (eller meshgrid-trick) att se ut som buggy whips i jämförelse, och att undvika en matris helt och hållet via en generator för en enkel summering känns som att få något för ingenting. (Jag är medveten om att Python har liknande språkfunktioner.)

Den stora funktionen multipel avsändning gör vissa saker mycket enklare och tydligare än vad objektorientering gör. Anta till exempel att du har klasserna Wall och Ball i ett traditionellt objektorienterat språk. Vilken klass ska upptäcka om en boll kolliderar med en vägg? Eller behöver du en Room-klass för att spela domare? Den här typen av frågor kan driva mig till vansinne. Med multipel avsändning paketeras data i objekttyper, men de metoder som arbetar med data är inte bundna till en klass. Så

function detect_collision(B::Ball,W::Wall)

känner till typerna men definieras oberoende av dem. Det har krävts en hel del programmering för att jag skulle uppskatta hur intressant och potentiellt viktigt begreppet multipel avsändning är för att utöka språket.

Det numeriska ekosystemet har utvecklats snabbt. Mitt främsta exempel är DifferentialEquations.jl, skriven av den fantastiska Chris Rackauckas. Om denna programvara inte vinner Wilkinsonpriset snart är systemet trasigt. Det är bara att gå till webbplatsen och förbereda sig på att bli omvänd.

Jag har ännu inte sett de stora hastighetsvinster jämfört med MATLAB som Julia lovar. Delvis beror det på min relativa oerfarenhet och den typ av uppgifter jag utför, men det beror också delvis på att MathWorks har gjort ett otroligt bra jobb med att automatiskt optimera koden. Det är i alla fall inte en aspekt av kodning som jag fokuserar på för det mesta.

Programmering i Julia har tagit mig ett tag att känna mig bekväm med (kanske börjar jag bara bli gammal och kristalliserad). Det får mig att tänka på datatyper mer än vad jag skulle vilja, och det finns alltid en smygande misstanke om att jag har missat det rätta sättet att göra något. Men för daglig användning är det ungefär lika troligt att jag vänder mig till Julia som till MATLAB nu.

Slutsatsen

MATLAB är företagslösningen, särskilt för ingenjörsarbete. Det är förmodligen fortfarande det enklaste att lära sig för grundläggande numeriska uppgifter. Noggrann dokumentation och årtionden av bidragande inlärningsverktyg spelar definitivt roll.

MATLAB är BMW-sedanen i den vetenskapliga datorvärlden. Den är dyr, och det är innan man börjar prata om tillbehör (verktygslådor). Du betalar för en stenhård, smidig prestanda och service. Det lockar också till sig en oproportionerligt stor mängd hat.

Python är en Ford pickup. Den är allestädes närvarande och älskad av många (i USA). Den kan göra allt du vill, och den är byggd för att göra vissa saker som andra fordon inte kan göra. Chansen är stor att du kommer att vilja låna en då och då. Men den erbjuder ingen stor ren körupplevelse.

Julia är en Tesla. Den är byggd med ett djärvt mål att förändra framtiden, och det kan den göra. Den kan också bli bara en fotnot. Men under tiden kommer du att ta dig dit du ska med stil, och med kraft i överflöd.

Lämna ett svar

Din e-postadress kommer inte publiceras.