Multi-Plattform-Multi-Threading: Was sind die wirklichen Herausforderungen?

21

Während eine Bibliothek wie SDL eine plattformübergreifende Wrapper-API für das Threading bereitstellt, wäre es meiner Meinung nach naiv anzunehmen, dass dies direkt zur einfachen Entwicklung von Spielen auf sehr unterschiedlichen Plattformen (Desktop / Mobile) führt.

Was ist der beste Weg, um die Entwicklung auf diese Weise anzugehen (unter Berücksichtigung einer plattformübergreifenden Threading-API), wenn Folgendes berücksichtigt wird:

  • unterschiedliche Anzahl von Kernen
  • Sehr unterschiedliche Verarbeitungsmöglichkeiten pro Kern
  • Eine generell andere Systemarchitektur mit z. Unterschiedliche Latenzen für Cache, RAM und E / A-Zugriff

Ich habe das Gefühl, dass der einzige Weg, dies zu tun, darin besteht, zu bewerten, wie viele Threads pro Gerät ausgeführt werden können, das Sie unterstützen möchten, und herauszufinden, welcher der kleinste gemeinsame Nenner ist. Dies lässt mich jedoch immer noch im Dunkeln, was den gesamten verfügbaren Verarbeitungsdurchsatz angeht. Habe ich Recht, wenn ich davon ausgehe, dass der einzige Weg, dies effektiv zu tun, darin besteht, aktiv für das niedrigste mobile Gerät zu entwickeln, das ich während der gesamten Entwicklung unterstützen möchte? - dh der kleinste gemeinsame Nenner? Sollte dies ungefähr ausreichen? Oder steckt noch mehr dahinter?

BEARBEITEN: Könnten andere bitte weitere Erfahrungen dazu machen, da ich der Meinung bin, dass meine Frage noch nicht vollständig beantwortet wurde.

Ingenieur
quelle
Da meine Antwort Ihre Frage nicht vollständig beantwortet, können Sie angeben, was fehlt / was Sie wissen möchten? Ich bin vielleicht kein großartiger Schriftsteller, aber ich habe diese Art von Problem mehr als einmal behandelt.
Valmond
Sie haben die Frage nicht wirklich beantwortet, in der es um Multithreading-Schwierigkeiten und deren Behebung bei der Entwicklung für Plattformen mit unterschiedlichen Threading- Fähigkeiten ging. Siehe meinen Absatz unter den Aufzählungspunkten. Sie sprechen über Bildschirmgrößen und Auflösungen - diese haben nichts mit meiner Frage zu tun - lesen Sie den Titel.
Ingenieur
1
Ich denke, die Schwierigkeit kommt von dem, wofür Sie die Threads verwenden möchten. Es ist eine Sache, dass ein Hilfsthread etwas auf der Seite tut, und eine ganz andere, um zu versuchen, die letzten Leistungsmerkmale eines 8-Core-Rechners zusammenzudrücken. So wie ich das sehe, sind die SDL-Threads hauptsächlich für den ersten gedacht. nicht das letztere.
Jari Komppa

Antworten:

11

Sie sprechen von "Multithreading-Schwierigkeiten", aber über welche Schwierigkeiten sprechen Sie tatsächlich? In gewisser Weise zitieren Sie ein Phantomproblem, das möglicherweise gar nicht existiert. Die eigentliche Herausforderung stellen Sie sich selbst - wenn Sie absolut entschlossen sind, den letzten Tropfen der Energie aus einem Stück Hardware herauszuholen, bedeutet dies, dass Sie die Hardware optimal einsetzen, aber auch die Kluft zwischen den leistungsstärksten Maschinen vergrößern und der am wenigsten mächtige. Dies hat zur Folge, dass Sie, wenn Sie ein Spiel haben, das wirklich das Beste aus einer PS3 macht (zum Beispiel), es sowieso nicht auf einem billigen Mobiltelefon laufen lassen können, sodass Ihr Problem nicht mehr darin besteht, wie ich 1 Programm bekommen kann auf sehr unterschiedlicher Hardware arbeiten "wird aber" wie kann ich 1 Spielidee auf verschiedene Arten umsetzen, damit es auf unterschiedlich starker Hardware funktioniert ".

Während eine Bibliothek wie SDL eine plattformübergreifende Wrapper-API für das Threading bereitstellt, wäre es meiner Meinung nach naiv anzunehmen, dass dies direkt zur einfachen Entwicklung von Spielen auf sehr unterschiedlichen Plattformen (Desktop / Mobile) führt.

