DTU udvikler software til fremtidens computere
Flerkernede processorer bliver i stigende grad normen både i private hjem og på forskningsinstitutioner.
Mens hjemme-pc'en indtil videre kan præstere processorer med op til fire kerner, prøver forskere på Danmarks Tekniske Universitet (DTU) kræfter med processorer, der indeholder hele otte kerner, som hver kan håndtere fire tråde. Det vil sige processorer, som kan udføre 32 parallelle beregninger.
Det store antal kerner stiller særlige krav til softwareudviklingen, hvis hardware-ressourcerne skal udnyttes optimalt. Det lyder måske som et problem forbeholdt forskerne på DTU, men selvom computerne på DTU indtil videre har mange flere kerner end almindelige pc'er, er det blot et spørgsmål om tid, før antallet af kerner i pc'en på kontoret eller i hjemmet bliver mangedoblet.
Dermed bliver udfordringen i at udvikle software til flerkernede processorer særdeles aktuel. Således indeholder Cell-processoren i Sonys spillekonsol Playstation 3 allerede ni kerner.
Godt nok er de enkelte kerner i flerkernede arkitekturer som udgangspunkt langsommere målt på clockfrekvens end traditionelle processorer, men alligevel er det den vej, udviklingen går.
»Det er klart, at man går lidt ned i clockfrekvens, når man kører multi-core (flerkerne, red.), for at kunne pakke det tæt. Men så får man jo hastigheden igen ved at køre parallelt,« siger professor Henrik Madsen ved Institut for Informatik og Matematisk Modellering ved DTU.
Han kalder den softwareudvikling, der foregår på DTU, for udvikling af software til fremtidens computere.
»Der skete en kovending for et par år siden, hvor man fandt ud af, at man ikke kunne blive ved med at skrue på clockfrekvensen - så blev processoren simpelthen for varm. Så det er altså antallet af kerner, man skal til at skrue på,« siger Henrik Madsen og peger på, at nutidens software generelt ikke er gearet til at håndtere flere kerner, fordi almindelig software fungerer sekventielt og som udgangspunkt er lavet til kun at skulle fungere på en enkelt processor.
Automatisk optimering
Når kerneantallet nærmer sig fire og derover, bliver det for alvor svært at optimere softwaren til antallet af kerner. Ganske vist forsøger det underliggende styresystem, eksempelvis nyere Windows-versioner, at fordele processorbelastningen mellem de enkelte kerner, men nogen egentlig optimering af softwaren er der ikke tale om, idet en proces kun afvikles på en kerne.
»Det er jo to forskellige teknologier, om man skifter mellem forskellige processer, som kører på forskellige kerner, eller om man lader et program rigtigt udnytte multicore-hardwaren,« siger Henrik Madsen.
Han fortæller, at en af måderne, hvorved et stykke software kan kodes til at udnytte flere kerner, kan være at dele en løkke i et program op i flere løkker, som derefter bliver afviklet samtidigt i hver deres kerne. Det kan dog være svært for en programmør at gennemskue, hvornår sådan en manøvre kan betale sig. Ikke mindst fordi den gavnlige effekt af eksempelvis en løkke-opdeling afhænger af den underliggende hardware og problemstørrelsen.
Til det formål findes der dog allerede compiler-udvidelser, som automatisk kan foretage optimeringen af koden til en flerkernet arkitektur.
Open MP er en af de standarder, som Henrik Madsen og hans kollegaer på DTU bruger til at optimere programmer til processorer med flere kerner.
»Det er et af de moderne værktøjer til at flytte almindelig software til en multi-core, shared memory-arkitektur,« siger han.
Værktøjet kan kompilere og optimere Fortran, C og C++ kildekode, så det passer til en specifik processor-arkitektur, hvis programmøren tilføjer nogle Open MP-udvidelser til koden.
»Man kan tage stort set alle programmer, der er skrevet i de sprog, og ret let få dem gjort parallelle. Faktisk er det overset, hvor let det reelt er med Open MP,« siger Henrik Madsen og peger på, at man i Open MP kan bevare den sekventielle version af programmet i samme kildekode.
»En compiler, som ikke har OpenMP-extensions, vil simpelthen ignorere OpenMP-tilføjelserne.«
Men selv om der findes software eller compiler-udvidelser, der kan optimere kode til flerkernede arkitekturer automatisk, så kan det altid blive endnu bedre.
Supercomputere
»Der er jo forskellige knapper, man kan skrue på, når man bruger Open MP. Selvom det som udgangspunkt er rigtig let, kan man godt gå ind og hjælpe den lidt. Der kan man bl.a. bruge profileringsværktøjer,« siger Henrik Madsen og henviser til, at profileringsværktøjerne bl.a. gør det muligt at optimere et program til mængden af cache på en computer.
Udfordringen med at lave software, der kører på adskillige processorer, er ikke ny. Traditionelt består supercomputere i form af clustere og grids af flere computere og dermed processorer.
Men den arkitektur afspejler ifølge Henrik Madsen ikke den måde, fremtidens computere kommer til at se ud på, fordi der er tale om flere computere, der opererer i et netværk med hvert deres hukommelsesområde i modsætning til en SMP- (Symmetric multiprocessing) eller multicore-computer, hvor hukommelsen deles af et eventuelt større antal kerner.
»Ingen af de to teknologier (grid og cluster-computere, red.) adresserer det faktum, at vi nu ser rigtig multikerne-hardware,« siger han og tilføjer:
»Vi tror, at fremtidens CPU'er vil være den, der har den største ydelse pr. kubikcentimeter.«
Kommentarer (2)
I det store hele er jeg enig med Henrik Madsen.
Dog, er jeg ikke helt enigt i, at problemet er så stor med "stor klokfrekvens". Hvis det er samme ALU som udfører indstruktionerne, vil den blive varm - men er de flere om, at udføre indstruktionerne på skift, bliver de ikke så varme. Første indstruktion udføres således på første ALU, og næste indstruktion på næste ALU, tredie på næste igen osv. afhængig af antal ALU'er. Det viser sig, at de endog kan køre hurtigere. Forsinkelsen fra en ALU, og til næste ALU er mindre, end vejen om og tilbage igen, samt varmen distribueres ud.
Er vi lidt smartere, kan vi lave større blokke, der behandler flere indstruktioner samtidigt (VLIW). Trods afhængighed, og en indstruktion bruger data fra en anden indstruktion i samme blok, så øges "dybden" af den tid der tager at udføre n indstruktioner i et VLIW ord, typisk kun logaritmisk med antallet af indstruktioner.
I stedet for at have n indstruktioner der udføres på skift kan vi bruge et VLIW ord, og dybden af indstruktionerne er mindre end for synkron logik.
Derfor kan egentligt godt betale sig, at udføre indstruktionerne i rækkefølge (software synspunkt) - men ved loops skal de dog "foldes ud", således alle ALU'er har noget at lave.
Registre og memory har fælles access, men så længe data kan tages fra en ALU direkte, skal dette gøres, fremfor at hente fra registeret. Det tager for lang tid at hente fra registerer, i forhold til fra ALU'en. Tiden, der bruges til at skrive og læse fra registeret er underodnet, og indgår ikke i den kritiske path. De tidligere indstruktioner tages data direkte fra, så det fungerer som cache, og kun gamle data, hvor der er brugt lang nok tid på skrivningen, hentes fra registeret direkte. Eventuelt, kan sættes ekstra registre på, så data kan hentes flere indstruktioner tilbage, end antallet af ALU'er muliggør.
Ved skrivning, må ikke foretages samtidigt skrivning til samme register, for to indstruktioner i en VLIW blok. Men, det betyder ikke noget, da vi altid kun ønsker at gemme den sidste. Har vi brug for data fra første indstruktion, kan vi altid tage det fra ALU's udgang direkte.
Det er muligt, at gøre ovenstående automatisk, og vi kan opnå stor hastighed, på en normal CPU. Størst er gevindsten ved asynkrone CPU'er, fordi vi har mulighed for at holde klokfrekvensen lav, uden det betyder noget, for indstruktionshastigheden - denne er alene bestemt af forsinkelsen mellem hver ALU, og indstruktionshastigheden er ikke påvirket af loopen retur. Ved asynkron logik, er ikke muligt at holde lav cyklus tid, som ved synkron logik. Men der opstår samtidigt parallelisering, og den tilsyneladende hastighed indstruktionerne udføres i, er højere end ved synkron logik. Det er derfor mere effektivt. Trods der ikke opstår parallelisering, vil den tilsyneladende hastighed være større, fordi asynkron logik er ligeså hurtig med hesyn til forsinkelsen. Det er kun cycle tiden, som er lavere.
Jeg håber, at ovenstående giver indtryk af at CPU'erne godt kan arbejde på skift, og varmen derved distribueres ud over chippen. Og samtidigt opnås større arbejdshastighed. En kombinatorisk blok, svarer udfra afhængigheder, og specielt ved asynkron logik, går hastigheden op på grund af parallelisme. Synkron logik kan ikke detektere uafhængighederne så godt og kører langsommere.
Ovenstående, håndterer kun afhængig parallelisme. Uafhængig parallelisme håndteres ikke. Dette kan kun gøres, ved at analysere programmet, og styre dette med en flow graf.
I mange tilfælde, er fordele ved at dele op på flere kerner, fordi man undgår fælles adgang til registre og ram.
Fremtidens computere vil afgjort parallelisere, og det vil blive ligegyldigt om de repræsenteres for kode der er skrevet til sekventiel afvikling, eller parallel afvikling. Begge dele vil paralleliseres, og operativsystemet vil kunne udregne hvilke processer der er bedst at udføre samtidigt, og hvilke der måske skal udsættes fordi der derved kan undgås at regne noget ud.
I princippet kan operativsystemet finde andre operativsystemer at gå sammen med, og de kan i fællesskab parallelisere koden. Kode, vil typisk kunne flyttes på grund af forbindelser med omverdenen, således den placeres strategisk i forhold til de data den arbejder med.
For mange år siden var jeg også inde på dette område. Bl.a. opstod der en Array Processor med dedikerede logike kredsløb designet i LCA/PLD til erstatning af det I kender for en ALU, men som vi kender fra RISC, alt udført med een clock, også til div. pipe-lines. Den blev styret af microcode, for afvikling af een bestemt deduktionsfunktion, som var grundlaget for andre overliggende logiske algoritmer.
Med flere kerner på samme chip er tiden igen kommet til multiprocessor.dk programmering :-)
Kik evt. IBM lidt over skulderen og se hvad de gjorde i 1992-1994.
Dengang blev skrevet specielle C-compilere for afvikling af kode i transputer-netværk.
