Home

Hoe betere optimalisatie van games de geheugencrisis kan verzachten

De geheugencrisis grijpt om zich heen en maakt in de techwereld steeds meer slachtoffers. Door de honger naar geheugen voor AI worden onder meer consoles, geheugensticks, videokaarten en laptops duurder. Gamen dreigt een elitehobby te worden. Of kunnen gameontwikkelaars hun games zo optimaliseren dat nieuwe games ook voor gamers met oude hardware toegankelijk blijven?

De geheugencrisis grijpt om zich heen en maakt in de techwereld steeds meer slachtoffers. Door de honger naar geheugen voor AI worden onder meer consoles, geheugensticks, videokaarten en laptops duurder. Gamen dreigt een elitehobby te worden. Of kunnen gameontwikkelaars hun games zo optimaliseren dat nieuwe games ook voor gamers met oude hardware toegankelijk blijven?

"Het zou mij niet verbazen als we toch nog wat innovatie en daarmee verbeteringen op audiovisueel gebied gaan zien, omdat je bij gelijkblijvende hardware beter moet optimaliseren." Collega Jurian deed die uitspraak begin maart in de podcast naar aanleiding van de geheugencrisis. Hij zag het als een van de weinige potentiële lichtpuntjes. Maar hoe optimaliseer je als gameontwikkelaar games voor mindere hardware en, vooral, minder ram?

Dat is iets waar Peter 'Durante' Thoman alles over kan vertellen. Thoman is bekend van de mod DSfix voor de originele versie van Dark Souls op pc. Zijn bedrijf PH3 Games heeft gewerkt aan de ports van verschillende games voor de pc, PlayStation 5, Nintendo Switch en Switch 2, zoals meerdere games in de Trails- en Ys-series.

Games optimaliseren begint meestal met profilers. Deze tools laten zien welke onderdelen het meest gebruikt worden tijdens processen en dus de meeste kans hebben om de bottleneck te zijn. "Als je gewoon gaat optimaliseren zonder dat je weet wat er precies gebeurt, werkt dat meestal helemaal niet", zegt Thoman.

De ontwikkelaar vertelt dat er twee soorten veelgebruikte profilers zijn: samplingprofilers en tracingprofilers. De samplingprofiler onderbreekt het programma een bepaald aantal keer per seconde om te zien welke threads waarmee bezig zijn. Wanneer dat tijdens een langere periode gebeurt, wordt duidelijk welke functies het systeem het vaakst gebruikt.

Het nadeel is dat deze methode alleen werkt voor een cpu: bij een gpu zijn de processen daarvoor te complex. Zelfs bij cpu-workloads kunnen 'nepbottlenecks' ontstaan door afhankelijkheden in parallelle processen. Als thread 1 negentig procent van de tijd wacht op thread 2, lijkt het alsof thread 1 de bottleneck is, omdat hij negentig procent van de tijd met één proces bezig is.

Ontwikkelaars gebruiken daarom vaak tracingprofilers als Tracy. Die laten met gekleurde balken zien hoe de threads in elkaar haken. Tracy maakt het mogelijk om de programma-uitvoering frame voor frame te inspecteren. Gebruikers kunnen precies zien welke functies het programma aanroept, hoeveel tijd die functies in beslag nemen en hoe ze elkaar beïnvloeden in een multithreaded omgeving.

Volgens Thoman zijn er grofweg vijf factoren waarmee je rekening moet houden tijdens de optimalisatie: compute van de gpu en de cpu, geheugenbandbreedte van de gpu en cpu en de geheugenbandbreedte tussen de gpu en cpu.

"In mijn ervaring ben je eigenlijk nooit beperkt door de rekenkracht", zegt Thoman. "Dat gebeurt alleen als het programma al extreem goed geoptimaliseerd is of je iets wilt doen dat in structuur simpel is, maar wel intensief."

In zijn blogs begint de ontwikkelaar het optimalisatieproces vaak met 'laaghangend fruit'. Meestal komt dat neer op het verwijderen van processen die niet hoeven plaats te vinden.

