Julia - äntligen ett snabbt språk för matematiska tillämpningar

Julia - äntligen ett snabbt språk för matematiska tillämpningar

2020-11-30

Artificiell intelligens, maskininlärning och big data har gjort matematik till ett riktigt hett område inom mjukvaruutveckling. Tidigare var det mest forskare som kombinerade matematik och programmering, eller så var det något som studenter tvingades sätta sig in för att klara en jobbig tenta på universitetet.

Python fick tidigt stöd för dessa matematiska tillämpningar och eftersom språket är lätt att lära sig blev det snabbt populärt inom data science som är samlingsbegreppet för allt detta. Men alla gillar inte Python. Matematiker brukar till exempel föredra MATLAB eller Mathematica eftersom syntaxen påminner mer om matematik och programmerare klagar ofta på att Python är för långsamt. Perfekta förutsättningar för att andra språk skall kunna ta sig in på marknaden med andra ord.

Ett annat språk som snabbt ökade i popularitet var R. Det är ganska överraskande med tanke på att språket, precis som Python, har funnits sedan början av 1990-talet och inte är känt för att vara snabbt. Förklaringen till dess popularitet var att det har bra stöd för den typ av statiska beräkningar och visualisering som används vid analys av big data. Men trots att det nu fanns två populära språk var det bara en tidsfråga innan det skulle dyka upp ett helt nytt språk som verkligen var anpassat för programmering med matematisk inriktning.

Julia är precis ett sådant språk och intresset för det ökar snabbt trots att det fortfarande får anses vara ganska omoget. Första versionen släpptes 2012 så det är 20 år modernare än Python och R, vilket är positivt eftersom det hinner hända mycket under två årtionden i IT-världen. Två viktiga exempel är CPU:er med många kärnor och molnplattformar. Båda dessa kräver bra stöd för parallell och distribuerad programmering, vilket Julia stödjer väl.

Skaparna av Julia hade riktigt ambitiösa mål och drömmar. Men ändå inte orealistiskt ambitiösa eftersom gänget bakom Julia består av matematiker och programmerare med lång erfarenhet inom sina respektive områden. Här är några av sakerna de drömde om eller inspirerades av när de designade språket:

  • Lika snabbt som C
  • Perls kraftfulla stränghantering
  • Lika naturligt för en matematiker som MATLAB
  • Lisps makron och möjlighet att betrakta kod som data
  • Lika väl lämpat för generell programmering som Python
  • Unix-skalets förmåga att koppla ihop program med varandra

Men programmeringsspråk blir sällan starka på egen hand. Det krävs oftast ett välutvecklat ekosystem med alltifrån editorer och debuggers till bibliotek för populära tillämpningar. Framförallt bristen på välfungerande bibliotek brukar vara en utmaning och något som verkligen kan hålla tillbaka utvecklingen av ett språk. Julia har löst detta genom att göra det enkelt och effektivt att anropa kod skriven i C. Men det går även lätt att anropa kod skriven i Python och flera andra språk. Vad gäller verktygsstöd så går det bra att använda populära editorer och IDE:er som Emacs, VSCode samt IntelliJ via plugins. Det finns också en specifik Julia IDE vid namn Juno som är baserad på den välkända Atom-editorn.

För att demonstrera Julias matematiska rötter kommer här två exempel på hur enkelt det är att skapa och använda funktioner i Julia. Har man lite vana av att skriva matematiska uttryck på en dator kan man nästan gissa sig fram till syntaxen i Julia.

julia> f(x) = x^2
f (generic function with 1 method) 

julia> f(3)
9

julia> f(x) = sin(x)
f (generic function with 1 method) 

julia> f(pi/2)
1.0

Plottning av data och diagram är också viktiga områden inom matematisk programmering och det finns många sätt att göra det på i Julia. Nedan följer ett exempel som installerar och använder det välkända paketet GR och sedan ritar upp ett histogram över 10 000 stycken normalfördelade slumpmässiga värden. Riktigt imponerande att detta går att göra med bara tre rader kod, eller egentligen bara en rad kod.

julia > Pkg.add("GR")
Installing known registries into `~/.julia`
...

julia> using GR
[ info: Precompiling GR [28b8d3ca-fb5f-59d9-8-90-bfdbd6d07a71]

julia> histogram(rand(10000))

Parallellprogrammering i Julia görs bland annat med hjälp av remote calls som returnerar en Future, som är en slags referens till ett jobb som utförs i en annan process eller tråd. Startar man upp Julia med -p n som kommandoradsargument så skapas n stycken worker-processer som kan användas för parallellprogrammering. Ett väldigt enkelt sätt att sedan skapa ett remote call är genom @spawn macrot som kör ett uttryck i en annan tråd eller process.

I exemplet nedan används @spawn först för att skapa en 2x2 array/matris med slumpvärden mellan noll och ett i varje element/cell i arrayen/matrisen. Sedan används @spawn igen för att addera 1 till varje element i arrayen med hjälp av Julias kraftfulla dot operator som utför en operation på varje element i en array. I exemplet nedan utför alltså .+ en addition på varje element. Denna gång används resultatet från det första anropet till @spawn med hjälp av funktionen fetch som “väntar in” och hämtar resultatet från ett jobb eller en process.

$ ./julia -p 2

julia> r = @spawn rand(2,2)
Future(2, 1, 4, nothing)

julia> s = @spawn 1 .+ fetch(r)
Future(3, 1, 5, nothing)

julia > fetch(s)
2 * 2 Array{Float64,2}:
1.66101 1.8835
1.61964 1.4839

Skriven av Henrik Bergström

Har du idéer på ett intressant eller roligt ämne att skriva om eller kanske till och med en redan färdig artikel? Klicka här för att läsa mer.

Demando