Einfache Entwicklung von Spielen - klar. Optimales Multithreading, nein. Aber Sie müssen nicht brauchen Multithreading - Spiele zu machen. Um Hochleistungsprodukte herzustellen, ist es sicherlich hilfreich. Aber viele großartige Spiele laufen in einem einzigen Thread.

Was ist der beste Weg, um die Entwicklung auf diese Weise anzugehen (unter Berücksichtigung einer plattformübergreifenden Threading-API), wenn Folgendes berücksichtigt wird:

  • unterschiedliche Anzahl von Kernen
  • Sehr unterschiedliche Verarbeitungsmöglichkeiten pro Kern
  • Eine generell andere Systemarchitektur mit z. Unterschiedliche Latenzen für Cache, RAM und E / A-Zugriff

Anstatt zu versuchen, Systeme Threads zuzuweisen, weisen Sie Threads Tasks zu. Weisen Sie jeder Aufgabe die Daten zu, die sie zum Ausführen benötigt, und führen Sie die Aufgaben auf der jeweils verfügbaren Hardware aus. Normalerweise haben Sie eine Art Thread-Pool, um die verschiedenen Kerne oder Prozessoren zu abstrahieren, und einen Task-Manager, der eine Reihe von Tasks enthält und diese an die verschiedenen Threads weitergibt, wenn der Thread signalisiert, dass er die vorherige Task beendet hat und beendet ist bereit für einen neuen. Hardware mit mehr Kernen erledigt die Aufgaben offensichtlich schneller und kann schneller gerendert werden. Die Spezialisierung dieses Systems auf ein optimales Arbeiten auf Systemen mit unterschiedlichen Merkmalen wird zu einem fortgeschrittenen Optimierungsproblem, kann jedoch auf bestimmten Heuristiken beruhen (z. B. einer Aufgabe, die nicht erfüllt ist).

Die Zerlegung von Spielfunktionen in einzelne Aufgaben ist jedoch eine recht komplexe Angelegenheit und oft nicht die Mühe wert, es sei denn, Sie sind sich sehr sicher, dass Sie die Leistung benötigen, und die meisten werden es nicht einmal versuchen.

Einige weitere Lektüre:

http://www.gamasutra.com/view/feature/1830/multithreaded_game_engine_.php - siehe Abschnitt 'Daten parallel'. Bei diesem Modell werden die Daten auf mehrere identische Tasks aufgeteilt und auf einzelne Threads verteilt.

http://software.intel.com/de-de/articles/designing-the-framework-of-a-parallel-game-engine/ - ziemlich dicht, beschreibt Dinge auf Betriebssystemebene und nicht auf Spielebene.

http://drdobbs.com/high-performance-computing/216500409 - nicht spielspezifisch, aber absolut relevant für die Aufteilung der Aufgaben.

http://www.itfgaming.com/news/tech-focus-crysis-2-and-the-future-of-cryengine-3 - Auf halbem Weg ist dieses Interview eine Anekdote darüber, wie sie auf ein aufgabenbasiertes System migriert sind .

Kylotan
quelle
Sehr gute Punkte. Und wahr, ich habe das Wort "Schwierigkeiten" verwendet, wenn "Herausforderungen" genauer wären. Sie sagten: "Die Zerlegung von Spielfunktionen in einzelne Aufgaben ist eine recht komplexe Angelegenheit und oft nicht die Mühe wert, es sei denn, Sie sind sich sehr sicher, dass Sie die Leistung benötigen, und die meisten werden es nicht einmal versuchen." Können Sie das näher erläutern? Quellen angeben? Es ist ein bisschen vage, aber ich würde sagen, Sie kommen dort auf den Punkt.
Ingenieur
Tut mir leid, ich dachte, diese Art von Ansatz wäre bekannt. Ich werde auf die Antwort eingehen.
Kylotan
4

Als ich Handyspiele gemacht habe, haben wir zuerst eine "goldene" Version (dh ein voll funktionsfähiges Spiel) entwickelt und dann in drei Hauptversionen (Großbild, Mittelbild und Kleinbild) aufgeteilt. Diese wurden weiter in 11 Versionen konvertiert: Anspruchsvolle Grafik (Lesen benötigt viel Speicher / CPU) im Vergleich zu Low Profile usw. (es gab auch einige spezielle Plattformversionen).

Das größte Problem war (das war unter anderem meine Aufgabe), die benötigten Plattformen zu isolieren und diese Versionen zu bestimmen und zu ermitteln, wie sie erstellt werden sollen (dh Großbild, aber Low Profile sollte eine herabgestufte Version von Großbild / Hi Profile sein oder sollte es sein) mittelgroßer Bildschirm / großes Bildschirmprofil?).

Natürlich haben wir dies so programmiert, dass Spiele sehr stark von der Bildschirmgröße abhängen.