"Stel je voor dat je de inverse kinematica continu bijwerkt. Inverse kinematica draait om de positionering van botten ten opzichte van de omringende geometrie", legt Thoman uit. "Dat is niet zo belangrijk. Het is wel behoorlijk intensief en het kan voorkomen dat je dit bijwerkt voor npc's die niet eens in beeld zijn. Dat klinkt misschien gek, maar de eenvoudigste aanpak is om het voor álle npc's te doen. Je moet extra werk verrichten om te bepalen wie wel en wie niet in beeld is."

"Je kunt dus rekenwerk volledig elimineren zonder de uiteindelijke resultaten te beïnvloeden", vervolgt hij. "Dat is natuurlijk de ideale situatie voor optimalisatie en vaak een van de efficiëntste dingen die je kunt doen. Eigenlijk hoef je pas na te denken over hoe je het werk sneller of efficiënter kunt doen, wanneer je het punt hebt bereikt waarop je voornamelijk de noodzakelijke taken uitvoert."

Dat klinkt eenvoudig, maar dat is het volgens Thoman zeker niet: "In de praktijk is het heel makkelijk gezegd. Het is niet in alle gevallen even makkelijk gedaan. Het geval dat ik schetste klinkt heel simpel. Dat is het misschien in sommige gevallen ook wel. Maar er zijn veel dingen waarin je aanzienlijk werk moet steken om bijvoorbeeld efficiënt uit te zoeken waarom je iets niet hoeft te doen of wat je wél moet doen."

Zo is het soms nodig om een compleet nieuwe acceleratiestructuur op te zetten, zegt Thoman. Deze datastructuur versnelt ruimtelijke zoekopdrachten in spellen, zoals de locatie van en onderlinge afstand tussen personages, voorwerpen en gebouwen bepalen. De acceleratiestructuur groepeert objecten op basis van hun positie. Hierdoor kan het systeem in één keer groepen objecten uitsluiten die niet relevant zijn voor een specifieke berekening, in plaats van dat het deze berekening voor elk afzonderlijk object moet doen.

Thoman: "Zonder goede acceleratiestructuur besteedt het systeem bijna net zoveel tijd aan het uitzoeken wat het wel en niet moet doen als aan alle assets renderen."

En het werkgeheugen? Hoe zit het met het optimaliseren daarvoor? Tot op heden was dat zelden de focus van pc-optimalisatie, legt Thoman uit: "Wanneer je een port maakt van een consolegame, heb je op de console waarschijnlijk minder geheugen dan op de pc. Dus als je een pc-versie van een consolegame maakt, is ramgebruik waarschijnlijk niet een van de dingen die je specifiek gaat optimaliseren."

Dat betekent niet dat het niet mogelijk is: "We hebben recent een Nintendo Switch-versie gemaakt voor een game die als eerste op de PlayStation 5 uitkwam. De Switch heeft natuurlijk niet zoveel geheugen als de PlayStation 5. Voor die game en voor veel midrange- tot high-end games is veel van het geheugengebruik te wijten aan textures en de geometrie. Het gaat echt om de assets."

Een van de manieren om dat geheugengebruik terug te dringen is textures comprimeren. Daarbij zou nog winst te behalen zijn door een alternatieve techniek in te zetten, maar bij pc-games doen ontwikkelaars dat niet.

Vaak gebruiken zij BC7 voor texturecompressie. Dat is een formaat om textures efficiënt te comprimeren. BC7 deelt textures op in 4x4-texturepixels, zogenoemde texels. Elk blok is 128bit. Om de details van verschillende textures te kunnen behouden, gebruikt BC7 verschillende modi.

Textures met ingewikkelde patronen krijgen bijvoorbeeld een modus met drie verschillende kleurgebieden. Textures met subtiele kleuren krijgen een modus met minder verschillende kleurgebieden, maar preciezere kleuren. Sommige modi kunnen ook transparantie weergeven.

