Roy Lurie is vicepresident engineering bij The Mathworks. Hij is verantwoordelijk voor de Matlab-productfamilie en voor specifieke teams op gebieden als beeldverwerking, besturingsontwerp, computationele biologie, financiële modellering en analyse, parallelle en gedistribueerde verwerking, taaluitvoering en testen en meten.

20 January 2010

Multicore en gedistribueerde systemen maken een onstuimige ontwikkeling door. Programmeertalen staan voor de taak om het programmeren van deze systemen makkelijker te maken, maar daarbij moeten ze zo veel mogelijk van de onderliggende architectuur verbergen en ervoor zorgen dat een applicatieontwikkelaar zich kan focussen op zijn probleemdomein. Roy Lurie van The Mathworks beargumenteert dat compilerannotaties hier een goede aanpak zijn.

Weet u waar uw algoritmes over twee jaar zullen draaien? Of over vijf jaar? En tien? Bent u nu aan het investeren in code die u later weg kunt gooien? In zo ongeveer elke branche stijgt de interesse in en de behoefte aan high-performance computing. Van automobielsimulaties tot financiële risicomodellen en van systeembiologie tot het ontwerpen van communicatiesystemen is de vraag naar pure rekenkracht dramatisch toegenomen en dat zal de komende tijd niet minder worden.

Hardware speelt hierop in via multicore processoren. Dit zijn echter parallelle computers – en die zijn berucht om het lastige programmeren. Het schrijven of herschrijven van parallelle applicaties kan lastig en duur zijn, veel tijd vergen en onderhavig zijn aan fouten. Bovendien vereist het een nieuwe set programmeervaardigheden.

Het aantal manieren waarop de hardware verandert, stijgt explosief. Sommigen vrezen dat de thans beschikbare hardware daardoor op korte termijn alweer zal worden vervangen door iets snellers en beters. Dit is natuurlijk altijd al wel het geval geweest, maar tot nu toe was het niet echt een probleem omdat het ontwikkelmodel altijd uitging van een enkele core, programmeerbaar in C. In de wereld van FPGA‘s, GPU‘s, multicores, many-cores, accelerators, clusters, grids, Cell-processoren en herconfigureerbare hardware werkt dit model echter niet.

Bij veel organisaties is het intellectuele eigendom van algoritmes onlosmakelijk verbonden aan een taal of omgeving. Dit maakt migratie naar nieuwe technologie vrijwel onmogelijk. De experts die de subtiliteit van deze code en de optimalisaties voor de ’beste prestaties‘ begrijpen, zijn vaak vertrokken. Vanwege deze onzekere toekomst zorgt het prematuur selecteren van uw architectuur, taal en algoritme ervoor dat u, in het gunstigste geval, zwaar moet investeren in migratie van de code. In het slechtste geval zult u tot ver na de nuttige levensduur moeten leven met legacy systemen. Wat moeten softwareontwikkelaars en domeinexperts dus eisen van taalaanbieders om de kans op algoritmeveroudering te verkleinen?

 advertorial 

Free webinar ‘Modernizing your code base with C++20’

As many production tool chains now adopt C++20 features, the potential this brings is unlocked. What advantages can recent versions offer to your code base? In this webinar we’ll look at the great improvements C++ has gone through and how features like concepts and ranges can transform your code. Register for video access.

Actief onderzoeksterrein

In software-engineering is het een goed gebruik om een programma waar mogelijk te schrijven op de simpelste wijze, zodat het eenvoudig is te begrijpen en te onderhouden. Bij de eerste implementatie moeten nog niet gelijk de prestatieknelpunten worden meegenomen. Als u probeert te optimaliseren voordat het juiste algoritme beschikbaar is, leidt dat slechts tot speculatieve prestatieverbeteringen die de code minder goed leesbaar en onderhoudbaar maken.

