Wie viel Assembler wird in modernen Spielecodes wirklich verwendet? [geschlossen]

21

Wie oft wird Assemblierung im modernen Spielcode im Durchschnitt verwendet?

Insbesondere auf Plattformen, die bereits über gute C ++ - Compiler wie x86, PPC oder ARM verfügen, da Spiele auf eingebetteten Systemen in großem Umfang von Assembly Gebrauch machen.

Legion
quelle
4
C ++ kompiliert nicht zu Assembly - es kompiliert zu Maschinencode. Mit der Assemblersprache können Sie direkt angeben, welcher Maschinencode generiert werden soll.
Kylotan,
6
C ++ wird (im Allgemeinen) nicht in Assembly kompiliert, sondern direkt in Maschinencode kompiliert. Die Frage bezieht sich wahrscheinlich darauf, wie viel handgeschriebene Assembly in ein Projekt eingebunden oder als Inline-Assembly geschrieben ist.
Josh
1
Ungeachtet dessen glaube ich nicht, dass es eine praktische und nützliche Antwort auf diese Frage gibt. Es hängt im Wesentlichen von einer Reihe von Faktoren ab, von denen viele subjektiv sind (dh die Meinungen der Autoren des Codes).
Josh
1
Heutzutage
4
@Legion - Sie können bewirken, dass der Compiler / die IDE eine Assembly ausgibt. Dies bedeutet jedoch nicht, dass der Compiler eine Assembly als Teil eines normalen Kompilierungsprozesses erstellt. Dies ist nicht erforderlich, und die meisten tun dies auch nicht.
Josh

Antworten:

29

Die Antwort hängt ein wenig davon ab, was Sie mit "Spiel" und "verwendet" meinen. Ich gehe davon aus, dass "used" bedeutet "geschrieben im Laufe des spezifischen Spielprojekts".

Nach meinen Erfahrungen und anekdotischen Daten von Personen, mit denen ich gesprochen habe:

  • in browserbasierten Spielen? Keiner.
  • in typischen PC-Spielen? Keiner. (Einige davon sehen Sie möglicherweise in Bibliotheken auf niedriger Ebene.)
  • in iOS- und Android-Spielen? Keiner.
  • "AAA" PC- und Konsolenspiele? Vielleicht ein bisschen, vielleicht 0,05% der Codebasis. (Mit ein bisschen mehr in den Bibliotheken.)

Assembler-Kenntnisse werden für die Arbeit in der Spielebranche nicht erwartet, sind jedoch abhängig von der Art der von Ihnen erstellten Spiele möglicherweise von Vorteil.

Früher gab es ein Argument dafür, dass der Compiler C-Code besser optimiert als ein Mensch mit handgeschriebener Assembly. Normalerweise ist das wahr, manchmal ist es falsch. Aber heutzutage bedeutet eine Kombination aus ständig wachsender CPU-Komplexität und dem Erfordernis des Skalierens (dh des Separierens von Prozessoren), dass Optimierungsbemühungen normalerweise an anderer Stelle durchgeführt werden.

In den letzten Jahren war das einzige Mal, dass ich Assembler im Spielcode gesehen habe, __asm int 3Anweisungen zum Erzwingen von Haltepunkten, und meine einzige persönliche Verwendung des Assemblers bestand darin, die Disassemblierung einer Funktion zur Diagnose ungewöhnlicher Absturzfehler zu untersuchen.

Kylotan
quelle
1
Was ist mit SSE-Anweisungen?
Legion
4
@Legion, Leute schreiben normalerweise SSE-Code entweder mit Intrinsics oder mit mathematischen Bibliotheken, die das SSE-Zeug umschließen , oder in einer speziellen Minisprache, die speziell für die Kompilierung mit SSE entwickelt wurde, wie zum Beispiel ispc . Assembler direkt zu schreiben ist noch ziemlich selten.
Nathan Reed
1
In Bezug auf iOS-Spiele: Wenn ich mich recht erinnere, verwendete die 3D / Math-Bibliothek Oolong eine Inline-ARM-Assembly. Dies wird nicht mehr benötigt, seit Apple das Accelerate-Framework veröffentlicht hat.
Nicolas Miari
Mit Nathan - SSE vereinbarte und ähnliche anweisungsspezifische Optimierungen existieren normalerweise in Bibliotheken (da dies normalerweise die einzigen Stellen sind, an denen der erzielte Gesamtnutzen den Aufwand wert ist).
Kylotan,
26

Der Großteil des Hochleistungscodes in modernen Konsolenspielen basiert auf einer Art Mittelweg zwischen Assembly und C ++: Compiler-Eigenheiten . Diese Konstrukte sehen aus und analysieren sie wie C ++ - Funktionen, werden jedoch tatsächlich in Einzelmaschinenanweisungen übersetzt . So sieht beispielsweise meine Funktion "Klemme jeden Wert des Vektors V auf> = a und <= b" aus

// for each v.x, ensure v.x >= a.x && v.x <= b.x
inline __m128 ClampSIMD( const __m128 &v, const __m128 & a, const __m128 & b )
{
    return _mm_max_ps( a, _mm_min_ps( v, b ) );
}