Op veel andere platforms, waaronder mobiel en de Nintendo Switch, gebruiken ontwikkelaars meestal adaptive scalable texture compression, ofwel astc. Astc is flexibeler dan BC7, omdat het variabele blokgroottes ondersteunt. Elk blok is nog steeds 128bit, maar de texels kunnen 4x4 tot 12x12 groot zijn. Daarmee kunnen ontwikkelaars bepaalde textures met minder detail opslaan, zoals achtergrondobjecten en egale muren. Dat bespaart vram, zonder dat het kwaliteitsverschil voor het menselijk oog zichtbaar is.

"Astc is wat beter, maar om de een of andere reden krijg je dat niet op pc-hardware. Dat is jammer, omdat je met die techniek in sommige gevallen relatief makkelijk het geheugengebruik van textures met 30 procent zou kunnen verlagen met vrijwel gelijkwaardige kwaliteit."

Thoman vermoedt dat het ontbreken van astc voor pc-hardware te maken heeft met licentiekwesties: "Ik weet het niet zeker, maar waarschijnlijk kost het een paar cent extra per gpu als ze die technologie willen integreren."

Volgens de ontwikkelaar zou het ook kunnen dat gpu-fabrikanten het voordeel van de betere technologie niet vinden opwegen tegen de extra kosten van de integratie. "Een BC7-texture is ongeveer vier keer kleiner dan een ongecomprimeerd bestand. Misschien vinden ze de relatief kleine extra compressie gewoon niet belangrijk genoeg."

Hoewel pc-ontwikkelaars dus werken met een wat minder efficiënte compressietechnologie, denkt Thoman dat er bij texturecompressie niet veel winst te boeken is. "We beschikken over goed ontwikkelde compressietechnologieën en die worden al in de meeste games gebruikt. Er komen nog steeds pc-games uit met ongecomprimeerde textures voor elementen die eigenlijk gecomprimeerd zouden moeten zijn. Maar in de meeste games is texturecompressie redelijk goed uitgevoerd."

Dat geldt niet voor de compressie van geometrie van games, oftewel de 'skeletten' onder de textures. "Veel pc-versies van games en versies voor andere platforms die niet erg beperkt zijn in hun geheugen, zijn extreem inefficiënt in de opslag van geometrie." 3d-modellen in games bestaan uit polygonen. De vertices, de hoekpunten van die polygonen, worden volgens Thoman vaak 'gewoon' opgeslagen als een lijst met 32bit-floats.

Dat loopt al snel op als onder andere de eigenschappen voor de positie van de vertex (bestaande uit een x-, y- en z-coördinaat), de normaal (bestaande uit een nx-, ny- en nz-waarde) en de tangent (tx-, ty-, tz- en tw-waarde) van elke vertex allemaal als 32bit-waardes worden opgeslagen.

"Dat is echt verspilling", zegt Thoman. "Voor een Nintendo Switch-port hebben we het geheugenverbruik per vertex met meer dan de helft verminderd, zonder dat de visuele kwaliteit er ook maar enigszins onder lijdt. Dat is gewoon door een geschiktere numerieke representatie te kiezen voor elk aspect van elke vertex. Dat kan vooral in het geheugengebruik van de gpu veel schelen."

Wat een 'geschikte numerieke representatie' is, hangt af van de situatie, legt de ontwikkelaar uit. "Het simpelste is om de 32bit-floats op te breken in helften van 16 bits, maar soms verlies je daarmee informatie. Bij de coördinaten van textures krijg je precisieverlies als die textures groter zijn dan 1024 bij 1024 pixels." Dat probleem is bij 16bit-integers niet aanwezig. Integers werken wel met discrete stappen. Daardoor is de positionele precisie beperkt, wat kan leiden tot problemen als shimmering.

Ook de informatie die de ontwikkelaar in de specifieke float moet opslaan, is van belang voor de keuze om een 16bit- of 32bit-float te gebruiken. "Dat proces is altijd een soort hiërarchische uiteenzetting van alle informatie", aldus Thoman. "Als je 32 bits hebt om één punt in je hele virtuele stad te definiëren, is dat natuurlijk niet veel. Maar als je 32 bits hebt om de positie van een arm ten opzichte van een romp te definiëren, is dat extreem veel. Zelfs met 16 bits ben je dan waarschijnlijk nog steeds preciezer dan met de 32bit-float in je hele stad."

