Faculteit Ingenieurswetenschappen Vakgroep Elektronische en Informatiesystemen Studie van fasegedrag in programma-uitvoeringen Jonathan-Lawrence van Roosmalen Promotor : Prof. Dr. Ir. Koenraad de Bosschere Begeleider : Frederik Vandeputte Proefschrift ingediend tot het behalen van de graad van licentiaat in de Informatica Academiejaar 2005-2006 Studie van fasegedrag in programma-uitvoeringen Jonathan-Lawrence van Roosmalen Proefschrift ingediend tot het behalen van de graad van licentiaat in de Informatica Academiejaar 2005-2006 Promotor : Prof. Dr. Ir. Koenraad de Bosschere Begeleider : Frederik Vandeputte Faculteit Ingenieurswetenschappen Universiteit Gent Vakgroep Elektronica en Informatiesystemen Samenvatting Het indelen van een programma in fasen is relatief recent in de belangstelling gekomen. Fasen zijn delen van een programma waarin het ongeveer hetzelfde gedrag vertoont (hier in termen van processorgebruik). In deze scriptie trachten we fasen op te sporen aan de hand van het gedrag van een superscalaire processor tijdens uitvoeren van het programma. In de inleiding wordt kort een schets gegeven over wat fasen zijn, waarom we ze zoeken, en werpen we een blik op wat de rest van de scriptie te bieden heeft. We bekijken dan hoe een superscalaire processor opgebouwd is, en geven een kort overzicht van de ontwikkeling van zo'n processor om de verschillende componenten te duiden. Hierna bekijken we hoe SimPoint, een programma dat fasen opspoort aan de hand van uitgevoerde code, te werk gaat, en lichten enkele technieken toe die belangrijk zijn om de rest van de scriptie te kunnen volgen. In het vierde hoofdstuk schetsen we hoe we zelf fasen trachten op te sporen, geven enkele mogelijkheden, lichten toe waarom we wel en waarom we niet voor bepaalde stappen kiezen, en geven aan welk soort informatie we gaan benutten. Dan gaan we in op de eigenlijke evaluatie, waar al de informatie die we vergaard hebben z'n nut bewijst, en waar we verbanden trachten na te gaan tussen verschillende processorarchitecturen, SPECbenchmarks. We sluiten af met de conclusie dat SimPoint door de band genomen voldoende is om fasegedrag op te sporen, dat processorarchitecturen weinig effect op fasegedrag hebben, en eventueel verder onderzoek. Trefwoorden: Superscalair, processor, SimPoint, clustering, fase Studie van fasegedrag in programma-uitvoeringen Jonathan-Lawrence van Roosmalen Voorwoord Van dit voorwoord zou ik willen gebruik maken om iedereen te bedanken die geholpen heeft deze scriptie te maken wat het geworden is; in het bijzonder wil ik mijn promotor, Koenraad De Bosschere, en mijn begeleider, Frederik Vandeputte, willen bedanken voor een schijnbaar eindeloos geduld, behulpzaamheid, en goede raad. Ook nog wil ik m'n familie bedanken voor het ondergaan van het lezen en herlezen van de scriptie in een nauwgezette zoektocht naar taalfouten, gedachtensprongen, onduidelijke conclusies, en esoterische figuren of termen. Iedereen is van harte bedankt voor de steun! De auteur geeft de toelating deze scriptie voor consultatie beschikbaar te stellen en delen van de scriptie te kopiëren voor persoonlijk gebruik. Elk ander gebruik valt onder de beperkingen van het auteursrecht, in het bijzonder met betrekking tot de verplichting de bron uitdrukkelijk te vermelden bij het aanhalen van resultaten uit deze scriptie. Getekend op 3 september 2006, Jonathan-Lawrence van Roosmalen Studie van fasegedrag in programma-uitvoeringen Jonathan-Lawrence van Roosmalen Promotor: Prof. Dr. Ir. Koenraad De Bosschere; Begeleider: Frederik Vandeputte Abstract—Dit werk richt zich op het vinden van fasen in programma-uitvoeringen. Fasen zijn tijden van uitvoering waarin een processor hetzelfde gedrag vertoont (bvb. instructies per cyclus). Uitgaande van het processorgedrag tijdens een programma-uitvoering gaan wij na wat het fasegedrag is, hoe dit beïnvloed wordt door verschillende processorarchitecturen en, in het bijzonder, in welke mate SimPoint dit fasegedrag terugvindt. We concluderen dat processorconfiguraties weinig effect hebben op de performantie van SimPoint, en dat deze een voldoende nauwkeurigheid heeft. Keywords—Superscalair, processor, SimPoint, clustering, fase I. INLEIDING Programma's zijn onder te verdelen in fasen: in het meest eenvoudige geval kan men spreken over begin, midden, en einde, maar fase-onderzoek kan ook gebeuren a.d.h.v. het bekijken van de uitgevoerde code (SimPoint) of het gedrag van een processor tijdens het uitvoeren van die code (wat wij zullen doen). We zullen met behulp van clusteringsalgoritmen het processorgedrag in fasen opdelen, en bekijken in welke mate onze indeling met die van SimPoint overeenkomt (om een mate van vergelijking te hebben). Tevens willen we nagaan hoe groot het effect van verschillende processorarchitecturen is op de faseindelingen; in het bijzonder zullen we dieper ingaan op schommelingen die dit zou kunnen teweegbrengen tussen SimPoint en onze eigen “traceclustering”. aaneengesloten stuk code dat precies één ingang en één uitgang heeft, aan respectievelijke einden van het blok. SimPoint telt hoe vaak een basisblok doorlopen wordt, houdt dit bij in vectoren, en gaat fasegedrag opsporen door deze vectoren te clusteren met het k-gemiddelden algoritme. We vermelden hier ook dat SimPoint gebruik maakt van een BIC-score (Bayesiaans Informatiecriterium) [2] om na te gaan welke clusteringen beter zijn dan andere, en de beste dan te kiezen. A.Variantiecoëfficiënt De variantiecoëfficiënt geeft een mate van afwijking weer voor de clusters. Het is de standaardafwijking gedeeld door de verwachtingswaarde (centroïde) van een cluster. We gebruiken de variantiecoëfficiënt om de prestatie van SimPoint en de traceclustering tegenover elkaar te kunnen vergelijken, en als maatstaf voor het belang dat we aan andere berekeningen kunnen hechten. B.Macht en betrouwbaarheid We nemen de definitie van macht en betrouwbaarheid (trouw) van een test (in ons geval, een model) over uit de statistiek [3]. Wij stellen SimPoint als nulhypothese op, en verkrijgen dan: Macht = fasewissel => SimPoint-fasewissel Trouw = SimPoint-fasewissel => fasewissel We zullen macht en trouw over een bepaald interval zien. Dit wil zeggen dat we een interval toestaan waarin een fasewissel mag voorkomen, i.p.v. op het moment van de wissel zelf. IV.ANALYSE VAN PROCESSORGEDRAG: TRACECLUSTERING Traceclustering werkt over processorgedrag i.p.v. codegedrag, dus moeten we eerst processorgedrag bekomen. We krijgen deze informatie via een uitbreiding op SimpleScalar, die ons dan de karakteristieken van een imaginaire, superscalaire processor geeft tijdens uitvoering van een programma. Voor de traceclustering en het vormen/bekijken van de resultaten gebruiken we zelfontworpen programma's, op maat geschreven voor de opdracht. III.ANALYSE VAN CODEGEDRAG: SIMPOINT [1] SimPoint gebruikt basisblokvectoren (BBV) om codesecties in te delen. Een basisblok is een A.Beschouwde configuraties We bekijken hier 27 (3x3x3) verschillende processorarchitecturen, met variërende cachegroottes, buffergroottes, en processorbreedten. Tevens beschouwen we zo'n 25 SPEC-benchmarks met onder II. SUPERSCALAIRE PROCESSOREN Superscalaire processoren vormen een stap vooruit op 'normale' processoren in het feit dat ze toestaan dat verscheidene instructies tegelijk (schijnbaar parallel) uitgevoerd worden. Dit zorgt ervoor dat een superscalaire processor andere karakteristieken vertoont, zoals meerdere instructies per cyclus kunnen uitvoeren. Wij zullen ons vooral tot deze karakteristiek richten. Verder bestaan superscalaire processoren uit een aantal extra componenten, zoals een instruction fetch queue en een register update unit. andere gcc, bzip2, vortex, applu, en gzip, tezamen goed voor meer dan 700 individuele “traces”. Over elk van die traces zullen we dan werken met 1-16 clusters (in 8 stappen), hetgeen ons over 5000 brengt. B.Preclustering Voor we kunnen clusteren, moeten we onze data omzetten naar informatie die we kunnen gebruiken. We zullen hier normalisatie doorvoeren, en stellen dat kerning op dit niveau soms slecht voorspelbare en onwenselijke effecten heeft. C.Clustering Hier implementeren we het Bayesiaans Informatiecriterium volgens [2], en bespreken enkele randgevallen en hun oplossingen. We gebruiken hetzelfde clusteringsalgoritme als SimPoint, met name kgemiddelden, onder andere vanwege de conceptuele eenvoud, en om de vergelijkingen duidelijker te maken. V. EVALUATIE Hier evalueren we de informatie die we vergaard hebben aan de hand van de clusteringen. We gaan met meer detail in op hoe we uiteindelijk de vergelijking met SimPoint zullen doorvoeren, en zoeken naar antwoorden op de vragen die we eerder gesteld hebben. Eerst bekijken we de algemene resultaten; conclusies die we kunnen trekken door aggregaten van de informatie te bestuderen. Hieronder vallen het kleine (relatieve) effect van verschillende processorconfiguraties, en welke elementen het meest bepalend zijn. Tevens zien we dat SimPoint door de band genomen goed presteert. Daarna gaan we na in welke gevallen we duidelijk goede resultaten bekomen, en waar de resultaten minder zijn. We trachten tevens te verklaren waarom dit in sommige instanties tegenvalt. VI.CONCLUSIE Hier vatten we samen wat de belangrijkste conclusies zijn. A.Stabiel codegedrag leidt tot stabiel processorgedrag Deze implicatie houdt tevens ook in dat labiel processorgedrag vaak leidt tot labiel codegedrag. De omgekeerde implicaties zijn echter minder krachtig. B.Processorconfiguraties zijn belangrijk, maar niet bepalend Verschillende configuraties maken individueel verschil uit, maar hebben in verhouding gelijkaardige effecten op zowel SimPoint als de traceclustering. Voor de vergelijking is dit dus niet bepalend. C.SimPoint is voldoende Door de band genomen is SimPoint ruimschoots voldoende om fasewisselingen op te sporen in programma's, en is er dus geen analyse van het processorgedrag nodig. Blindelings vertrouwen is niet aangeraden, maar doorgaans mag men van SimPoints leiding uitgaan. D.Mogelijk verder onderzoek Dit onderzoek legt zich toe op laagste-orde fasegedrag. Soms vertonen programma's patronen op hoger niveau. Dit kan eventueel bestudeerd worden met behulp van patroonherkenning, na een faseindeling te bekomen met behulp van SimPoint of een traceclustering. Eventueel kan kerning op het niveau van de fasen de prestaties van SimPoint nog verhogen. ERKENNINGEN Graag wil ik iedereen bedanken die geholpen heeft de scriptie te maken wat het is; in het bijzonder verdienen promotor Koenraad De Bosschere en begeleider Frederik Vandeputte een vermelding voor hun schijnbaar eindeloos geduld en goede raad. Verder wil ik m'n familie bedanken voor het lezen en herlezen van m'n scriptie op gedachtensprongen, taalfouten, onduidelijke verwoordingen, en layoutproblemen. REFERENTIES [1] [2] [3] B. Calder, T. Sherwood, E. Perelman, G. Hamerly, S. Sair, Discovering and Exploting Program Phases, 2003 D. Pelleg, A. Moore, X-means, extending K-means with efficient estimation of the number of clusters H. De Meyer, Nota's bij het opleidingsonderdeel “Waarschijnlijkheidsrekening en statistiek”, 2003 (Dit zijn enkel referenties voor dit abstract. De scriptie zelf bevat een volledige lijst.) Inhoudstafel 1.Inleiding........................................................................................................................................................... 1 2.Superscalaire processoren................................................................................................................................ 3 2.1.De vroegere processoren..........................................................................................................................3 2.2.De processor evolueert.............................................................................................................................3 2.3.Architectuur van een superscalaire processor..........................................................................................4 3.Analyse van codegedrag: SimPoint................................................................................................................. 5 3.1.Basisblokvectoren (BBV)........................................................................................................................ 5 3.2.Clustering................................................................................................................................................. 5 3.3.Het Bayesiaans Informatiecriterium (BIC).............................................................................................. 6 3.4.Prestatieschatting..................................................................................................................................... 6 3.4.1.Variantiecoëfficiënt......................................................................................................................... 6 3.4.2.Macht en betrouwbaarheid...............................................................................................................7 4.Analyse van processorgedrag: Traceclustering................................................................................................9 4.1.Processorgedrag extraheren..................................................................................................................... 9 4.2.Verschillende architecturen................................................................................................................... 10 4.2.1.Caches............................................................................................................................................ 10 4.2.2.Breedtes......................................................................................................................................... 11 4.2.3.Buffers........................................................................................................................................... 12 4.2.4.De beschouwde architecturen........................................................................................................ 12 4.3.Preclustering.......................................................................................................................................... 12 4.3.1.Preprocessing................................................................................................................................. 13 4.3.2.Kerning.......................................................................................................................................... 15 4.4.Clustering............................................................................................................................................... 18 4.4.1.Bayesiaans Informatiecriterium.....................................................................................................18 4.4.2.Minimal Spanning Tree................................................................................................................. 19 4.4.3.Doelclusters ≠ Clusters ?............................................................................................................... 20 5.Evaluatie.........................................................................................................................................................21 5.1.Maatstaven voor vergelijking................................................................................................................ 21 5.1.1.Variantiecoëfficiënt....................................................................................................................... 21 5.1.2.Macht en betrouwbaarheid.............................................................................................................22 5.1.3.Welk aantal clusters?..................................................................................................................... 22 5.2.Algemene resultaten...............................................................................................................................22 5.2.1.Gemiddelde variantiecoëfficiëntverhouding is stabiel.................................................................. 23 5.2.2.Goede macht en betrouwbaarheid..................................................................................................23 5.2.3.Evenredige prestatie over verschillende configuraties heen..........................................................25 5.2.4.Effecten van de configuraties........................................................................................................ 25 5.3.Gevallen met hoge nauwkeurigheid.......................................................................................................27 5.3.1.Regelmatig processorgedrag..........................................................................................................27 5.4.Gevallen met lagere nauwkeurigheid.....................................................................................................29 5.4.1.Moeilijk voorspelbaar gedrag........................................................................................................ 29 6.Conclusie........................................................................................................................................................32 6.1.Stabiel codegedrag geeft stabiel processorgedrag................................................................................. 32 6.2.Processorconfiguraties zijn belangrijk, maar niet bepalend.................................................................. 32 6.3.Simpoint is voldoende............................................................................................................................32 6.4.Mogelijk verder onderzoek.................................................................................................................... 33 7.Referenties......................................................................................................................................................34 1. Inleiding Programma's vertonen vaak patronen in hun gedrag tijdens uitvoering. We weten dat programma's een begin, midden en einde hebben, maar vaak schuilt er in die drie onderverdelingen ook nog herhaling, zoals het doorlopen van een lus, of herhaaldelijk aanroepen van een functie; denk maar aan een compiler, die door duidelijke stappen gaat om van broncode tot object-code of mogelijks uitvoerbare code te komen. We noemen zo'n stappen fasen (figuren 1 & 2). Fasen kunnen vinden in een programma leent zich tot een groot aantal toepassingen in evenveel gebieden, om enkele te noemen: • een compiler kan schatten wanneer welke code uitgevoerd zal worden, en optimaliseren; • een scheduler kan voorspellen wanneer processen de processor veel nodig hebben, en wanneer ze door een lichtere fase gaan; • stroomverbruik kan aan de hand van fasegedrag voorspeld worden. Er kan op verschillende manieren gekeken worden naar fasegedrag: code-gebaseerd en prestatie-gebaseerd. Code-gebaseerd werken heeft het voordeel dat het werk vooraf gedaan kan worden, maar het is mogelijk dat prestatiegedrag afwijkt van codegedrag (meer daarover later). Intuïtief, echter, kunnen we stellen dat codegedrag toch minstens een sterke factor in prestatiegedrag moet zijn, wat eerder ook aangetoond werd [strong-correlation]. Deze scriptie richt zich op het prestatie-gebaseerd perspectief: wij gaan proberen fasen op te sporen aan de hand van het gedrag dat de processor vertoont tijdens uitvoering. Het bekomen van die fasen is een eerder technisch deel waar we niet diep op in zullen gaan, en we zullen eerder beschrijven welke informatie we bekomen en gebruiken. Eens we de fasen hebben, gaan we na in welke mate ze overeenkomen met de fasen die SimPoint gevonden heeft. Voor het perspectief waar we vanuit de code beginnen, is er het programma SimPoint, ontwikkeld aan het UC San Diego. SimPoint probeert representatieve delen te vinden in de code, en begint daaruit naar fasen in codegedrag te zoeken. Het derde hoofdstuk gaat iets dieper in op hoe SimPoint fasegedrag tracht op te sporen, en welke technieken daarvoor ontwikkeld werden, alhoewel we het hier maar kort zullen aanraken; een volledige beschrijving valt buiten ons kader en kan gevonden worden bij de auteurs van het programma [SimPoint]. Een ander onderdeel bestaat uit het vergelijken van de resultaten voor verschillende processorarchitecturen. Verschillende architecturen vertonen verschillend gedrag tijdens uitvoering, maar mogelijks is er nog altijd terugkerend fasegedrag. We gaan dan na wat de afwijking is tussen de verschillende architecturen, maar in het bijzonder wat de impact op fase-indelingen is. p.1 Uiteindelijk is de bedoeling van deze scriptie tweeërlei: enerzijds gaan we kort methoden na waarmee we fase-indelingen kunnen vergelijken, en anderzijds zullen we met deze methoden nagaan in welke mate en gevallen we SimPoint kunnen gebruiken om fasegedrag op te sporen. Figuur 1: Een andere SPEC-benchmark, gebruik makend van gcc. Alhoewel er zich hier ook patronen voordoen, zijn ze niet globaal, maar lokaal. p.2 Figuur 2 - Processorgedrag tijdens het uitvoeren van een SPEC-benchmark, applu. Merk het duidelijk wederkerend gedrag op dat zich voordoet. 2. Superscalaire processoren 2.1. De vroegere processoren De eerste processoren toonden heel duidelijk de von Neumann-cyclus: “fetch, decode, execute”. Een instructie werd uit het geheugen gehaald, gedecodeerd, en dan uitgevoerd. Een tweede instructie werd opgehaald wanneer de eerste uitgevoerd was. Een eerste optimalisatie was het pipelining-model. Deze zorgde er in essentie voor dat instructies dichter op elkaar volgden tijdens uitvoering; terwijl één instructie gedecodeerd werd, was de processor de volgende al aan het ophalen. In het optimale geval konden er zoveel instructies in een wachtlijn staan als de processor “lang” was, i.e. zoveel stappen er tijdens uitvoering waren. Dit systeem werkt degelijk zolang het programma rechtlijning in uitvoering is, i.e. grote basisblokken heeft (een basisblok is een sequentie van instructies met de eigenschap dat, als de eerste instructie uitgevoerd wordt, de laatste ook uitgevoerd zal worden). Wanneer een programma voor een keuze staat, (bvb. door een if-then clausule), moet de processor wachten op het resultaat voor het de volgende instructies kan ophalen. Men zegt ook dat de pijplijn leegloopt. Om dit tegen te gaan, werd sprongvoorspelling (branch prediction) ingevoerd. Sprongvoorspelling tracht de programmateller te voorspellen aan de hand van een geschiedenis van waar een programma al eerder naar andere codefragmenten gesprongen is. Enkel wanneer een foute voorspelling voorkomt, loopt de pijplijn toch nog leeg. 2.2. De processor evolueert Pipelining voert een zekere vorm van parallellisme door, alhoewel alle instructies nog altijd sequentieel uitgevoerd worden. Ontwerpers vonden dat veel delen van een processor inactief waren tijdens uitvoering van een instructie, en ontwikkelden een manier om verschillende soorten instructies “tegelijk” uit te voeren. Een processor die dit ondersteunt wordt een superscalaire processor genoemd. Superscalaire processoren lezen een aantal instructies in en proberen die te ordenen zodat verscheidene instructies tegelijk kunnen uitvoeren op de processor, bvb. vermenigvuldiging van gehele en vlottende kommagetallen. Later worden de instructies dan op de “juiste” manier terug samengebracht. “Juist” verwijst hier naar de volgorde waarin de instructies in de code voorkomen. Mocht hier niet aan voldaan zijn, zou een programma slecht voorspelbaar gedrag vertonen. Er zijn vele andere obstakels waar een superscalaire processor mee te kampen heeft, i.h.b. nog altijd sprongvoorspelling (hier mogelijk nog meer dan bij pipelining), het zo klein mogelijk houden van de instructie “latency” (tijd tussen ophalen en uitvoeren van een instructie), en lees/schrijfconflicten van opeenvolgende instructies. p.3 Het aantal instructies die een superscalaire processor parallel kan uitvoeren wordt ook wel eens de bandbreedte (of kortweg breedte) van de processor genoemd. 2.3. Architectuur van een superscalaire processor Allereerst heeft een superscalaire processor een sprongvoorspeller. Sprongvoorspellers zijn uitermate belangrijk om grotere blokken code te kunnen ophalen voor parallelle verwerking. Indien een sprongvoorspelling foutief blijkt, moet andere code opnieuw opgehaald en uitgevoerd worden. Afhankelijk van de sprongvoorspeller is de instruction fetch queue (IFQ). Om instructies te kunnen herordenen moet de superscalaire processor zowel bij het ophalen (fetch) als uitvoeren (execute) van een blok code de individuele instructies kunnen bufferen. Doorgaans is de IFQ minstens zo groot als de bandbreedte van de processor (zodat de processor altijd een volledig blok kan ophalen). Omdat het verloop op instructies in een superscalaire processor doorgaans veel hoger is dan normaal, is er ook vaak nood aan aparte caches: een instructiecache en een datacache (alhoewel er architecturen zijn die er toch in slagen ze samen te houden in één type cache). Caches houden eerder gebruikte instructies/data bij zodat de processor ze snel kan vinden. Wanneer een processor de nodige informatie in de cache terugvindt, spreekt men van een cache hit, en anders van een cache miss. Tegenwoordig hebben processoren vaak meerdere caches, hiërarchisch in niveaus gedeeld. (We gaan later dieper in op caches.) Indien een processor toch nieuwe informatie nodig heeft, moet het de load-store queue (LSQ) raadplegen. De LSQ bevat geheugeninstructies die wel opgehaald maar nog niet doorgevoerd zijn. De processor werkt hierlangs omdat het niet meer de volgorde van uitvoering volgt die de code oplegt, en dus is het mogelijk dat bepaalde gebieden in het geheugen aangepast zouden moeten zijn voor een andere instructie uitvoert. Tenslotte is er nog de register update unit (RUU). Wat de LSQ doet voor het geheugen, doet de RUU voor de registers op de processor. Het zorgt ervoor dat de uitvoerende instructies de correcte waarden krijgen voor de registers die ze opvragen. p.4 3. Analyse van codegedrag: SimPoint In de inleiding werd kort vermeld dat SimPoint gebruikt werd om fasen te vinden aan de hand van de code van een programma. Hier gaan we kort vermelden wat we nodig hebben om verder te kunnen; voor meer informatie verwijzen we naar [SimPoint] en [phases]. We beginnen met uit te leggen welke informatie SimPoint uit de code van een programma haalt. Daarna beschrijven we kort hoe deze in fasen onderverdeeld worden, en uiteindelijk beschrijven we welke maatstaven we gaan hanteren om SimPoint met onze traceclustering1 te vergelijken. 3.1. Basisblokvectoren (BBV) Aan de basis van SimPoints methodologie liggen basisblokken. Een basisblok is een aaneengesloten blok code met één toegangspunt en één uitgangspunt. Een basisblokvector (BBV) is een vector met voor elk basisblok een component. SimPoint overloopt de programmacode en deelt het op in die basisblokken. Dan, wanneer het programma-uitvoering simuleert, telt het hoeveel maal het een basisblok doorloopt, en slaat dit op in een BBV. BBVs worden ingedeeld per intervalsgrootte. Voorbeelden zijn grootten van 1 tot 100 miljoen instructies. Wij zullen groottes van 220 instructies gebruiken, hetgeen ongeveer 1 miljoen is. 3.2. Clustering Nadat de BBVs gevuld zijn, worden ze geclusterd. Clustering is een principe dat een typisch grote hoeveelheid data probeert onder te verdelen in verscheidene representatieve groepen, clusters genaamd. In het bijzonder gebruikt SimPoint het K-gemiddelden algoritme: procedure kmeans kies K datapunten uit als beginnende centroïden loop until geen verandering or maximum aantal iteraties bereikt foreach datapunt do vind dichtstbijzijnde cluster door _ afstand tot centroïde te berekenen wijs toe aan dichtstbijzijnde cluster end do foreach centroïde do berekenen nieuwe centroïde2 end do end loop end procedure 1 De clustering over het processorgedrag. We zullen hier vaker naar verwijzen als de “traceclustering”. 2 Centroïden zijn niet noodzakelijk datapunten in een cluster. Ze worden berekend als het zwaartepunt van alle datapunten in een cluster, wat geen garantie levert dat de centroïde een eigenlijk datapunt voorstelt. p.5 Men zegt hier dat een fase voorkomt wanneer een aaneengesloten blok van BBVs aan dezelfde cluster toegewezen is. Hoe groter dit blok, hoe langer de fase zich doorzet. Merk op dat K-gemiddelden minstens één parameter vergt: K, het aantal gewenste clusters. Dit is een uiterst beslissende factor in het clusteralgoritme, gezien een te klein aantal clusters waarschijnlijk grotere fasen zal herkennen dan een groot aantal clusters. Daarentegen zal een te groot aantal clusters onze data in meer groepen onderverdelen dan nodig. Liefst hebben we zo min mogelijk clusters, maar manueel nagaan welke clusteringen voldoende goed zijn is een tijdrovend (en inherent onnauwkeurig) werk. In het volgend stuk beschrijven we een methode die dit automatiseert. 3.3. Het Bayesiaans Informatiecriterium (BIC) In statistiek wordt het Bayesiaans Informatiecriterium (BIC) gebruikt om na te gaan hoe goed een model past bij de distributie die het probeert te modelleren. Mits een paar aanpassingen, leent BIC zich ook tot het nagaan van de kwaliteit van een clustering. Een BIC heeft typisch de volgende eigenschappen die nuttig zijn voor ons: • het berekent de variantie tussen model en data, dus een mate van afwijking; • het promoot eenvoud van modellen: een hoog aantal parameters resulteert in lagere BIC. Door het gebruiken van BIC gaat SimPoint na welke clusteringen beter zijn dan andere. Doorgaans worden enkele clusteringen gedaan met verschillende startpunten en verschillende waarden voor K (aantal clusters), en wordt dan degene met de hoogste BIC-score als beste gekozen. BIC ligt tevens aan de basis van een voorgestelde verbetering op K-gemiddelden, genaamd Xgemiddelden, die zelf het optimaal aantal clusters zou schatten. Voor meer informatie verwijzen we naar [pelleg-xmeans]. 3.4. Prestatieschatting Voor het schatten van de prestatie van de fase-indeling, bekijken we zowel de variantiecoëfficiënt (CoV) van de instructies per cyclus (IPC) per cluster, als de macht en betrouwbaarheid (trouw) van een model. 3.4.1. Variantiecoëfficiënt Voor het schatten van de prestatie van de fase-indeling, bekijken we de variantiecoëfficiënt (CoV) van de instructies per cyclus (IPC) per cluster. We berekenen de CoV als de verhouding van standaard afwijking tot verwachtingswaarde3. Als verwachtingswaarde nemen we de centroïde van een cluster: 3 Merk op dat het wel degelijk om de standaard afwijking gaat en niet de variantie. Waarom de term in de literatuur dan een variantiecoëfficiënt genoemd wordt, mag een raadsel wezen. [answers-1] p.6 CoV = function CoV(cluster: Cluster) cov : double := 0; foreach datapunt in cluster do cov := cov + afstand(datapunt, centrum); end do cov := cov / clusterSize; cov := sqrt(cov); cov := cov / norm(centrum); return cov; end function In dit geval zullen de datapunten enkel bestaan uit de IPC, waardoor de norm de absolute waarde wordt. Hierna wordt een gewogen gemiddelde genomen over de CoVs van de verschillende clusters, met als gewicht het aantal datapunten per cluster (de grootte van de clusters). Indien we de statistische notatie wat geweld aandoen, bekomen we: Stel: X is de verzameling datapunten; C(X) is de verzameling clusters over de datapunten; σC is de standaardafwijking over cluster C; μC is de verwachtingswaarde (centroïde) van C; Dan: CoV = ∑ C⊆C X ∣C∣∗ C C ∣X ∣ ∣C∣∗ C ⇔CoV = ∑ C ⊆C X ∣ X ∣∗ C Dit kunnen we als één van de maatstaven gebruiken om onze resultaten te vergelijken. De variantiecoëfficiënt vertelt ons hoe groot de relatieve afwijking in een cluster is. Indien de centroïde van een cluster dicht bij de nulvector ligt, zal de afwijking zwaarder doorwegen dan wanneer de centroïde verder van de nulvector verwijderd is. 3.4.2. Macht en betrouwbaarheid De macht van een test is de kans dat een valse hypothese door de test verworpen wordt, of ook de kans dat er geen fout van het type II begaan wordt. [stat-1] In ons geval wordt een fout van het p.7 type II begaan wanneer er geen fasewisseling is, maar er toch één geregistreerd wordt. De macht wordt dan de kans dat, wanneer een fasewisseling gevonden wordt, er ook wel degelijk één is: macht = fasewissel ⇒ SimPointfasewissel De betrouwbaarheid van een test is de kans dat een ware hypothese aanvaard wordt wanneer deze ook waar is; anders uitgedrukt, de kans dat er geen fout van het type I begaan wordt. [stat-1] In ons geval zal een fout van het type I voorkomen wanneer er een fasewisseling is, maar deze niet geregistreerd wordt. De betrouwbaarheid wordt dan de kans dat, wanneer er een fasewissel is, deze gevonden wordt. betrouwbaarheid = SimPointfasewissel ⇒ fasewissel In werkelijkheid staan we een zekere marge toe: de fasewissel hoeft niet onmiddellijk te zijn, maar mag binnen een zeker interval rond het wisselpunt voorkomen. Deze intervallen kunnen wisselen in straal, maar we zullen doorgaans aanvaarden dat er een marge van 2 datapunten is (wat in ons geval enkele miljoenen instructies voorstelt). Merk op dat we, wanneer macht en betrouwbaarheid beide 1 zijn, de fasewisselingen correct gemodelleerd achten. We spreken tevens enkel over een fasewisseling, niet over de fasen zelf. p.8 4. Analyse van processorgedrag: Traceclustering We hebben besproken hoe SimPoint tewerk gaat om fasegedrag trachten op te sporen aan de hand van de code van het programma. Eerst verzamelt het nodige data (in de vorm van BBVs), en groepeert ze met behulp van clusteringalgoritmen. In dit hoofdstuk bekijken we het probleem vanuit de andere kant van het spectrum: we beginnen met het processorgedrag tijdens uitvoering, en trachten zo een programma in fasen onder te verdelen. Merk op dat, waar SimPoint niet over processorgedrag beschikt, wij niet over de code beschikken tijdens het clusteren. Allereerst gaan we na hoe we processorgedrag kunnen meten tijdens uitvoering, dus waar we onze data vandaan halen. Daarna beschrijven we kort de verschillende architecturen waarover we getest hebben. Uiteindelijk leggen we uit hoe we, vertrekkend van deze data, aan een clustering komen. 4.1. Processorgedrag extraheren Om het processorgedrag te verkrijgen, maken we ook gebruik van SimPoint om goede simulatiepunten4 terug te vinden [simpoint]. Vertrekkend van deze simulatiepunten, kunnen we gebruik maken van een aangepaste versie van SimpleScalar om een “trace” te maken van een imaginaire processor tijdens uitvoering van een SPEC-benchmark. Een “trace” zal hier een geschiedenis geven van verschillende karakteristieken van de processor terwijl het code uitvoert. Voorbeelden van deze karakteristieken zijn: instructies uitgevoerd per cyclus, het aantal toegangen tot een bepaald type cache, enzovoort. Wij gaan het processorgedrag bekijken van 28 benchmarks, over 27 verschillende architecturen, goed voor 756 traces. We zullen uiteindelijk slechts enkele representatieve voorbeelden tonen in de uiteindelijke evaluatie, en aggregaten (gemiddelden, veelal) over alle data. De 28 SPEC-benchmarks die beschouwd worden zijn: ammp, applu, apsi, art, bzip2, crafty, eon (3 traces), equake, facerec, galgel, gap, gcc, gzip, lucas, mcf, mesa, mgrid, parser, perlbmk, sixtrack, swim, twolf, vortex, vpr (2 traces), wupwise. Deze programma's vervullen sterk uiteenlopende rollen: bzip2 is een compressieprogramma, gcc is een compiler. 4 Het volstaat te weten dat simulatiepunten representatieve delen van het programma voorstellen, zodat van daaruit vertrokken kan worden om informatie te vergaren. We gebruiken dezelfde punten zowel om zelf duidelijke informatie te hebben, als om de vergelijking te kunnen maken. p.9 4.2. Verschillende architecturen Voor de volledigheid bekijken we verschillende processorarchitecturen waarop de code loopt. De architectuur van een processor kan verregaande implicaties hebben op de prestatie van uitgevoerde code. Programma's die gretig gebruik maken van een cache zullen minder hinder ondervinden van grote caches, en programma's die zeer rechtlijnig zijn (weinig sprongen) zullen ten volste gebruik kunnen maken van een processor die veel instructies per cyclus aankan. De architecturen die wij zullen bekijken verschillen in de grootte van de caches, van de buffers, en de breedte van de processor. Over elk van deze karakteristieken hebben we drie onderverdelingen, waardoor we in totaal 27 (33) architecturen bekijken. Om het woordental te verminderen, zullen we een verkorte notatie (3 letters) voor een architectuur gebruiken. De notatie is van de vorm CPB, waar C staat voor de cachegrootte, P voor de processorbreedte, en B voor de buffergrootte. Een architectuur met kleine caches, grote processorbreedte, en normale buffers, zullen we een SLN-architectuur noemen. Allereerst zullen we uitleggen wat de verschillende karakteristieken allemaal inhouden, en later geven we een tabel waarin beschreven staat hoe de groottes van elkaar verschillen. 4.2.1. Caches Caches worden ruwweg gedefinieerd door 3 karakteristieken: hun associativiteit, het aantal sets, en hun granulariteit/blokgrootte. Offset Data (32 bytes) Data (32 bytes) 4eef85a0 5ee21180 2485a260 2485a2a0 Figuur 3: Een 2-wegs associatieve cache met 4 sets en een blokgrootte van 32 bytes. De blokgrootte van een cache verwijst naar wat de cache als een eenheid informatie ziet. Een cache met een blokgrootte van 32 bytes haalt informatie binnen in blokken van 32 bytes. In het voorbeeld hierboven is de blokgrootte 32 bytes. De associativiteit van een cache is de hoeveelheid blokken per set. Bij een associativiteit van x en een blokgrootte van y, zijn er x * y databytes per set. In het voorbeeld hierboven is de associativiteit 2. Hiermee, en met de blokgrootte, wordt de lokaliteit van data uitgebuit. We noemen een cache met associativiteit 2 ook 2-wegs associatief. Het aantal sets van een cache verwijst naar hoeveel “lijntjes” er in een cache voorkomen. Het aantal blokken per set is gelijk aan de associativiteit van de set. In het voorbeeld zijn er 4 sets. Men kan zich een cache voorstellen als een tabel: de blokgrootte is het aantal bytes per cel, de associativiteit het aantal kolommen, en met elke rij komt een set overeen. p.10 Wanneer een instructie geheugen addresseert, wordt eerst nagegaan of de informatie zich in de cache bevindt. Zoja, wordt het hieruit teruggegeven; indien nee, dan wordt de aanvraag doorgestuurd naar eventuele andere niveaus, en treedt er een cachemisser op. Wanneer informatie in de andere richting (naar de processor) door de cache passeert, wordt die tevens in de cache opgeslagen; deze informatie kan eventueel nog uit een andere (verdere) cache komen. Pas wanneer geen van de caches de vraag kan beantwoorden, wordt het geheugen aangesproken. Deze is gewoonlijk aanzienlijk trager dan een cache, en kan voor vertraging zorgen. Merk op dat we hier over data spreken; hetzelfde geldt voor instructiecaches. Wij zullen drie types caches bespreken: IL1, DL1, en DL2. IL1 staat voor instructiecache niveau 1, DL1 voor datacache niveau 1, en DL2 voor datacache niveau 2. 4.2.2. Breedtes Met de breedte van een processor bedoelen we een aantal verschillende karakteristieken gegroepeerd onder een gezamelijke noemer. Eerder hebben we uitgelegd hoe een superscalaire processor in essentie opgebouwd is. Hieronder staan in het kort de verschillende karakteristieken uitgelegd: Fetchspeed staat hier voor de relatieve kloksnelheid van het “begin” van de pijplijn, ten opzichte van de processor. Een fetch-waarde van 1 staat voor zelfde snelheid, terwijl 2 staat voor dubbele snelheid. IFQ-size (instruction fetch queue) staat voor de grootte van de IFQ in blokken. Een blok is hier de hoeveelheid data die binnengehaald wordt in een enkele fetch. Decode-width staat voor het aantal instructies die per cyclus gedecodeerd kunnen worden. Denk terug aan hoe een superscalaire processor instructies in parallel tracht uit te voeren om alle onderdelen te benutten. Deze instructies moeten eerst gedecodeerd worden. Issue-width staat voor het aantal instructies die per cyclus toegewezen kunnen worden. Alhoewel instructies in parallel uitgevoerd worden, moeten ze wel nog aan een eenheid toegewezen worden. De commit-width is het aantal resultaten die per cyclus kunnen doorgevoerd worden. IALU staat hier voor het aantal gewone rekeneenheden. Analoog FPALU voor vlottende kommagetallen. IMULT staat voor het aantal vermenigvuldigings-/deelingseenheden. Analoog FPMULT voor vlottende kommagetallen. Ports is het aantal geheugenpoorten beschikbaar voor de processor. p.11 4.2.3. Buffers De waarden RUU en LSQ staan voor het aantal geheugeneenheden in respectievelijk de register update unit en de load-store queue. 4.2.4. De beschouwde architecturen Buffe r Bree d t e Cac h e De volgende tabel zal tonen welke processorarchitecturen we beschouwen, en hoe die onderling verschillen. Grootte > Klein – Small Normaal – Normal Groot – Large IL1 2-wegs, 128 sets, blok 32 4-wegs, 128 sets, blok 32 4-wegs, 256 sets, blok 32 DL1 2-wegs, 128 sets, blok 32 4-wegs, 128 sets, blok 32 4-wegs, 256 sets, blok 32 DL2 4-wegs, 2048 sets, blok 64 4-wegs, 4096 sets, blok 64 4-wegs, 8192 sets, blok 64 Grootte > Klein – Small Normaal – Normal Groot – Large Fetch 1 1 2 IFQ 4 8 32 Decode 2 4 8 Issue 3 6 12 Commit 2 4 8 IALU 2 4 8 IMULT 1 1 2 PORTS 1 2 4 FPALU 1 2 4 FPMULT 1 1 2 Grootte > Klein – Small Normaal – Normal Groot – Large RUU 48 96 192 LSQ 24 48 96 Tabel 1: De verschillende groottes voor karakteristieken die we aan een imaginaire processor gaan toewijzen. Let op: de afkortingen worden uit het Engels overgenomen. 4.3. Preclustering We hebben nu getoond voor welke configuraties we over datapunten beschikken. Voor we de datapunten gaan gebruiken, echter, gaan we selecteren welke data we nodig hebben, en hoe we deze data gaan voorstellen. We hebben niet alle karakteristieken nodig, en een andere voorstellingswijze zou clustering potentieel veel eenvoudiger kunnen maken. Allereerst zoeken we best een manier om onze gegevens voor te stellen. De meest voordehandliggende manier zou zijn om de data 1-op-1 over te nemen, maar dat geeft ons niet altijd de informatie die we zoeken. Bijvoorbeeld, we zijn minder geïnteresseerd in hoeveel cachemissers er waren, dan wel meer in wat de missrate was. p.12 Verder kijken we of de data die we bekomen “handelbaar” is; hiermee bedoelen we, of de data zelf niet beter op de één of de andere manier aangepast kan worden. Dit is niet zo onorthodox als het klinkt, gezien het kan helpen om verbanden te vinden die anders door 'data saturation'5 verloren zouden gaan. 4.3.1. Preprocessing Met behulp van SimpleScalar bekomen we datapunten met 23 componenten. componenten maken we nieuwe datapunten (vectoren) met 17 componenten: Uit die 23 • IPC: gemiddelde instructies per cyclus; • bpred: sprongmisvoorspellingen, als verhouding tot totaal aantal voorspellingen; • bpredT: totaal aantal sprongvoorspellingen; • il1: instructiecache niveau 1 missers, als verhouding tot totaal aantal toegangen; • il1T: totaal aantal instructiecache niveau 1 toegangen; • dl1: datacache niveau 1 missers, als verhouding tot totaal aantal toegangen; • dl1T: totaal aantal datacache niveau 1 toegangen; • dl2: datacache niveau 2 missers, als verhouding tot totaal aantal toegangen; • dl2T: totaal aantal datacache niveau 2 toegangen; • IFQ: bezetting van de instructie-fetch-queue; • RUU: bezetting register update unit; • LSQ: bezetting van de load-store-queue; • iALU: bezetting van de integer-ALU componenten; • iMUL: bezetting van de integer-MUL componenten (ook delers); • fADD: bezetting van de float-optellingscomponenten; • fMUL: bezetting van de float-vermenigvuldigings- en delingscomponenten; • RW: bezetting van lees/schrijfpoorten voor data. 5 Mogelijks zijn er duidelijke aanwijzingen in de data, maar door kleine schommelingen en/of extrema is het mogelijk dat deze minder naar voren komen dan bij een glooiender resultaat het geval zou zijn. p.13 Figuur 4: Processorgedrag van een SPEC-benchmark met galgel. Merk op hoe bvb LSQ en bpred omgekeerd afhankelijk van elkaar zijn. p.14 Wanneer we deze vectoren hebben, kunnen we niet eenvoudigweg beginnen ze in een clusteringsalgoritme te steken en hopen iets nuttig uit te komen; onze componenten zijn namelijk niet op schaal. Bpred werkt bvb in percentages, terwijl IPC dit niet doet. Om dit te verhelpen, normaliseren we componentsgewijs naar [0, 1]. Dit heeft als voordeel dat elke component nu in hetzelfde domein blijft, hetgeen een afstandsfunctie zinvoller maakt. Als nadeel, daarentegen, is nu elke component even belangrijk als een andere. We kunnen dit verhelpen door ofwel een weging door te voeren in de afstandsfunctie, ofwel door bepaalde componenten uit te schakelen door projectie. Merk bijvoorbeeld op dat IFQ en bpred sterk met elkaar verbonden zijn, waardoor we één van beide kunnen laten vallen zonder beduidende informatie te verliezen. We zullen hier echter geen componenten wegprojecteren (uitschakelen). Deel van ons doel is nagaan wat de invloed van processorconfiguraties op het fasegedrag van een programma is, en een andere configuratie zou mogelijks andere afhankelijkheden kunnen aanleggen. Dit betekent dat we over alle karakteristieken zullen clusteren. 4.3.2. Kerning Kerning bestaat uit het aanpassen van datapunten aan de hand van omliggende datapunten. Deze techniek wordt vaak toegepast in beeldverwerking, in het bijzonder om contrasten te vergroten of verkleinen. In ons geval kunnen we kerning toepassen om de datapunten uit te middelen. Indien een karakteristiek zeer zwak, maar ook zeer lang en/of regelmatig, schommelt, kan dit eventueel last berokkenen bij het berekenen van clusters. Wij passen kerning toe aan de hand van de discrete kleinste kwadratenmethode, met lineaire lokale vereffening [numa]. Voor normale punten komt dit neer op een gemiddelde, terwijl het voor randpunten een andere vorm aanneemt; omdat er niet genoeg punten aan een van beide kanten ligt, kunnen we niet zomaar een gemiddelde nemen. Voor lineaire vereffening vertrekken we van het volgende stelsel vergelijkingen: i=r ∑ i=−r i=r ∑ i=−r i =r y ki−3a 0−a 1 ∑ x ki=0 i=r i =−r i=r x k i y k i−a 0 ∑ x ki −a 1 ∑ x ki=0 2 i=−r i=−r Oplossing voor drie punten: 5y 02y 1− y 2 6 y k−1 y k y k1 yk' = 3 5y 2y n−1− y n −2 yn ' = n 6 y 0 '= p.15 Voor vijf punten: 6y0 4y 12y2 −2y 4 10 4y 03y 12y 2 y 3 y1 ' = 10 y k−2 y k−1 y k y k 1 y k2 y k '= 5 4y n 3y n−12y n −2 y n−3 y n−1 '= 10 6y n4y n−12y n−2−2y n−4 y n '= 10 y 0 '= Bekijken we de volgende drie grafische weergaven van dezelfde benchmark onder dezelfde processorconfiguratie. Merk op hoe kerning licht schommelend gedrag uitmiddelt, maar tevens de pieken afvlakt. Figuur 5: 8 clusters, met drie-punts kerning. Merk op hoe de eerste fasewisseling een stuk vlotter verloopt. Uit experimenten blijkt, echter, dat het toepassen van kerning ook een averrechts effect heeft die sterk afhangt van de waarde van de datapunten. Sterke pieken, die anders een korte onderbreking zouden betekenen, worden weliswaar afgezwakt, maar trekken tevens omliggende punten met zich mee. Hierdoor krijgen we een langere glooiing waar eerder een enkele piek was. Aangezien dit een moeilijk voorspelbare factor is, hebben we uiteindelijk besloten geen kerning toe te passen op de datapunten. p.16 Figuur 6: 8 clusters, zonder kerning. Bij de eerste piek in RW doen zich enkele fasewisselingen voor. Figuur 7: 8 clusters, met vijf-punts kerning. p.17 4.4. Clustering We hebben al onze data vergaard en verwerkt. Nu kunnen we beginnen met het effectief clusteren van de datapunten. We gebruiken hier zelfgeschreven software: een programma/module in ANSI C om de clustering uit te voeren, en een verzameling Java-klassen om de datapunten te tekenen, clusters voor te stellen, en allehande andere informatie te verzamelen. Voor het clusteren gebruiken we hetzelfde basisalgoritme als SimPoint, met name Kgemiddelden, om de vergelijking beter te laten opgaan. Een aantal vragen rijzen ook hier, in het bijzonder: wat is een ideaal aantal clusters? Ook hier gaan we BIC gebruiken, en hier specifiëren we tevens hoe. We gaan dan kort andere punten aanhalen die tijdens het clusteren opkomen, zoals potentiële verbeteringen en randgevallen, en hoe we ermee omgaan. 4.4.1. Bayesiaans Informatiecriterium Zoals aangeraakt in het parallelle stuk over SimPoint, zullen we hier het Bayesiaans Informatiecriterium toepassen, en wel in de volgende vorm (uit [pelleg-xmeans]), met zelfde definities als voorheen: 2= ∑ C2 C ∈C X 2 C = ∑ x−C x∈C =∑ ∣ X ∣−∣C X ∣ x∈C x −C ∣ X ∣−∣C X ∣ ln 2 VectorGrootte∗ln 1−∣C X ∣ BIC= ∑ ∣C∣∗ ln ∣C∣− − −ln ∣ X ∣− 2 2 2∣C∣ C ∈C X 2 Merk op dat, de statistische conventies volgende, we de variantie als het kwadraat van de standaard afwijking afbeelden. Bovengenoemde gelijkheid vertaalt zich in volgend algoritme: p.18 function BIC bic : double := 0; sigma : double := 0; for i := 0 to sample_count do sigma := sigma + d(x[i], m[cluster[i]]) ^ 2; end for sigma := sigma / (sample_count – cluster_count); for i := 0 to cluster_count do bic := bic - size[i] * ln(2 * pi) / 2 - size[i] * componenten_per_vector * ln(sigma) / 2 - (size[i] – cluster_count) / 2 + size[i] * ln(size[i]) - size[i] * ln(sample_count); end for return bic; end function Merk op dat de BIC onbepaald is wanneer één van de clusters nul elementen zou bevatten 6. Dit gebeurt zeer zelden, maar kan met een eenvoudige controle opgelost worden door de betreffende cluster te verwijderen, en het aantal met 1 te verminderen. Bij ons wordt dit door het clusteringsalgoritme zelf afgehandeld. 4.4.2. Minimal Spanning Tree Nadat K-gemiddelden voor een bepaald aantal clusters gelopen heeft, proberen we het aantal te verminderen a.d.h.v. het MST-algoritme. MST staat voor minimal spanning tree en tracht telkens de twee dichtstgelegen clusters samen te voegen. Wij stoppen MST zodra de BIC niet meer verbetert; gegeven de aard van de data, daarentegen, wordt de BIC niet vaak verbeterd, en ziet MST weinig gebruik. function MST bic : double := 0; best_bic : double := -1; while bic >= best_bic do best_bic := bic; vind dichtste clusters c1, c2 combineer clusters c1, c2 bereken nieuwe centroïde bic := BIC; end while end function 6 Het logaritme is onbepaald voor 0. Men kan dit oplossen op basis van de overtuiging dat lege clusters geen bijdrage hebben tot de BIC, maar het is beter om het clusteringsalgoritme daar zelf mee te laten omgaan, onder de strikte definitie dat lege clusters geen clusters zijn. p.19 MST geniet minder populariteit dan K-gemiddelden vanwege de hogere tijdscomplexiteit7. Optimalisaties kunnen van MST ook een goed presterend algoritme maken, in termen van uitvoeringstijd, maar het strikt hiërarchisch gedrag heeft soms ongewenste effecten. 4.4.3. Doelclusters ≠ Clusters ? In enkele eenzame gevallen wil het gebeuren dat het aantal clusters dat vooropgesteld werd niet overeenkomt met het aantal clusters dat effectief gemaakt is. In het geval van de processortrace kan dit voorkomen wanneer K-gemiddelden een betere clustering vond met een kleiner aantal, analoog voor MST, maar dit kan zeker ook bij SimPoint voorkomen. Ingeval SimPoint gebeurt dit wanneer een bepaalde cluster 0 elementen zou blijken te hebben. De applicatie die geschreven is, is tevens geschikt om deze zeldzame gevallen op te vangen en verwijdert stil de lege cluster uit de berekeningen. Merk op dat wij altijd zullen uitgaan van het aantal doelclusters, ervan uitgaande dat, als SimPoint een cluster achterwege laat, dat de traceclustering dit zou moeten kunnen opvangen met MST, wat totnogtoe veelal bleek (het omgekeerde is niet het geval). 7 MST stelt het opstellen van een afstandsmatrix voorop. Dit is strikt theoretisch en kan gelineariseerd worden. p.20 5. Evaluatie In dit hoofdstuk zullen we de eigenlijke vergelijking doorvoeren. Alle informatie is voorhanden: de data is in fasen ingedeeld, en er is een systeem om de twee modellen (processortrace en SimPoint) met elkaar te vergelijken. Vooraf gezegd, we gaan ervan uit dat de traceclustering beter zal presteren dan SimPoint, en dit is een redelijk eenvoudige veronderstelling. We vergelijken namelijk een fase-indeling die enkel de programmacode heeft om mee te werken (SimPoint), met een fase-indeling die het effectief gedrag van de processor kon nagaan. De vergelijking gaat niet volledig op, gezien we vergelijken op basis van de IPC, en de traceclustering meer dan enkel IPC in rekening neemt, maar het is een aanduiding. In dit hoofdstuk zullen we allereerst iets dieper ingaan op hoe we effectief de vergelijking gaan doorvoeren. Er zijn twee verschillende maatstaven die we zullen hanteren, elk met een andere nadruk. Na uit te leggen hoe we kunnen vergelijken, zullen we dieper ingaan op wat we algemeen genomen kunnen afleiden uit de informatie die we bekomen. Daarna gaan we bekijken wat enkele specifieke gevallen ons zeggen, en trachten na te gaan waarvan de prestaties van zowel traceclustering als SimPoint (vooral tegenover elkaar) afhangen. 5.1. Maatstaven voor vergelijking We zullen hier twee soorten maatstaven gebruiken: de variantiecoëfficiënt 8, en de macht en betrouwbaarheid van SimPoint ten opzicht van het processorgedrag. Met de variantiecoëfficiënt zullen we nagaan hoe zwaar de clusters onderling verspreid zijn (hoever ze reiken), terwijl macht en betrouwbaarheid iets zullen vertellen over wanneer fasewisselingen voorkomen. 5.1.1. Variantiecoëfficiënt Variantiecoëfficiënten hebben we geïntroduceerd in het korte hoofdstuk over SimPoint, en daar ook grotendeels uitgewerkt. Variantiecoëfficiënten hebben het voordeel op het BIC gezien de coëfficiënten ook individueel beduidend zijn, en intuïtief duidelijker, terwijl BIC eerder gradaties aantoont (zij het wel nauwgezet). Door een verhouding van de variantiecoëfficiënten van beide fase-indelingen te maken, kunnen we nagaan hoe nauwkeurig de fasen onderling worden voorgesteld (trace tov SimPoint). Indien de verhouding ver van 1 ligt, zullen de fasen zelf waarschijnlijk een grote afwijking vertonen ten opzichte van de twee verschillende modellen. Ligt de verhouding dicht bij 1, dan is de kans groot dat de afwijking minimaal is, en dan is een fase-onderzoek door direct vergelijken ook zinvoller. De verhouding stelt hier dus een soort “belang” of beduidendheid van de vergelijking voor. 8 Alhoewel SimPoint de eigen CoV waargeeft, werken we hier over andere datapunten en metrieken, en herberekenen we dus de CoV in de nieuwe context. p.21 trace CoV SimPoint = CoV trace CoV SimPoint Verder zullen we ook regelmatig gebruik maken van de gemiddelde variantiecoëfficiënt (average CoV), een aggregaat over alle benchmarks die we beschouwen. Dit gemiddelde zal zijn wat we zullen gebruiken voor de algemene beschouwingen, en om onregelmatigheden op te sporen. Ons eerste zicht zal gaan naar de gemiddelde variantiecoëfficiëntsverhouding (average CoV ratio), een mondvol voor het gemiddelde over al de benchmarks van de verhoudingen; we zullen het soms afkorten als gemiddelde verhouding. Hiermee kunnen we in een oogwenk nagaan hoe zwaar de variantiecoëfficiënt wisselt tussen de traceclustering en SimPoint, gegeven een aantal clusters. 5.1.2. Macht en betrouwbaarheid Wat betreft de macht en betrouwbaarheid van de modellen, stellen we SimPoint als nulhypothese op. Eerder hebben we vermeld dat we een interval zouden toelaten: we zullen intervallen van verschillende groottes beschouwen, met stralen variërend van 0 tot en met 5 datapunten. Een straal van x wil zeggen dat een fasewisseling hoogstens x punten links of rechts moet voorkomen voor het als dezelfde fasewisseling gezien wordt. We verwachten dat de betrouwbaarheid doorgaans hoger zal liggen dan de macht, d.w.z. we stellen dat SimPoint niet alle fasewisselingen zal vinden, maar dat de wisselingen die gevonden worden wel correct zullen zijn. Dit komt omdat de traceclustering nauwkeuriger informatie heeft om mee te werken en dus “subtiliteiten” gemakkelijker kan terugvinden. 5.1.3. Welk aantal clusters? Na het bekijken van de data, besluiten we om onze ogen te richten op de resultaten met aantal clusters tussen 4 en 8, grenzen inbegrepen (in het bijzonder 8 clusters). We gaan daar later iets dieper op in, maar momenteel volstaat het te weten dat kiezen voor meer clusters vaak voor zo'n granulariteit in de datapunten zorgt, dat er bijna geen sprake meer is van fasegedrag op het laagste niveau. Merk op dat fasegedrag op hogere orde (d.i. patronen in lagere-orde fasegedrag) wel haalbaar wordt met grote aantallen clusters (cfr. Conclusies—Verdere uitgangspunten). 5.2. Algemene resultaten In dit stuk zullen we beschrijven wat de algemene trend van—beter, de rode draad doorheen— het onderzoek is. In het bijzonder zullen we hier beschrijven wat er uniform over alle architecturen heen gebeurt, en met wat meer detail ingaan op de effecten van het “excentriek” en “stabiel” gedrag van bepaalde benchmarks. p.22 5.2.1. Gemiddelde variantiecoëfficiëntverhouding is stabiel De gemiddelde variantiecoëfficiëntverhouding geeft een ogenschijnlijke vreemde tendens weer: de verhouding daalt door de band genomen, maar vertoont een kleine piek opwaarts bij 8 clusters, zodat blijkt dat de verhouding beter is bij 8 clusters dan bij 12. Dit baart ons weinig zorgen; hetgeen dit ons vertelt is dat SimPoint een minder sterk dalende verlaging in variantiecoëfficiënt heeft dan de traceclustering, maar het geeft toch stof tot denken. Hoe meer clusters er dus genomen worden, hoe groter het relatieve verschil lijkt te worden. Average CoV Ratio 1 0,9 0,8 0,7 0,6 Avg 0,5 0,4 0,3 0,2 0,1 0 1 2 3 4 6 8 12 16 Figuur 8: De gemiddelde CoV-verhouding van de NNN-configuratie. Merk op hoe er een lichte stijging is bij 8 clusters, gevolgd door een sterke daling bij 12 clusters. Bij 1 cluster ligt de verhouding op 1, gezien de beide clusteringen dan identiek zijn, en de standaardafwijking en verwachtingswaarde dus ook. Verder lijkt de verhouding doorgaans tussen 50% en 75% te liggen, wat we voldoende achten om resultaten zinvol te kunnen bespreken. 5.2.2. Goede macht en betrouwbaarheid Met uitschieters in beide richtingen voor verschillende benchmarks, lijkt het dat de macht en betrouwbaarheid van de modellen doorgaans boven 50% liggen; dit wil zeggen dat het veiliger is om van SimPoints leiding uit te gaan dan niet. Belangrijk voor deze nummers is natuurlijk de intervalstraal waarover we rekenen. Eerder hebben we vermeld dat we interstralen tussen 0 en 5 zouden beschouwen, grenzen inbegrepen, maar p.23 dit is aanzienlijk moeilijk grafisch voor te stellen, dus tonen we hier de resultaten gebaseerd op enkele configuraties op intervalstraal 2. Gemiddeld genomen zijn de resultaten dus goed te noemen (figuren 9 & 10). Radius 2 Averages 1 0,9 0,8 0,7 0,6 Levels Powers 0,5 0,4 0,3 0,2 0,1 0 1 2 3 4 6 8 12 16 Figuur 9: Gemiddelde macht (power) en trouw (level), straal 2, van alle benchmarks onder LLL-configuratie, voor 116 clusters. Merk op hoe de trouw hoger blijft dan de macht. Radius 2 Averages 1 0,9 0,8 0,7 0,6 Levels Powers 0,5 0,4 0,3 0,2 0,1 0 1 2 3 4 6 8 12 16 Figuur 10: Gemiddelde macht (power) en trouw (level), straal 2, van alle benchmarks onder NNN-configuratie, voor 116 clusters. p.24 5.2.3. Evenredige prestatie over verschillende configuraties heen Het verschil in configuraties leidt tot weinig verschil in gemiddelde verhouding. Op het eerste zicht vertelt dit ons dat SimPoint grotendeels onafhankelijk is van de configuratie van de processor (binnen grenzen), of toch dat het in evenredigheid niet beter of slechter presteert dan een traceclustering onder dezelfde voorwaarden. Individueel zijn er soms wel verschillen naargelang de benchmarks die bekeken worden, maar de verschillen zijn vaak verwaarloosbaar. Dit heeft als voordeel dat we alle configuraties ongeveer gelijk kunnen wegen, wat vergelijken aanzienlijk eenvoudiger maakt. In principe staat dit ons toe om slechts een aantal configuraties te bekijken. Average CoV Ratio LXX 1 0,9 0,8 LLL LLN LLS LNL LNN LNS LSL LSN LSS 0,7 0,6 0,5 0,4 0,3 0,2 0,1 0 1 2 3 4 6 8 12 16 Figuur 11: Gemiddelde variantiecoëfficiëntverhouding (trace/SimPoint) over alle configuraties met grote caches, voor 1-16 clusters. Merk op dat voor 4 of meer clusters, de verhouding weinig afwijking geeft, alhoewel LSL een uitschieter blijft. Ook hier weer de daling bij de sprong van 8 naar 12 clusters. 5.2.4. Effecten van de configuraties De effecten van de verschillende configuraties wegen wel door op de individuele variantiecoëfficiënten van zowel de traceclustering als SimPoint. De effecten zijn, in volgorde van kracht: 1. Processorbreedte is evenredig met variantiecoëfficiënt 2. Buffergrootte is omgekeerd evenredig met variantiecoëfficiënt 3. Cachegrootte is omgekeerd evenredig met variantiecoëfficiënt De processorbreedte lijkt het meest doorslaggevend; hoe hoger de processorbreedte, hoe hoger de variantiecoëfficiënten voor zowel de traceclustering als SimPoint (merk op dat, volgens vorige punt, deze verandering wel in evenredige verhouding zal zijn). p.25 Achteraf gezien zouden we dit ook mogen verwachten; hoe groter de processorbreedte, des te groter het mogelijke verschil in instructies per cyclus (IPC). Het potentieel wordt des te meer, maar een plotse schommeling in de omgeving (code) zal ook tot grotere schommelingen in processorgedrag leiden. Als noot, de cachegrootte blijkt weinig verschil te maken wanneer de processorbreedte en buffergrootte klein zijn. Average Trace CoV LXX 55 50 45 LLL LLN LLS LNL LNN LNS LSL LSN LSS 40 35 30 25 20 15 10 5 0 1 2 3 4 6 8 12 16 Figuur 12: Gemiddelde variantiecoëfficiënt van traceclustering over alle configuraties met grote caches, voor 1-16 clusters. Merk op dat de CoV aanzienlijk daalt bij verkleining van de processorbreedte (middenste component), en dat dit duidelijk de sterkste factor is. Average SimPoint CoV LXX 55 50 45 LLL LLN LLS LNL LNN LNS LSL LSN LSS 40 35 30 25 20 15 10 5 0 1 2 3 4 6 8 12 16 Figuur 13: Simpoints gemiddelde variantiecoëfficiënt over dezelfde data als hierboven. Merk de sterk gelijke trend op. p.26 5.3. Gevallen met hoge nauwkeurigheid 5.3.1. Regelmatig processorgedrag Waar de processor gestaag gedrag vertoont—dus duidelijke fasepatronen in lage of hogere orde —lijkt SimPoint het meest tot recht te komen. Zelfs voor een klein aantal clusters weet het hoge waarden op zowel macht als betrouwbaarheid te halen, al wil de variantiecoëfficiënt soms wat hoger liggen. Dit spreekt weinig tot de verbeelding. Stabiel gedrag betekent vaak (zeker niet altijd) dat gelijkaardige code doorlopen blijft worden. Beter gezegd, processorgedrag blijft vaak stabiel tijdens het uitvoeren van gelijkaardige code. Dit bleek zeer duidelijk uit de SPEC-benchmark vortex, maar ook nog vele andere. Uit recent onderzoek blijkt tevens dat beduidende veranderingen in code nauwkeurig teruggevonden worden in SimPoint [strong-correlation], wat hier bevestigd wordt. Intervalstraal 0 1 2 3 4 5 Trouw 0,91 0,96 0,98 0,98 0,99 0,99 Macht 0,84 0,93 0,95 0,95 0,96 0,96 Tabel 2: Macht en betrouwbaarheid voor vortex, 8 clusters. Merk op dat zelfs met intervalstraal 0 de waarden nog zeer hoog liggen. p.27 Figuur 14: Processorgedrag voor SPEC-benchmark met vortex, LLL-configuratie. Merk op hoe het gedrag stabiel blijft, en SimPoint dit ook duidelijk aantoont. p.28 5.4. Gevallen met lagere nauwkeurigheid 5.4.1. Moeilijk voorspelbaar gedrag Sommige programma's vertonen sterk variërend gedrag, zelfs al zijn ze door het menselijk oog min of meer in fasen onder te verdelen. Neem als voorbeeld een compiler (gcc); hoewel er duidelijk fasen zijn (lexicaal, abstractie, tussentaal, optimalisatie...), is het gedrag in de fasen zelf moeilijk voorspelbaar. In het specifieke voorbeeld van bzip2 zijn de karakteristieken op z'n minst excentriek te noemen, met alle gevolgen vandien. Excentriek gedrag doet vaak meer schade aan de traceclustering dan aan SimPoint bij een laag aantal clusters. Dit valt te verklaren door de vele karakteristieken waar de traceclustering rekening mee houdt, en die onderling ook sterk beginnen variëren bij wild processorgedrag. Over het algemeen vindt SimPoint minder fasewisselingen, en hier wordt dat in het extreme getrokken. Doorgaans verbeteren de statistieken naarmate het aantal clusters toeneemt, wat te verwachten valt; extreme waarden, die dan ongeveer even vaak zullen voorkomen als “normale” delen, komen tot hun recht met een eigen cluster, waardoor macht, betrouwbaarheid, en variantiecoëfficiënt verbeteren. Intervalstraal 0 1 2 3 4 5 Trouw 0,62 0,67 0,77 0,79 0,8 0,82 Macht 0,03 0,03 0,04 0,04 0,04 0,05 Tabel 3: bzip2 met 8 clusters, NSS-configuratie. De macht blijft beduidend laag, alhoewel de trouw hoog is. Dit betekent dat, alhoewel SimPoint niet alle fasewisselingen vindt, het niet vaak mist wanneer het er één vermoedt. SimPoint CoV 140 130 120 110 100 90 ammp sixtrack applu apsi art swim twolf vortex bzip2 crafty eon wupwise equake facerec galgel gap 80 70 60 gcc gzip lucas mcf mesa mgrid parser 50 40 30 20 10 perlbmk 0 1 2 3 4 6 8 12 16 Figuur 15: SimPoint CoV voor NNN-configuratie. De donkere staaf is bzip2 en blijft (in verhouding) zeer hoog staan. p.29 Bzip2 is duidelijk het probleemkind hier, en mcf is dat ook voor minder dan 6 clusters. Deze zijn meer uitzondering dan regel, maar duiden aan dat SimPoint niet in alle gevallen de fasen nauwkeurig weergeeft. De vraag is hier misschien ook of we dit effectief wel als fasewisselingen willen aanvaarden (figuur 16), echter dat is niet aan ons, maar aan de benutters van de data, om dat te kiezen. p.30 Figuur 16: Een deel van een SPEC-benchmark voor bzip2, met 0,5x zoom. Merk op dat er schommelingen in IPC, iALU, en RW, die zorgen voor wisselingen in de traceclustering, maar niet in SimPoint. p.31 6. Conclusie Hier vatten we nog eens samen wat we uit de evaluatie kunnen afleiden, en geven blikken op waar mogelijk verbeteringen kunnen doorgevoerd worden. 6.1. Stabiel codegedrag geeft stabiel processorgedrag We krijgen duidelijk fasen wanneer het codegedrag weinig varieert. Dit spreekt weinig tot de verbeelding, maar is deel van de conclusie die we uit dit werk kunnen afleiden. In het bijzonder stellen we vast dat, wanneer er duidelijke patronen zijn (voor het menselijk oog), deze ook waarheidsgetrouw weergegeven worden door zowel de traceclustering als SimPoint. Opmerkelijk is wel dat stabiel processorgedrag niet altijd de aanleiding is tot stabiel codegedrag, maar dit is meer uitzondering dan regel. Over het algemeen gaat de gelijkheid op, maar de implicatie is sterker als in de hoofding gegeven. En aangezien het om een implicatie gaat, willen we er nog op wijzen dat labiel processorgedrag vaak toon geeft aan labiel codegedrag. 6.2. Processorconfiguraties zijn belangrijk, maar niet bepalend De processorconfiguratie stelt een maat op voor de variantiecoëfficiënt, maar er is weinig aanleiding naar duidelijke fasewisselingen omwille van de processorconfiguratie, wat we kunnen afleiden uit het stabiel blijven van de gemiddelde variantiecoëfficiënt onder verschillende architecturen. Verder bleek wel dat de impact van de processorbreedte het grootst was, en wel evenredig aan de variantiecoëfficiënt: hoe breder de processor, hoe groter de relatieve afwijking. Daarentegen zijn de groottes van caches en buffers omgekeerd evenredig met de variantiecoëfficiënt. 6.3. Simpoint is voldoende Dit is de rode draad die we doorheen dit werk terugvinden: doorgaans volstaat SimPoint om de fasen tijdens programma-uitvoering terug te vinden, maar het is ook belangrijk te weten dat er gevallen zijn waarin de gunstige vergelijking minder opgaat. Blindelings vertrouwen is hier niet zo zeer verantwoord, maar zoals leidraden komen en gaan, lijkt deze toch wel een belangrijke en nauwkeurige variant. We merken op dat er vaak meer fasewisselingen zijn dan er gevonden worden, wat ook met onze intuïtie strookt. Het verschil is echter niet groot, zoals onze macht- en betrouwbaarheidsresultaten laten blijken. p.32 Ook blijkt de configuratie van de processor weinig verschil te maken in de verhouding van de performantie van beide modellen. Beide modellen ondervinden door de band genomen gelijkaardige effecten bij variërende configuraties, en het blijkt dat de breedte van de processor de meest bepalende factor is. Wat betreft SimPoint lijkt het tevens dat 8 clusters het beste aantal is. Het merendeel van de benchmarks verdeelt zich blijkbaar, code-gewijs, gunstig in onder een 8-tal uitvoeringspatronen. Voor meer dan 8 clusters daalt de CoV-verhouding sterk (en lijkt te blijven dalen), wat voor de concepten macht en betrouwbaarheid van een model minder waardevolle cijfers oplevert. 6.4. Mogelijk verder onderzoek Soms vertoont een programma ook hogere-orde fasegedrag, wat wil zeggen, sterk periodiek gedrag. Dit kan opgespoord worden met technieken uit patroonherkenning; een mogelijke invalshoek houdt in de fasen zelf als alfabet te beschouwen, en dan patroonherkenning voor karakterstrings toe te passen. Zo kunnen wetmatigheden als “patroon A volgt altijd patroon B” opsporen, of “patroon A volgt nooit zichzelf op” ook gevonden worden. Mogelijks kan een programma quasi volledig periodiek bevonden worden (zoals applu). Eventueel kan men kerning toepassen op het niveau van de fasewisselingen zelf. Deze optie zou aanzienlijk de eenvormigheid verhogen inzake benchmarks als bzip2, maar men moet ook nagaan wat de impact op clusteringen is die wel goed ingedeeld lijken. p.33 7. Referenties Reducing design complexity of the load/store queue, Il Park, Chong Liang Ooi, T. N. Vijaykumar. Instruction Issue Logic for High-Performance, InterrupTabel, Multiple Functional Unit, Pipelined Computers, Gurindar S. Sohi, Sriram Vajapeyam [answers-1] “Coefficient of Variance: <http://www.answers.com/coefficient+of+variance>, 2006-08-29 Search Results”, [numa] Collegenota's voor “Numerieke Analyse”, G. Vanden Berghe, 2004 [pelleg-xmeans] X-means, Extending K-means with efficient estimation of the number of clusters, Dan Pelleg, Andrew Moore [phases] Discovering and Exploiting Program Phases, T. Sherwood, E. Perelman, G. Hamerly, S. Sair, B. Calder, 2003 [simpoint] “SimPoint”, B. Calder, <http://www.cse.ucsd.edu/~calder/simpoint/> [stat-1] Nota's bij het opleidingsonderdeel “Waarschijnlijkheidsrekening en statistiek”, H. De Meyer, 2003 [strong-correlation] The Strong Correlation between Code Signatures and Performance, J. Lau, J. Simpson, E. Perelman, G. Hamerly, B. Calder, Maart 2005 [superscalar] The Microarchitecture of Superscalar Processors, James E. Smith, Gurindar S. Sohi, 1995 p.34