RPCS3 auf Arm: Mobile PS3-Emulation wird bis zu 60 Prozent schneller
Die Arm-Version des PS3-Emulators RPCS3 hat durch umfangreiche Optimierungen deutlich an Leistung gewonnen. Je nach Szenario soll das Plus bis zu 60 Prozent betragen. Erreicht wurde dies durch die Beseitigung mehrerer Fehler und die Optimierung bislang ineffizienter Routinen. Zugleich sank auch die Leistungsaufnahme.
Dies erklärt „Whatcookie“, einer der führenden RPCS3-Entwickler, in einem Video auf seinem YouTube-Kanal.
Unterschiedliche Zeitmessungen
Ausgangspunkt war ein Ayn Odin 2, den Whatcookie eigenen Angaben zufolge für die Optimierung von RPCS3 auf Arm genutzt hatte. Dabei erkannte der Entwickler schnell, dass der Emulator vor allem deshalb viel Leistung einbüßte, weil er teilweise die Hälfte seiner CPU-Zeit innerhalb einer lediglich vier Zeilen umfassenden „Busy Wait“-Funktion verbrachte. Diese überprüfte fortlaufend, ob ein anderer Thread den Wert einer Variablen verändert hat. Das ermöglichte zwar eine schnelle Reaktion auf Änderungen, verursachte aber zugleich CPU-Last und beanspruchte Ressourcen, die sich mehrere Prozessorkerne teilen. Auf x86-Systemen hatte die entsprechende Busy-Wait-Implementierung unter bestimmten Bedingungen hingegen eine nahezu dreifache Performance ermöglicht – die Systeme verhalten sich also grundverschieden.
Bei Arm war das Problem vor allem in der Zeitmessung zu finden. Auf x86-Systemen arbeitet der dafür verwendete Hardware-Timer laut Whatcookie üblicherweise mit etwa 2 bis 4 GHz, wodurch die Wartezeit ungefähr einer Mikrosekunde entspricht. Bei der Portierung auf Arm wurde die Timer-Abfrage durch das entsprechende Arm-Gegenstück ersetzt, das beispielsweise beim Ayn Odin 2 allerdings lediglich mit 19 MHz und damit laut Whatcookie rund 150-mal langsamer als die entsprechende Timer-Abfrage auf x86-Systemen läuft. Dadurch konnte die Wartezeit auf bis zu 150 Mikrosekunden anwachsen. Hinzu kam, dass Hardware-Timer auf Arm-Geräten je nach Plattform mit sehr unterschiedlichen Frequenzen zwischen 10 MHz und 1 GHz arbeiten können – was die Implementierung noch einmal problematischer gestaltete.
Als Lösung soll RPCS3 deshalb die tatsächliche Frequenz des jeweiligen Timers berücksichtigen und die Wartezeit entsprechend skalieren. Allein diese Korrektur soll durchschnittlich rund 25 Prozent mehr Performance ermöglichen und gleichzeitig die Leistungsaufnahme im Mittel um etwa zehn Prozent reduzieren.
Projekt seinerzeit an vielen Stellen unvollendet
Auch die Synchronisation innerhalb der Busy-Wait-Funktion wurde optimiert, was ebenfalls einen Leistungszuwachs mit sich brachte. Bislang verwendete RPCS3 auf Arm den Yield-Befehl als Gegenstück zum Pause-Befehl auf x86-Systemen, wobei der Befehl, vereinfacht dargestellt, dem Prozessor signalisiert, dass die aktuelle Arbeit eines Threads eine geringere Priorität besitzt und Rechenzeit gegebenenfalls anderweitig genutzt werden kann.
Dieser Ansatz funktioniert allerdings nur so lange, wie Geräte Simultaneous Multithreading, kurz SMT, nutzen. Die meisten Arm-Systeme setzen stattdessen allerdings auf Symmetric Multiprocessing, kurz SMP, weshalb Whatcookie zur Instruction Synchronization Barrier (ISB) wechselte. Diese Lösung entspricht zwar nicht exakt der Pause-Funktion von x86, kann die Leistungsaufnahme aber weiter reduzieren. Statt eine Bedingung mehrfach innerhalb einer Nanosekunde abzufragen, erfolgt die Überprüfung dadurch nur noch einmal innerhalb mehrerer Nanosekunden.
Auch an den Recompilern von RPCS3 hat Whatcookie Verbesserungen vorgenommen. Die ursprüngliche Arm-Portierung stammte von Nekotekina, dem ehemaligen Lead-Entwickler des Projekts. Dieser verließ dieses jedoch, bevor die Arbeit an den Recompilern abgeschlossen war. Gerade diese Komponenten sind aber entscheidend dafür, dass emulierte Spiele mit hoher Geschwindigkeit laufen können – entsprechend blieben bei Arm mehrere Probleme bestehen, die in den x86-Versionen bereits gelöst waren. In der Folge hatte Whatcookie zahlreiche Instruktionen untersucht, bei denen die x86-Version effizienteren Code erzeugte, als es bei der Arm-Version der Fall war. Dafür wurden mehrere Stellen des Codes bearbeitet, um die Ausführung auf Arm-Prozessoren zu beschleunigen.
Viele kleine Veränderungen ergeben ein hohes Potenzial
Darüber hinaus wurden grundlegende Routinen des Emulators optimiert. So konnten unter anderem Vergleichsoperationen mithilfe von Multiply-Accumulate-Instruktionen beschleunigt werden. Dabei werden die Ergebnisse mehrerer Vergleiche miteinander multipliziert und anschließend akkumuliert, wodurch weniger Instruktionen ausgeführt werden müssen. Dies soll auf mittleren und größeren Arm-Kernen eine Leistungssteigerung von bis zu 22 Prozent und auf kleineren Kernen von etwa 16 Prozent bedeuten.
Gleiches gilt für die Checksum-Berechnung, bei der nun UABAL, Unsigned Absolute Difference and Accumulate Long, zum Einsatz kommt. Die Anweisung kann zwei Werte laden, deren absolute Differenz bestimmen und das Ergebnis akkumulieren. Dadurch soll die entsprechende Routine auf mittelgroßen Arm-Kernen um 38 Prozent und auf größeren Kernen um 21 Prozent schneller arbeiten. Zudem wird nun umfangreicher Checksum-Code zusammengefasst, sodass weniger Platz im Code-Cache benötigt wird, was noch einmal eine Steigerung von zwei Prozent bringen soll.
Weiteres Potenzial zur Performance-Steigerung sollen die Scalable Vector Extensions, kurz SVE, ermöglichen. Da RPCS3 intensiv Vektoroperationen nutzt, sind entsprechende Arm-Erweiterungen für den Emulator besonders interessant. Whatcookie nutzt dafür spezifische SVE-Instruktionen mit einer Vektorlänge von 128 Bit, um weitere Abläufe effizienter auszuführen. In einer einfachen Schleife mit zahlreichen Multiplikationen wurde dadurch ein weiterer Performance-Zuwachs von rund zehn Prozent beobachtet.
RPCS3 auf Armmacht großen Schritt
Am Ende laufen die vielen kleinen Optimierungen in einer großen Leistungssteigerung zusammen, die laut dem Entwickler in Abhängigkeit von Spiel, Hardware und Workload bis zu 60 Prozent betragen kann. Gleichzeitig soll damit eine reduzierte Leistungsaufnahme von bis zu 25 Prozent einhergehen. Das bedeutet nicht nur einen geringeren Stromverbrauch und damit längere Laufzeiten, sondern auch potenziell weniger Abwärme und damit eine einfachere Kühlung.
Gleichzeitig zeigen die genannten Beispiele, dass ein erheblicher Teil des bisherigen Leistungsnachteils von RPCS3 auf Arm nicht zwangsläufig durch die Architektur selbst verursacht wurde, sondern auf unvollständige oder nicht optimal an Arm angepasste Implementierungen zurückzuführen sind. Durch die Korrektur dieser Fehler sowie neue, gezielt für Arm entwickelte Optimierungen kann die Plattform deutlich näher an die ausgereifte x86-Version heranrücken.