HTH

[edit] Was ich meinte war, dass Sie Ihre Zielplattformen in verschiedene Qualitäten aufteilen müssen (dh 1 Kern, 2 Kerne, 1 Kern, aber doppelt so schnell ...). Dann entscheiden Sie, wie viele virtuelle Ziele Sie wollen (zum Beispiel " only one "oder" Low, Mid, Hi ") Dann platzieren Sie alle Plattformen in ihrer jeweiligen" Qualität "und nehmen für jede Qualität den niedrigsten Nenner und" portieren "den Code, damit er diesen Anforderungen entspricht (dh funktioniert und schnell ist genug).

Es mag den Anschein haben, dass Sie dies mit ziemlich viel Rätselraten tun müssen, aber Sie können bereits die schlechteste Qualität mit der schlechtesten Plattform finden. Ich würde jede nächste Qualität mindestens "doppelt so gut" wählen wie die erste, dies würde wahrscheinlich nicht mehr als 3-4 "Qualitäten" erzeugen. Wenn der Code von einer Gold-Version portiert ist, kann jede Plattform, die nicht gut genug funktioniert, auf eine niedrigere "Qualität" zurückgesetzt werden, um die Geschwindigkeit zu erhöhen. Jede neue Plattform könnte auch leicht in der richtigen Qualität platziert werden.

Valmond
quelle
Wie viel Overhead-Zeit hatte das Projekt Ihrer Meinung nach sowohl in der Entwurfs- als auch in der Entwicklungsphase, um eine Veröffentlichung auf mehreren Plattformen wie dieser zu ermöglichen? Nur ein grober Durchschnitt würde helfen.
Ingenieur
1
Nun, da wir mehrsprachig waren (Englisch, Französisch, Spanisch, Portugiesisch, Deutsch und Italienisch in einem Paket + welche Sprache auch immer benötigt wird, Taiwanesisch, Türkisch, Russisch ...) und wir neue Plattformen hatten, mussten wir "portieren" Bei all unseren Spielen hätten wir alle paar Monate (lesen Sie eine neue Klasse von Handys) tatsächlich viel Zeit verloren, wenn wir nicht in diese Richtung gegangen wären. Ohne ein wirklich großes Tempo wäre das eigentlich unmöglich gewesen. Das Design des 'Frameworks' wurde auf der Flucht gemacht, als ich etwas über verschiedene Handys lernte und nach etwa 3-4 Jahren zur Reife kam. Eine Investition, die sich lohnt.
Valmond
1

Ich habe das Gefühl, dass der einzige Weg, dies zu tun, darin besteht, zu bewerten, wie viele Threads pro Gerät ausgeführt werden können, das Sie unterstützen möchten, und herauszufinden, welcher der kleinste gemeinsame Nenner ist.

Nicht unbedingt - es besteht möglicherweise die Hoffnung auf eine dynamischere Lösung, dies hängt jedoch von dem tatsächlichen Problem ab, das Sie zu lösen versuchen (falls vorhanden). Ihre Frage ist etwas vage, daher muss meine Antwort auch vage sein.

Wenn die Gruppierung von Plattformen, auf denen Sie ausgeführt werden möchten, die Möglichkeit zur Hardware-Aufzählung über eine API bietet, können Sie über diese Schnittstelle die maximale Anzahl von Threads ermitteln, die das System verarbeiten kann, und auf dieser Grundlage festlegen, wie viele Threads Ihre Anwendung ausführen soll sollte schaffen. Die einzige Herausforderung besteht darin, diese APIs zu finden. Ob Sie zur Betriebssystemebene wechseln oder nach einer Drittanbieter-Bibliothek oder einem plattformübergreifenden SDK / API suchen, liegt bei Ihnen und hängt von den Plattformen ab, die Sie unterstützen möchten.

Was ist der beste Weg, um die Entwicklung auf diese Weise anzugehen (unter Berücksichtigung einer plattformübergreifenden Threading-API), wenn Folgendes berücksichtigt wird:

different numbers of cores
vastly different processing capabilities per core
A generally different systems architecture with eg. different

Latenzen für Cache, RAM und E / A-Zugriff

Meiner Meinung nach sollte keines dieser Dinge Ihr Anliegen sein. Ihr Anliegen sollte es sein, Ihr Spiel aufzubauen. Wenn Sie auf einen Engpass stoßen und entscheiden, dass es besser ist, einen separaten Thread für eine bestimmte prozessorintensive Aufgabe zu erstellen, erstellen Sie den Thread und lassen Sie das Betriebssystem und andere untergeordnete Software entscheiden, wie die Hardware für das Threading bearbeitet werden soll.

Chiffre
quelle