Ny DIKU-professor: F# og Haskell viser vejen ud af multicore-krisen
Et ældre paradigme fra datalogien, funktionsorienteret programmering, er blevet taget ned fra loftet, støvet af og gjort mere aktuelt end nogensinde før.
Årsagen er multicore-processorerne, der i dag findes i alt fra supercomputere til mobiltelefoner.
De er langt sværere at programmere end processorer med en enkelt kerne, men det kan funktionsorienterede sprog være med til at ændre.
Sådan lød budskabet fra datalog Fritz Henglein ved hans tiltrædelsesforelæsning som professor i programmeringssprog- og systemer ved Datalogisk Institut på Københavns Universitet i sidste uge.
Funktionsorienteret programmering kan rent teoretisk spores tilbage til den berømte amerikanske matematiker og datalog Alonzo Church i 1930'erne.
Alligevel er det i dag vigtigere end nogensinde før og kan meget vel vise sig at være en del af løsningen på de problemer, softwareudviklere står over for, når moderne computere med mange processorer og CPU-kerner skal programmeres.
»Funktionsorienteret programmering er problemorienteret og fokuserer mere på, hvad der skal løses, end hvordan det skal løses. De eksisterende sekventielle programmeringssprog vil være trenden i mange år endnu. Men vi vil se mere og mere 'impact' fra funktionel programmering fremover,« siger Fritz Henglein i et interview med Version2.
Eksempler på funktionelle programmeringssprog er Haskell og Erlang, men også moderne, 'general purpose'-sprog som F# og Scala understøtter paradigmet.
Paradigmet udspringer af den såkaldte lambda calculus fra 1930'erne og giver kort fortalt programmøren mulighed for at udtrykke på et højt abstraktionsniveau, hvad der skal gøres, frem for at give en trin for trin-opskrift på, hvordan det skal gøres.
Altså mere i stil med »tag en samling af data, 'x', og gør 'y' ved den«, end en sekventiel gennemgang af hvert skridt i en algoritme, som de fleste programmører er vant til.
Den tankegang er tiltalende i en tid, hvor CPU'ernes clock-frekvens er fastfrosset omkring de 2-3 gigahertz, og bedre ydelse derfor kun kan hentes ved at fordele programmer parallelt i tråde på tværs af mange processorkerner.
Færre linjer kode
De funktionelle programmeringssprog er oplagte til videnskabelig og teknisk programmering, men kendes også fra systemprogrammering og webprogrammering på store datamængder.
Eksempelvis er Googles parallelle framework, MapReduce, funktionsorienteret.
Fordelen kan være, at programmøren ikke skal tænke så meget over konkrete problemer som for eksempel kommunikation og synkronisering mellem programtråde på de enkelte processorkerner, der er én af de helt store udfordringer ved at skrive programmer til multicore-processorer.
Samtidig er det nemmere at undgå fejl i kildekoden, fordi funktionsprogrammering typisk giver færre linjer kode, som er mere overskuelig at læse.
Det stiller dog også krav til de funktionelle programmeringssprog, og flere spørgsmål er stadig ubesvarede.
»Det er et 'grand challenge problem' inden for datalogien at finde ud af, hvordan vi løser udfordringen med programmeringen af computermodeller, der bliver stadig mere højt parallelle. Vi bliver nødt til at sikre, at concurrency er understøttet i sprogets syntaks på en måde, som er naturlig for programmøren. Samtidig skal compileren sørge for, at parallelliseringen af koden også foretages korrekt og udnytter parallelarkitekturer effektivt,« siger Fritz Henglein.
Og så er det vigtigt, at de funktionelle sprog ikke bare kapper forbindelsen fuldstændig til de eksisterende programmeringssprog som eksempelvis C#, Java og C++.
»De fleste udviklere vil sige, at de har tabt, hvis de bliver tvunget til helt at opgive de programmeringssprog, de kender i forvejen,« forklarer Fritz Henglein.
Han fremhæver sprog som det .NET-baserede F# og det Java-baserede Scala som konkrete eksempler på sprog, der kan bruges til funktionsorienteret programmering uden at slå hånden af de sprog, de bygger på.
»Et godt eksempel er F# (udviklet af Microsoft, red.), som gør det nemt at bruge abstraktioner fra funktionsprogrammering. Der risikerer programmørerne ikke at tabe funktionalitet, fordi de har adgang til den fulde .NET-platform og Visual Studio-understøttelse. Og så er sproget bakket op af én af verdens allerstørste it-virksomheder.«
Fritz Henglein er forskningsleder på projektet HIPERFIT, som kombinerer forskning i programmering, high performance computing og finans.
Projektet søger at afklare flere af udfordringerne ved at programmere moderne, parallelle computere. HIPERFIT har modtaget 31,4 millioner kroner i støtte fra Det Strategiske Forskningsråd.
Har du selv erfaring med funktionsorienterede sprog som for eksempel Haskell og F#? Hvornår er det hensigtsmæssigt at bruge dem? Hvilke udfordringer er der ved at programmere funktionsorienteret sammenlignet med eksempelvis objekt-orienteret eller imperativt? Giv dit besyv med i debatten nedenfor.
Kommentarer (6)
Funktionel programmering er langt mere centreret om hvordan data-flow i programmet opfører sig end om hvordan kontrol-flow er. Det er i skarp kontrast til imperativ programmering, hvor det oftest er kontrol-flow der regerer.
Fordelen ved at være orienteret omkring dataflow er at dine programmer i højere grad har en form hvor data ikke deles mellem de enkelte komponenter i programmet. Hele hemmeligheden for at få fart på parallelle arkitekturer er at data ikke må deles, fordi vi så kan køre de 2 komponenter ved siden af hinanden, og i mange tilfælde på samme tid.
Sat lidt på en spids: Hvis ikke funktionelle programmer kan parallelliseres, så kan imperative ditto det heller ikke - og noget tyder på at det er meget nemmere hvis sproget er funktionelt.
Personligt laver jeg stort set ikke andet end at skrive programmer i funktionelle sprog: Erlang, Haskell og Ocaml er sprog jeg skriver mange linier kode i. Den anden rigtigt interessante faktor er at programmer skrevet funktionelt typisk er mere abstrakte, nemmere at få til at virke og har færre fejl end imperative ditto. Og efterhånden er deres tidligere akilleshæl, Eksekveringshastigheden, helt væk. Det er specielt tilfældet hvis flere kerner skal udnyttes.
Mange webudviklere har dyppet tæerne i funktionel programmering måske endda uden at ane det. XSLT er funktionsorienteret, selv om det mangler visse elementer for at kunne kaldes et rigtigt funktionsorienteret programmeringssprog. Disse mangler kan dog til dels afhjælpes med FXSL (http://fxsl.sourceforge.net/).
Hvis man vil smage den funktionsorienterede fisk, er XSLT tillige et let sted at begynde - man behøver blot en webbrowser og en teksteditor.
Deklarative sprog har er stor fordel i fokus på funktion frem for implementeringsteknik - i modsætning til imperative sprog. Omvendt skaber den større afstand til hardware, abstraktionen, en mindre udnyttelsesgrad - det generiske abstraktionslag i sig selv, bruger ressourcer. Det gør heldigvis ikke så meget i situationer med flerkernede processorer. Tværtimod.
Udnyttelse af flere kerner til samme opgave kan ske med forskellige teknikker. Fælles er en øget abstraktion - væk fra hardwaren. Om det er i form af funktionelle sprog, parallelliseringsbibloteker eller parallelliserende sprogkonsktruktioner i imperative sprog, er knapt så interessant. Samtidig giver den den øget abstraktion andre gevinster - f.eks. færre systemsspecifikke bindinger.
Jeg downloadede (en version af) OCAML for netop at se på det som et parelleliserbart sprog. Men runtime var implementeret med en "Great Runtime Lock" (ligesom Python) - og så kan man jo ikke parellisere nogle som hen :-(
Jeg kender ikke meget til O'Camls implementering (andet end at den sekventielle kode er superb), men GHC, den suverænt mest udbredte implementering af Haskell, har yderst fornuftig understøttelse for parallelisering. Ellers er der jo Erlang, som muligvis også er det funktionssprog som er mest udbredt i industrien.
Haskell har endvidere lang mere finkornet kontrol med at afvikle programmer parallelt i forhold til Erlang. Det kan formentlig betyde alt i forbindelse med visse problemer.
Erlang er noget mere grovkornet.