Deze redenering kan ook toegepast worden op taalontwerp voor toekomstige high-performance systemen. Om uw langetermijninvestering in een algoritme te optimaliseren, dienen programmeurs het uit te drukken op een zo hoog mogelijk abstractieniveau, zonder vroegtijdig architectuur- of systeemspecifieke constructies toe te voegen. De tweede stap is dat gebruikers het algoritme annoteren met additionele informatie die richtlijnen en input geeft voor de onderliggende execution engine, zonder op een specifieke architectuur vast te pinnen. Dit kunnen bijvoorbeeld annotaties zijn om parallellisme in het algoritme te beschrijven.

GRAF ACH Mathworks
Door parfor te schrijven in plaats van for in een Matlab-programma geeft de programmeur aan dat de bewerkingen van de loop in willekeurige volgorde mogen worden uitgevoerd. Dat geeft de Matlab-omgeving de mogelijkheid om ze uit te smeren over meerdere processen op meerdere computers (workers), wat resulteert in een bijna lineaire versnelling van de uitvoer.

Het liefst is dit natuurlijk helemaal niet nodig en bepaalt de taal uit zichzelf al het optimale gebruik van een voorgeschotelde architectuur. Dit volledig impliciete systeem zou slechts een enkele stap vergen voor het uitvoeren van bewerkingen zoals automatische parallellisatie. Dit is een actief onderzoeksterrein. Op dit moment zijn er echter nog geen algemeen geldende oplossingen. Voor de afzienbare toekomst zal dus nog enige annotatie nodig zijn om de specifieke execution engine van aanwijzingen te voorzien voor optimale prestaties. Zo‘n systeem kan worden omschreven als ’minimaal expliciet‘, waarbij een minimale hoeveelheid expliciete informatie benodigd is om de execution engine te assisteren bij het bereiken van optimale prestaties.

Cluster

Met een dergelijk tweestapsmodel stelt de taal de domeinexperts in staat snel het juiste algoritme te ontwikkelen, zonder zich in eerste instantie zorgen te hoeven maken over architectuurnuances. Net als de wetenschappers en ingenieurs die de belangrijkste gebruikers zijn van high-performance computersystemen, moeten zij hun ideeën op een natuurlijke wijze kunnen uitdrukken zodat ze hun oplossingsruimte snel kunnen verkennen. Beeldverwerkingsexperts zouden bijvoorbeeld een taal tot hun beschikking moeten hebben waarin semantiek, syntax en functies passen bij de gebruikelijke manier waarop ideeën binnen dit domein worden uitgedrukt. Door hun de gelegenheid te geven zich volledig te richten op de algoritmeconcepten, in plaats van op de typische problemen rond geheugenallocatie, threading of databehandeling, kunnen ze snel de juiste algoritmes ontwerpen.

Een voorbeeld van een annotatie is de parfor-constructie in Matlab, die de for-instructie vervangt. parfor is ontworpen voor taakparallelle probleemtypes waar elke herhaling van de loop onafhankelijk is van elke volgende herhaling. Met het construct geeft de programmeur aan dat de iteraties in elke willekeurige volgorde kunnen worden uitgevoerd. Op een enkelprocessorsysteem gedraagt parfor zich als een traditionele for-loop, maar op een multicore machine of een cluster kan de execution engine de code parallel uitvoeren. Als Matlab de parfor-loop tegenkomt, voert het de berekeningen niet direct uit, maar verdeelt het deze parallel over workers. Dit zijn onafhankelijke Matlab-sessies, elk met hun eigen unieke geheugen. De benodigde data worden dus van de client naar de workers gestuurd en de uitkomsten worden na afloop weer teruggezonden en door de client samengevoegd.

Het mooie aan parfor is dat de gebruiker deze gegevensoverdracht niet hoeft te organiseren. Zodra Matlab de loop bereikt, voert het een statische analyse uit van de loop-body en bepaalt het welke informatie naar welke worker gaat en welke variabelen worden geretourneerd naar de client.

Met een geannoteerde aanpak kan hetzelfde algoritme dus worden gebruikt op een single-core CPU, maar ook op een multicore systeem met gedeeld geheugen, een cluster of een gespecialiseerde hardwareversneller, wat de rekentijd aanzienlijk zal verkorten. De gebruiker heeft hiervoor geen kennis nodig van wat er zich allemaal afspeelt onder de motorkap. Voor de ontwikkelaar is de enige cruciale eis voor het gebruik van het construct dat de volgorde van uitvoeren onbelangrijk is.