Bei Funktionen wie diesen denke ich immer noch an die spezifischen Maschinenanweisungen , aber ich habe die Möglichkeit, sie in C zu schreiben, damit ich mich nicht um das Ausmalen und Planen von Registern und das Laden von Operationen und anderen langweiligen Details kümmern muss.

Sie müssen sich immer noch darüber im Klaren sein, welche Anweisungen die CPU unterstützt, insbesondere weil moderne Compiler Code schlecht vektorisieren können, verglichen mit der Leistungsfähigkeit eines intelligenten Menschen. Manchmal können auch subtile Details, wie Sie Ihren Code anordnen , enorme Auswirkungen auf die Leistung haben , die nicht offensichtlich sind, ohne zu verstehen, was der Computer tut.

Obwohl wir in der Assembly möglicherweise nicht programmieren, debuggen wir in der Assembly noch häufig. Durch die Optimierung von Compilern wird Code aggressiv in einer Weise reorganisiert, mit der Debugger nicht Schritt halten können. Beim Debuggen eines Builds im "Release-Modus" empfiehlt es sich daher, den Disassembler zu öffnen und den Code auf diese Weise zu durchsuchen. Dieser GDC-Vortrag zum "Forensic Debugging" von Abstürzen zeigt viele der Gründe und Gründe für das Debuggen auf dieser Ebene.

Crashworks
quelle
3
+1 einfach, weil Crashworks auf SO als "der Typ bekannt ist, der wirklich optimierten Code für Spiele auf niedriger Ebene schreibt" - wenn jemand etwas über dieses Thema weiß, ist er es.
BlueRaja - Danny Pflughoeft
@ BlueRaja-DannyPflughoeft "Bekannt"? Ich bin geschmeichelt! =) Ein amüsanter Zufall im Lichte von Nathan Reeds Kommentaren ist, dass ich viele meiner geringen Optimierungsfähigkeiten bei Naughty Dog gelernt habe.
Crashworks
An anderer Stelle habe ich auch die Bedeutung der Assembly beim Debuggen gehört. Also werde ich es lernen. Danke für den Einblick und die Links.
Legion
7

Die Probleme, die früher eine handgerollte Montage erforderten, werden immer geringer. Was Sie an Geschwindigkeit "gewinnen" könnten, verlieren Sie an Lesbarkeit und Debug-Fähigkeit. Es sollte auch nur als einer der letzten Optimierungsschritte für Codeabschnitte ausgeführt werden, da Geschwindigkeitsprobleme in den meisten Fällen nicht mit der Assembly verbessert werden können. Heutzutage sind die CPUs viel schneller geworden als die Speichergeschwindigkeiten. Oft ist es wichtiger als alles andere, den Datenfluss durch die CPU zu steuern.

Bei modernen Compilern fällt es ihnen auch schwer, den Assembler-Code zu optimieren, da sie mit allen Registern umgehen müssen, die Sie berührt haben, und sie können normalerweise keine Anweisungen in Ihrem handgefertigten Code nachbestellen. Um den Montageaufwand zu reduzieren, gibt es jetzt auch Intrinsics, die den Zugang zu Konzepten auf niedriger Ebene erleichtern, jedoch compilerfreundlich sind und es ihnen ermöglichen, mit Ihnen zusammenzuarbeiten, anstatt dagegen zu arbeiten.

Trotzdem ist die SPU auf der PS3 ein Bereich, in dem die Benutzer immer noch die Baugruppe verwenden müssen, um das Beste aus dem Prozessor herauszuholen, beispielsweise mit manuellem Anweisungs-Pipelining, wie hier erläutert .

Roger Perkins
quelle
1
Sogar auf PS3 programmieren die Leute normalerweise nicht so ganz in Bare Assembly. Es gibt ein Tool, mit dem Sie Code in Assembly-ähnlicher Syntax schreiben können, in dem Sie die Maschinenanweisungen angeben, aber die Registerzuweisung, die Befehlsplanung und das Loop-Pipelining für Sie ausführen. Naughty Dog macht das vielleicht wirklich alles von Hand, aber selbst die meisten PS3-SPU-Entwickler tun dies meiner Erfahrung nach nicht. :)
Nathan Reed
1
@ NathanReed In den PS2-Tagen war manuelles Loop-Pipelining tatsächlich Teil des Naughty Dog-Programmiererinterviews.
Crashworks
-1

Tatsache ist, dass wir in einer Welt mit mehreren Plattformen leben und Teile unseres Spielcodes auf die lokale Plattform zugeschnitten sein müssen - und nicht, aber es gibt Vorteile, wenn wir lokale Hardware nutzen!

Es geht nicht um Spiele oder Spielelogik, es geht um die Hardware-Lokalität für eine optimale Leistung des Codes, von der die Spielelogik abhängt. Wir können in der Tat Codeabschnitte umbrechen, zum Beispiel mit Hilfe von Makros, so dass es einen Quellcode gibt, der auf der gut ausgeführt wird Plattform, gegen die es gebaut wurde.

Homer
quelle