Makkelijkste weg naar multicore loopt via besturingssysteem

Author:

John Carbone is vicepresident marketing bij Express Logic en heeft 35 jaar ervaring in realtime computersystemen en software.

Reading time: 6 minutes

Met een paar ingrepen aan het besturingssysteem kan veel bestaande software al redelijk efficiënt worden uitgesmeerd over een symmetrische multiprocessor. John Carbone van Express Logic legt uit waar de valkuilen zitten bij het geschikt maken van een RTos voor een SMP-systeem.

Vandaag de dag zien we Soc-architecturen met meerdere cores of processoren steeds meer doordringen in een brede reeks embedded consumenten- en communicatiesystemen. Software die verschillende taken tegelijkertijd moet uitvoeren, kan met de multicoreaanpak betere prestaties halen zonder het verkwistende stroomverbruik van een singlecore processor die tot zijn maximale kloksnelheid wordt opgezweept. Dan gaat het bijvoorbeeld om settopboxen die verschillende televisiezenders opnemen en tegelijkertijd filmpjes via internet delen, of een autocomputer die tegelijkertijd de navigatie verzorgt voor de bestuurder en computerspelletjes voor de kinderen op de achterbank.

Maar multiprocessoren introduceren allerlei extra complexiteit voor programmeurs. Zij hebben hier betere softwareondersteuning voor nodig, onder meer van het besturingssysteem. Voor zowel de commerciële RTos-aanbieders als de grofweg vijftig procent van de ontwikkelaars die nog steeds hun eigen realtime kernels bouwen, zijn dit forse uitdagingen. Nu er chipontwerpen met zes, zeven of zelfs meer rekenelementen opduiken, wordt het duidelijk dat het ontwikkelproces flink op de schop genomen zal moet worden.

Op dit moment kan er echter al een aanzienlijke groep embedded toepassingen binnen de consumentenelektronica profiteren van multicore, via de symmetrische multiprocessingaanpak (SMP) die oorspronkelijk werd ontwikkeld voor serverclusters en uitgebreide rekentoepassingen. Programmeurs kunnen hiermee nagenoeg volledig werken met hun oude vertrouwde sequentiële, procedurele programmeermodel. Met voldoende aandacht voor realtimeprestaties, multithreading en realtime interruptafhandeling zijn zelfs bestaande RTos‘en hiervoor in te zetten. Het is weliswaar niet mogelijk om versnellingen te halen van honderd procent per core, maar significante verbeteringen van tussen de twintig en negentig procent liggen zeker binnen bereik.

Microseconde

Multiprocessoren zijn er in verschillende configuraties, variërend van grids met processoren die losjes gekoppeld zijn via internet tot aan symmetrische multiprocessoren waarin de cores (doorgaans in koppels of groepjes van vier) het geheugen en andere bronnen met elkaar delen. Dit SMP-model kan in het voordeel werken van de programmeur, met name doordat alle processoren bij hetzelfde geheugen kunnen en doordat een proces of thread dus vanuit dezelfde geheugenlocatie op elke processor kan draaien. Dit is de sleutel tot het aanpassen van een toepassing voor een SMP-architectuur.

Arms MPCore is een voorbeeld van zo‘n architectuur. MPCore-multiprocessoren kunnen tot vier cores in een SMP-configuratie bevatten en implementeren adaptive shutdown en Arms Intelligent Energy Manager-technologie, waarmee stroombesparingen tot 85 procent zijn te behalen. Idealiter kan een applicatie net zo goed overweg met een, twee, drie of vier cores zonder rekening te houden met het specifieke aantal. Dit zou het een stuk makkelijker maken om de implementaties over te zetten en codehergebruik sterk verbeteren – met de nodige resultaten voor de time-to-market.

Applicaties die verschillende onafhankelijke taken moeten uitvoeren, profiteren het makkelijkst van multicore: het besturingssysteem verdeelt de taken steeds netjes over de beschikbare cores.

Met de juiste configuratie kan ook een traditioneel RTos de multiprocessortoepassing al op verschillende manieren helpen. De taken van een RTos zijn traditioneel het afhandelen van interrupts en het beheren van threads: op zichzelf staande stukken code die een specifieke rol vervullen. Een deterministische realtime applicatie bestaat in de regel uit meerdere threads. Het RTos bepaalt aan de hand van hun prioriteit en externe gebeurtenissen (interrupts) welke thread er aan de beurt is om te draaien.

Een multiprocessor-RTos dat zich richt op de multimedia-intensieve mobiele of consumententoepassingen moet – of het nu om commerciële of zelf geschreven versies gaat – op zijn minst interrupts met responstijden onder de microseconde kunnen afhandelen. Daarnaast moet het een ongelimiteerd aantal threads met dezelfde of verschillende prioriteiten aankunnen, met deterministische scheduling. Voor de beste prestaties moet het ook klein genoeg zijn om in het on-chip geheugen te passen, doorgaans tussen de 32 en 128 kB aan Rom of flash.

Het RTos moet verder kunnen inspelen op variaties in de hoeveelheid rekenwerk, zodat alle cores ingezet worden als de vraag hoog is en het systeem de kloksnelheden kan aanpassen als de vraag laag is. De threads moeten ook niet specifiek worden toegewezen aan een bepaalde core; de applicatie moet hardwareagnostisch blijven.