Hotspots

Andere voorbeelden van een dergelijke annotatie zijn de spawn– en sync-constructies aangeboden door Cilk, een algoritmische multithread-gebaseerde taal (supertech.csail.mit.edu/cilk). De filosofie achter Cilk is dat een programmeur zich dient te concentreren op het annoteren van een programma om parallellisme bloot te leggen en te profiteren van lokaliteit. Traditionele seriële C-code kan worden geannoteerd, en kan, indien gekoppeld aan het Cilk-runtimesysteem, efficiënt worden geschaald voor grootschalige threaded werking.

Cilk++ van Cilk Arts is een uitbreiding op Cilk die C++ naar de multicorewereld brengt, zonder dat dit ten koste gaat van seriële semantiek. De oplossing bestaat uit een simpele set extensies voor de C++-programmeertaal, een krachtig runtimesysteem en tools die de ontwikkeling van multicoresoftware vereenvoudigen.

De seriële semantiek van Cilk++ biedt drie belangrijke voordelen: prestaties, betrouwbaarheid en productiviteit. Het gehanteerde model zorgt voor schaalbare prestaties doordat het niet afhankelijk is van vooraf bij de programmeur aanwezige kennis over het aantal beschikbare processoren. Ontwikkelaars kunnen traditionele seriële tools voor prestatietuning gebruiken om hotspots te vinden en zowel seriële als parallelle prestaties te verbeteren. Ook debuggen en regressietesten gaat op de vertrouwde manier. De betrouwbaarheid verbetert via de testvoordelen die herhaalbaarheid en determinisme bieden, en via de mogelijkheid om een efficiënte en bewezen correcte race-detector te bouwen die de parallelle semantiek van het programma kan vergelijken met de seriële semantiek.

Ten slotte kunnen programmeurs hun vertrouwde paradigma‘s gebruiken voor nieuwe ontwikkeling, wat de productiviteit ten goede komt. Seriële legacy code kunnen ze eenvoudig converteren naar Cilk++ omdat ze deze niet hoeven te herschrijven om toch een compleet ander programmeermodel te kunnen gebruiken. De programmeur voegt Cilk++-kernwoorden toe aan een seriële C++-applicatie om parallellisme aan te geven.

Monte Carlo

Uiteraard zijn er ook situaties waarbij architectuur aan de basis staat van algoritmes en waarbij een duidelijk afgebakend tweestapsmodel onuitvoerbaar is. In de meeste gevallen biedt deze aanpak echter het duidelijke voordeel dat de gebruiker eenvoudigweg de taal vervangt om additionele informatie te verstrekken aan de onderliggende execution engine. Er is een minimale mentale belasting op de gebruiker om volledig te profiteren van de beschikbare hardware.

Een goed voorbeeld is een financiële kwantitatieve analist die een Monte Carlo-risicoanalyse van een portfolio probeert uit te voeren. Draaiend op een standaard pc zou deze analist een model bouwen in Matlab, gebruikmakend van specifieke financiële modelalgoritmes en componenten en van traditionele for-loops om te itereren over een uitgebreide set scenario‘s. Prestatieproblemen kunnen opdoemen vanwege de rekenkundige complexiteit van het vraagstuk. Na overgang op een multicore machine kan de analist hetzelfde programma gebruiken, waarbij for wordt vervangen door parfor. De nieuwe hardware gaat vergezeld van het voordeel van een proportionele snelheidsverbetering. Om de rekentijd nog verder terug te dringen, zou de analist de zelfde parfor-code ook kunnen uitvoeren op een afdelingscluster.

Met minimale inspanningen en zonder kennis van het onderliggende systeem is deze domeinexpert in staat om hoge prestaties te bereiken via minimale annotatie van het initiële Matlab-model. Dit zijn de resultaten die gebruikers van high-performance computing in de toekomst moeten eisen van alle talen.