De beste 'werkgeheugenoptimalisatie' is ervoor zorgen dat het systeem het werkgeheugen helemaal niet hoeft aan te spreken, zegt Thoman. "Met sneller werkgeheugen kun je de latency bijvoorbeeld met een factor twee verkleinen. Dat klinkt als een grote winst. Maar het verschil tussen een datastructuur die in cache blijft en een die buiten de cache gaat, is veel groter. Het verschil daartussen is ongeveer een factor 100."

"Je snellere geheugen is mooi meegenomen, maar als iemand de datastructuur zou optimaliseren, zou dat een veel groter verschil maken dan welke hardwarewijziging dan ook. Ik denk dat de grootste impact van de optimalisatie in de meeste applicaties – niet alleen games – te danken is aan aanpassingen aan datastructuren en algoritmes waardoor ze efficiënter omgaan met de cache. Dat geldt voor zowel de cpu als de gpu."

Het geheugengebruik en de cache-efficiëntie optimaliseren gaat bovendien vaak hand in hand, zegt Thoman. "Als je je geheugenverbruik vermindert, zijn je datastructuren kleiner en passen ze beter in de cache. Als een gpu een gecomprimeerde BC7-texture rendert, is dat sneller. Dat komt niet alleen door het lagere geheugengebruik, maar ook doordat het systeem de texturecache van de videokaart efficiënter kan inzetten."

Bij PH3 werken in totaal drie werknemers aan games porten en optimaliseren. Toch zet PH3 Games vaak zeer geoptimaliseerde ports neer. Zo wist de studio de fps van de pc-versie van Ys X: Nordics op zijn testsysteem bijna te verdrievoudigen. Waarom lukt het grote uitgevers dan soms niet om goede pc-ports te maken, zoals bij Monster Hunter Wilds, Star Wars Jedi: Survivor en The Elder Scrolls IV: Oblivion Remastered?

Volgens Thoman komt dat waarschijnlijk vaak meer door zakelijke beslissingen dan onkunde. "Het komt vaak voor dat niemand die in het bedrijf zakelijke beslissingen neemt, intrinsiek geeft om pc-ports. Dan moet er dus een duidelijk verband zijn tussen slechte optimalisatie en slechtere bedrijfsresultaten. Anders geven ze geen prioriteit aan het maken van een betere port."

Het probleem ligt volgens Thoman niet bij de mensen. "Ik weet zeker dat er mensen bij de grote studio's zijn die een game voor de pc kunnen optimaliseren. Maar als je een goede port wilt maken, kost dat waarschijnlijk een paar maanden tijd voor een paar man. Daarbij moeten ook een paar senior technische engineers helpen. Dan kan het prima. Het is geen magie."

Volgens Thoman kunnen de ramtekorten game-uitgevers mogelijk aansporen om hun pc-ports beter te optimaliseren. "Monster Hunter Wilds kreeg flinke kritiek vanwege prestatieproblemen op pc. Een van de redenen dat de uitgever opmerkte dat het spel niet goed liep, is dat het negatieve recensies op Steam kreeg. Dat merken uitgevers wel degelijk op."

"Steam-reviews zijn niet perfect, maar over het algemeen is het goed dat er een directere feedbackloop is naar uitgevers bij problemen met games", vervolgt Thoman. "Dat betekent dat ze er misschien meer aandacht aan besteden. Ik denk dat dit ook kan gebeuren met onnatuurlijk hoge prestatie-eisen in het algemeen, vooral nu niemand het zich kan veroorloven om zijn pc-hardware te upgraden."

"Ik denk dat het er simpelweg op neerkomt dat steeds meer mensen op oudere hardware gaan spelen", voorspelt de ontwikkelaar. "Als ze dan niet de prestaties zien die ze verwachten, zullen ze dat ook luider laten horen. En dat zou weleens iets kunnen veranderen."

Redactie: Imre Himmelbauer • Eindredactie: Marger Verschuur

Source: Tweakers.net

Previous

Next