Als het het RTos bovendien een mechanisme heeft voor realtime interprocescommunicatie (IPC) zijn de threads over cores heen te synchroniseren. De programmeur kan zich dan richten op het algoritme en hoeft zich niet te bemoeien met details over waar zijn code draait.

Wachtstand

Een typisch applicatiedomein waarin een RTos met SMP-capaciteiten een verschil kan maken, is streaming multimedia. Hierbij moet op al dan niet gelijktijdige datastromen aanzienlijke rekenkracht worden losgelaten voor compressie en decompressie, encryptie en de-encryptie, renderen, filteren, vergroten of verkleinen, enzovoorts. In een doorsnee systeem wordt een afgemeten hoeveelheid data voor het beeldscherm of een een bewerking via een DMA-opdracht in een geheugenbuffer geladen. Zodra die vol is, wordt er een interrupt gegenereerd als seintje voor de applicatie, die de gegevens bewerkt terwijl een nieuwe buffer wordt gevuld.

Dit model beschrijft een dataflow die weliswaar continu is, maar varieert in intensiteit. Realtime reacties op het arriveren van data zijn hier belangrijk en de totale throughput is het doel, maar programmeergemak is het sleutelwoord.

Een van de meest intrigerende aspecten van een SMP-RTos is de load balancing zonder tussenkomst van de programmeur. Dit maakt het leven van de ontwikkelaar makkelijker, maar belangrijker nog: het wordt mogelijk om legacycode zonder al te veel aanpassingen te draaien op een SMP-systeem. Om deze benadering te kunnen gebruiken, moet de programmeur meerdere (identieke) threads opzetten met gelijke prioriteit en elke thread toewijzen aan een deel van de datastroom.

De prioriteiten zijn een belangrijk aspect. Een prioriteitgebaseerde pre-emptive scheduler kan meerdere cores gebruiken om de klaarstaande threads te draaien. Daarbij worden de threads met een hoge prioriteit uitgevoerd vóór die met een lagere prioriteit. Ze kunnen er dus op vertrouwen dat er geen code met lagere prioriteit draait terwijl ze bezig zijn. Het RTos moet deze regel ook bij een SMP-systeem doorvoeren, anders kan de logica die ten grondslag ligt aan een legacytoepassing in de mist lopen.

Na initialisatie bepaalt de RTos-scheduler welke thread de hoogste prioriteit heeft, om vervolgens de context ervoor te creëren en hem uit te voeren. Daarna kijkt de scheduler of er nog een thread klaarstaat met gelijke prioriteit en start hij die op de tweede core als die er is, en zo gaat het door. Als er geen threads meer klaar staan, zet de scheduler zichzelf in wachtstand totdat er een externe gebeurtenis of service-request binnenkomt.

Een thread mag daarbij alleen starten als hij dezelfde prioriteit heeft als de threads op de andere cores. En als er een thread klaar wordt gezet terwijl een andere thread met een lagere prioriteit draait, volgt er een pre-emption: de laaggeplaatste thread wordt stilgelegd samen met alle lager ingeschaalde threads op andere cores. Dit is essentieel om de prioriteitshiërarchie te waarborgen.

Binnen deze automatische load balancing kunnen er extra features zijn om de prestaties verder te optimaliseren. Er kan bijvoorbeeld één core verantwoordelijk worden gemaakt voor de afhandeling van alle externe interrupts, zodat de andere cores nagenoeg zonder overhead van interruptafhandeling werken. Ook als er intensieve interruptactiviteit is, kunnen ze zich zo volledig op de applicatie focussen.

Triviaal

Multicore en multiprocessing worden de komende tijd veel complexer en RTos‘en zullen zich hier veel meer aan moeten aanpassen dan nu het geval is. Voor SMP-omgevingen hoeven we echter geen radicaal andere OS-architectuur te gebruiken. Met een aantal ingrepen aan de onderliggende interrupt- en threadmechanismes kunnen we het RTos inzetten voor multiprocessing-omgevingen zonder het welbekende programmeermodel te hoeven aanpassen. Vooral de onderliggende datastructuur van het RTos zullen we op de schop moeten nemen naarmate processoren ingewikkelder worden dan de relatief eenvoudige dualcores. Voor load balancing moeten we wellicht een gedimensionaliseerde datastructuur gebruiken om de meerdere arrays te beheren. Bij een enkele processor zijn de mutexen, geheugenpools, eventtags, semaforen en queues al niet geheel triviaal om te managen. In een dualcore processor worden dat er al twee keer zo veel en in een quadcore vier keer zo veel.

Ironisch genoeg is het hierbij niet van belang om het meest geavanceerde RTos met de meeste features te gebruiken, maar juist het kleinste met de beste realtime interruptafhandeling. Een dergelijke gedimensionaliseerde datastructuur vereist – afhankelijk van de implementatie – tussen de tien en vijftig procent meer coderuimte en heeft een vergelijkbare impact op de interruptafhandeling. Dat is voor een OS met submicrosecondeafhandeling en een codegrootte van enkele tientallen kilobytes niet zo‘n heel groot probleem. Maar een Linux-gebaseerd ontwerp, met responstijden van tientallen microseconden en een omvang van een à twee megabyte, wordt bij een toename van slechts tien procent al buitenspel gezet voor veel multimedia-intensieve consumententoepassingen.