Wie viele Prozessorkerne kann Unity nutzen?

6 Antworten

Hängt davon ab wie nebenläufig dein Programm ist denke ich.

Das ist üblicherweise der Hauptgrund Wieviele Kerne benutzt werden.

Ein Thread kann pro Kern laufen. Wenn dein komplettes Programm sequentiell ist. Sprich in einem Thread abläuft wird auch nur einer genutzt.

Wie neben läufig die engine selbst ist weiss ich nicht.

Würde ich einfach Mal ausprobieren.

Einfach Mal über verschiedene Wege nen busy wait einbauen. Also das deine Methoden Mal für 2-3 Sekunden oder mehr beschäftigt sind. Und schauen Wieviele ich davon gleichzeitig laufen lassen kann.

Dann weisste auch wo die nebenläufigkeit in dem System ist. Und wo du selbst ggf. Nebenläufige Prozesse starten musst.

Z.b. nur Mal aus Spass an der Freude:

Bau ein Ding das sich im Kreise bewegt und immer mit ein Objekt kollidiert.

Bei jeder Kollision schiesste ein busy wait los. Das ne ganze Weile läuft. Und dann schauste was da passiert.

Toastbrot375, der ersteller dieses Themas, hat gefragt wie es in Unity aussieht! Die Antworten sollten sich also entweder direkt auf Unity beziehen, oder zumindest von Leuten geschrieben werden die auch selber Multithreading programmieren können und somit wirklich wissen wovon sie schreiben! Was ich hier lese, sind alles nur bestenfalls Fünftelwissen (also nichtmal Halbwissen) was hier geantwortet wurde ;-/

Also, Grundsätzlich mal:
1.) Ein halbwegs moderner Rechner (Intel/AMD Prozessoren jünger ca. 10 Jahre, alles ab Windwos 7 bzw. ähnlich alte Linux und Mac Rechner, inkl Bios etc.), können prinzipiel problemlos 64 Threads pro Programm und mindestens 16 Kerne und mehr handhaben.
2.) Als Programmierer programmiert man nicht auf Kerne, sondern man programmiert Threads! Ausnahme ist wenn man in Assembler programmiert. Denn dann programmiert man so extrem Hardware nah, das man praktisch mit dem Prozessor knutscht! Seit ca. der Zeit von DirectX 7 (rund seit 15 bis 20 Jahren) macht man das allerdings in der Spieleprogrammierung nicht mehr, weil es so derart viele Multimedia Befehle in den Prozessoren gibt, das eine moderne Programmiersprache ganz automatisch viel besser optimiert, als man es als Assembler Programmierer kann. Überhaupt wird Heutzutage nurnoch Assembler bei sehr sehr Hardware nahen Dingen verwenden (z.B. Treiber), doch selbst in diesen Bereichen wurde Assembler inzwischen von C fast komplett abgelöst.

Bezüglich Multithreading sind die limitierenden Faktoren Heutzutage 2 Dinge:
A) der im Rechner/Laptop/Tablet/Handy verbaute Prozessor.
(z.b. ein 4 Kern Prozessor, kann Physikalisch natürlich nur 4 echte Kerne laufen haben). Wenn das Programm auf mehr Kerne (genau genommen Threads) programmiert wurde, dann hat das aber praktisch keine negativen Auswirkungen. Der Prozessor wird intern einfach die vorhandenen Kerne, entsprechend 'mehrfach füttern'.

B) Wie der Programmierer sein Programm programmiert hat.
Hier ist das Problem, das man als Programmierer überhaupt ersteinmal Sinnvoll sein Programm auf Teil-Themen aufteilen muss, um dann aus jedem Teil-Thema ein extra laufenden Thrad zu machen. Zudem wird es mit mehr Threads, ganz schnell um ein vielfaches Komplizierter zu programmieren.

Nun speziell zur Spieleprogrammierung:
Ein Spiel lässt sich meistens nur auf wenige Threads Sinnvoll aufteilen. Ganz einfach weil bei einem Spiel nicht massenhaft über gleichartige Daten die gleichen Befehle laufen, sondern weil ein Spiel aus vielen verschiedenartigen Daten besteht über die ganz unterschiedliche Berechnungen laufen und diese Dinge wiederum voneinander abhängig sind (NPC A bewegt sich zu Position X, NPC B verfolgt NPC A und alles muss im selben Frame auf dem Bildschirm dargestellt werden).
Der größte Teil der Daten die sich in einem Spiel per Multithreading abarbeiten lassen, sind Grafik berechnungen (Licht/Schatten etc.) und das macht die Grafikkarte und diese ist intern extrem darauf optimiert. Als Spieleprogrammierer kümmert man sich also um DIESES Multithreading garnicht. Das nimmt einen perfekt die Grafikarte und die Engine ab.
Was man als Spieleprogrammierer Multithreaden kann, ist z.B. Gegner-KI, oder Spieler-Assistenten-KI (das wäre z.B. in einem Strategiespiel, die Steuerung der einzelnen Soldaten der eigenen Armee), Wegfindung der Spielfiguren (bester Weg von Position A zu Position B finden), oder Dinge die praktisch ganz vom restlichen Spiel unabhängig sind (automatisch im Hintergrund sich dynamisch änderndes Wetter, EMail an den Spieler schicken weil der sein Login-PW vergessen hat und per Mail ein neues anfordert).
Es finden sich oftmals also kaum mehr als ca. 4 verschieden Dinge, die man Sinvoll in einen eigenen Thread berechnen lassen könnte. Daher wird in der professionellen Spieleprogrammierung, üblicherweise auf 4 Kern Prozessoren hin programmiert. Ja, manchmal werden auch bis zu 6 oder 8 STÄNDIG laufende Threads programmiert. Doch hierbei handelt es sich um Threads die praktisch sowieso 99,99% der Zeit schlafen, und deswegen auch von der CPU ohne Geschwindigkeitsverlust auf einem 4 Kern Prozessor mit laufen können. (Hierunter fällt z.B. auch das Beispiel mit den EMail versenden, oder auch z.B. ein Wetter-System das alle 60 Sekunden mal kurz aufwacht um per Zufallsgenerator das Wetter der nächsten 60 Sekunden bestimmt und dann innerhalb von 3 Sekunden von Regen auf Sonne fadet).
ja, man KÖNNTE z.B. für jeden einzelnen NPC einen eigenen Thread für die Gegner-KI laufen lassen. ABER, jeder dieser Threads würde dann 99% der Zeit nichts tun, und es wäre ein extremer aufwand für den Programmierer, die damit einhergehenden Logiken und Abhängigkeiten, zu überblicken und Fehlerfrei aufeinander abzustimmen. Denn gerade bei einem Spiel, greifen unzählige Zahnräder ständig ineinander und beinflussen sich dauernd gegenseitig und sind voneinander abhängig. ab ca. 4 Threads wird allein der Planungsaufwand und die Fehleranfällig so derart zunehmen (ohne das man performance/Geschwindigleitsvorteile hätte), das es kaum noch Sinnmacht!
Der EINZIGE Grund warum bei der Professionellen Spieleprogrammierung überhaupt z.B. auf 8 DAUERHAFTEN Threads programmiert wird, ist für die Werbung! Aber das ist lachhaft, eben weil der Kern des Spiels dann trotzdem nur auf 2 oder maximal 4 dauerhafte Threads programmiert ist und diese "für die Werbung zusatz Threads" nur Dinge machen die praktisch keine Rechenleistung brauchen, und man genau so gut im "Thread für alle Kleinarbeiten" zusammenfassen könnte.

So nun schrieb ich mehrmals DAUERHAFTE Threads. Was meine ich damit? Bei einem Spiel startet man als Programmierer bei "Levelstart" sozusagen, seine 1 bis 3 Zusatzthreads für die gut Paralelisierbaren Dinge (wie z.B. 1x Wegfindung + 1x NPC KI) und hatt dann zusammen mit seinem Hauptthread, 2 bis 4 Threads ständig am laufen.
Neben diesen Dauer-Threads, startet mann aber ab und zu mal kurz einen Thread der nur für wenige Sekunden existiert. z.B. im Multiplayer Game kann das sein wenn der Spieler eine Kiste (oder die Leiche eines erledigten NPC's/anderen Spielers) öffnet, das dann ein Thread erstellt wird mit der Befehlslogik "Sende an Server das Kiste mit Level X geöffnet wurde -> was ist der Zufallsinhalt der Kiste? -> warte auf Antwort vpm Server -> 0,4 Sekunden später Antwort erhalteb -> Öffne für den Spieler das Fenster mit dem Inventar/Inhalt der Kiste -> Thread ende".
Diese kurzzeitigen Zusatsthreads brauchen braktisch FAST KEINE Prozessorleistung. Man startet sie nur deswegen, weill eine Befehlskette ausgeführt werden soll die evtl. erst in z.B. 0,5 oder 1 oder 2 Sekunden fertig ist, aber in der Zeit soll natürlich das Spiel nicht einfrieren sondern es soll weiter laufen. Diese Kurzzeithreads dienen also nur dazu um Zeitlich etwas zu entkoppeln. SIe brauchen kaum Rechenleistung und im laufe eines Spiels startet (und beendet) man unzählig viele davon. Sie bedeuten keine Zusatzbelastung für den Prozessor, und deswegen spielen sie keine wirkliche Rolle was das angeht. Was relevant ist, sind die DAUERHAFT paralel laufenden Threads die ständig auch VIEL ARBEIT erledigen. Und von denen hat man in einem Spiel schlicht nur 2 bis maximal 4!

Speziell zu Unity3D.
Alles was man in Unity in IRGENDEINEM MonoBehaviour Update() laufen lässt, wird im Hauptthrad ausgeführt. Das ist auch absolut Sinvvol so, denn praktisch alles was man hier programmieren würde, wäre sowieso so eng mit den anderen Objecten und Dingen verbunden bzw. von deren Zustand abhängig, das man sie sowieso nicht paralel ablaufen lassen könnte.
Alles was im LateUpdate() abläuft, wird von Unity in einem ANDEREN Thread ausgeführt. ABER erst nachdem der LETZTE Update() im aktuellen Frame fertig ist. Es wird also garantiert, das LateUpdate() immer erst NACH Update() ausgeführt wird. Deswegen sollte man LateUpdate() nur für wenige Dinge verwenden. Jedoch sind beide Update-Typen, in eigenständigen Threads und diese wiederum zu großen Teilen unabhängig vom Rest. Und beide Typen werden pro Frame 1x ausgeführt.
LateUpdate() Ist somit also Sinnvoll für Grafische Sachen, die aber NACH den normalen Grafischen Sachen erst passieren sollen. z.B. eine Kamera die etwas verfolgt, oder das Rad eines Autos, das egal wie/wohin sich das Auto bewegt, am ende des Frames immer "runter gedrückt wird so dass das Rad den Boden berührt".
FixedUpdate() wird ebenfalls in einem eigenständigen Thread ausgeführt und ist darüber hinaus auch total entkoppelt und unabhängig von Update() und LateUpdate(). Jedoch ist FixedUpdate() unabhängig von der Framerate!!!! Das bedeutet, FixedUpdate() eignet sich NICHT für Grafische Sachen! FixedUpdate() wird von Unity als sehr "Zeitkritisch" betrachtet. Bedeutet das Unity extrem darauf achtet, das FixedUpdate() ganz pünktlich und genau auch x mal pro Sekunde ausgeführt wird. Notfalls würde Unity auch die Framerate runter regeln etc. um die FixedUpdate() Rate konstant zu halten! Bedeutet, FixedUpdate() eignet sich nur für die wenigen Dinge die sehr Zeitkritisch und 'Pünktlich' laufen müssen. Also hauptsächlich für ein paar ganz bestimmte Physik berechnungen. Jedoch ist sogar das meiste Physik Zeug so Zeitunkritisch, das es evtl. Sinnvoller im normalen Update laufen könnte.

Hier haben wir also schon 3 Threads/Kerne die Unity ganz automatisch bedient.

Neben diesen Update-Typen, hat Unity intern seine Physik-Engine laufen, die sogar automatisch sich auf mehrere weitere Threads verteilt, also selber sich sehr hoch optimiert! Als Programmierer muss man lediglich darauf achten, von ALLEN Objekten die in irgendeiner Art sich bewegen, den RigidBody richtig einzustellen! Jedoch nicht für das Multithreading, sondern um der Physik-Engine zu sagen welches verhalten das Objekt hat, und somit die Physik-Engine alles andere dann automatisch optimieren kann.
Dazu kommt dann nochmal automatisch ein Thread für Sound verwaltung, und bei Sounds die länger als ca. 1 Sekunde laufen (und/oder komprimiert auf der Festplatte oder im Arbeitsspeicher liegen) startet Unity automatisch einen eigenständigen (kurzzeit) Thread zum enpacken bzw. zum abspielen des Sounds. So wird z.B. eine 3 Minuten lang laufende Musik im Hintergrund, automatisch von Unity in einen extra Thread ausgelagert. Ganz ohne das man als Programmierer was dafür machen muss.

Für Netzwerksachen hat Unity ebenfalls einen eigenen Thread laufen. Alle Funktionen die man als Programmierer für das Netzwerk ausführt, sind alle ein "Schiebe diesen Befehl in den Netzwerk Thread". Man füttert also vom Hauptthrad aus, nur sozusagen den Netzwerkthread bzw. holt vom Netzwerkthread die fertigen Daten ab.

Am ende aller Update-Funktionen, (aber wiederum paralel zum Netzwerk und Sound Thread) hat dan Unity seinen eigenständigen Grafik-Thread mit dem es die Grafikkarte füttert.

Und für bewegungen die man an Objekten macht die keinen Parent haben (also in der Szenen Root liegen), macht Unity auch automatisch Multithreading.

'Grafikkarte' und Shader laufen dann auch nochmals komplett unabhängig und werden lediglich sozusagen jeden Frame mal mit neuen Anweisungen versorgt, läuft aber zwischen den Frames parallel zum ganzen Rest.

Somit hat man also ganz automatisch in Unity schonmal seinen Code auf MINDESTENS 6 dauerhaften Threads am laufen, plus evtl. viele weitere die Unity intern automatisch startet.

Aktiv als Programmierer, hat man aber bis hierhin eigentlich 'nur' einen Thread programmiert. Obwohl man also noch nichts für Multithreading gemacht hat. Wieviele Threads hat man nun also 'programmiert'? Meiner bescheidenen Ansicht nach, 'nur einen'. Denn man hat bis zu diesem Punkt, ja 'sein Game' noch nicht aufgeteilt auf verschieden Spiel-Komponenten die man als Programmierer paralel steuert. Erst hier würde mann also nun ZUSÄTZLICH als Programmierer anfangen mit Multithreading und z.B. Wegfindung und NPC-KI auf 2 zusätzliche Threads aufteilen.

Zusammengefasst:
Mit Unity wird sehr vieles automatisch auf einige Threads (und dadurch auf 'beliebig viele echte CPU Kerne') aufgeteilt. Trotzdem hängt es am Programmierer was er daraus macht.... ein Spiel das keine hunderte KI Figuren hat, und/oder nur auf einer eher kleinen Map läuft, da kann man als Programmierer auch einfach seinen ganzen COde in einen einzigen Thread (dem Hauptthread) schreiben. Will man viel Gegner KI oder braucht man viel komplizierte Wegfindung, dann lohnt es sich aber noch 1, 2 oder vielleicht auch 3 extra Threads dafür zu schreiben. Prinzipiell kann man sein Spiel auch auf so viele Threads aufteilen wie man will.... Es wird aber sehr sehr schnell der Punkt kommen, wo man es nicht mehr weiter aufteilen kann -> weil es nur eine begrenzte Anzahl von UNABHÄNGIG abarbeitbaren Teile gibt auf die man das Spiel aufteilen kann .. und weil es sehr schnell extrem kompliziert werden kann, wegen der vielen abhängigkeiten wo diese Teile dann doch wieder ineinander übergreifen.

Wegen dem Gerücht das 'dieses oder jenes Spiel oder Engine nur auf 1 Kern läuft': Keine Ahnung woher das immer wieder mal kommt. Wenn ein Spiel nur auf einen einzigen Kern läft, dann entweder weil es eine sehr alte Engine ist die wirklich noch dieses Limit hatte, oder weil der Programmierer sich nicht die Mühe gemacht hat für Multithreading (wenn wenig Wegfindung gebraucht wird und nur wenige KI Figuren gleichzeitig handeln, braucht es das oft garnicht) oder wenn es ein Browsergame ist... Denn Webbrowser (ALLE! egal ober z.B. Google Crome, Firefox etc.) erlauben es einem Browsergame nur das es in einem einzigen Thread ausgeführt wird! Multithreading in einem Browsergame ist mit der Heutigen Technik nicht möglich! Jede Engine, egal wie sie ansonsten intern Multithreading macht (also auch das was ich oben über Unity geschrieben habe), macht dies nur solange wie das Spiel für Windows/Mac/Linux, Tablet, iPhone oder Android erstellt wird. In dem Moment wo man das Spiel für Webbrowser erstellen lässt, werden ALLE internen Multithreading Sachen, in einen einzigen Thread gepackt. Nix mit Multithreading! Und als Programmierer darf mann dann entweder garnicht Code per Hand für Multithreading schreiben (Fehlermeldung wenn man dann das Game für Browser erstellen läst) oder die Engine wird (ohne das man es merkt) den entsprechenden Code 'rausfiltern' und ersetzen durch alternativen 'Simulations-Code', der aber dann alles in einem einzigen Thread NACHEINANDER ablaufen lässt -> Wodurch es anstatt schneller, nur noch langsamer wird!

Woher ich das weiß:Berufserfahrung
simoncaspar  13.06.2020, 10:26

Das ist aber ziemlich viel. Danke, werde ich mir merken.

2

Die Kernanzahl bestimmt nicht das Spiel sondern dein Bios. Das Bios ist eine Art Überprogramm: Sprich über deinem Windows. Wenn du ein Spiel spiels, merkt das Bios, wie viele Kerne das Spiel benötigt um optimal zu laufen. Folglich „benutzt“ Unity und alle anderen Spieleanbieter bzw. die Spiele selber alle deine Kerne ;)

Woher ich das weiß:Hobby
Toastbrot375 
Fragesteller
 16.03.2020, 20:17

Aber die meisten Spiele nutzen nur max. 6 Kerne und diev meisten anderen programme auch nur max. 16 Kerne auch wenn man z.b. einen 64kerner Threadripper hat.

Danke für deine Antwort

0
jort93  16.03.2020, 20:18

Nicht unbedingt. Wenn du ein strikt linearen Programm Ablauf hast ohne irgendwelches threading dann wird das Programm auch auf nur einem Kern laufen.

Du musst das Programm schon gewusst so schreiben dass du mehrere Kerne nutzt.

0

die Anzahl der Kerne wird im Spiel/Betriebssystem selbst festgelegt .

Wenn ein Programm z.B. 6 Kerne anfordert ,dann weist das OS 6 Kerne dem Programm zu. Hat man 8 Kerne und 6 werden für ein Programm genutzt werden die restlichen 2 Kerne mit den anderen noch Übriggebliebenen Kernen Belastet.

Es macht auch hier wenig Sinn wenn man 8 Kerne hat a,dann alle 8 dem Programm zuzuweisen weil man selbst noch das OS laufen hat das auch verwaltet werden muss. Auch in Zeiten wo Programme sich die Leistung "Sharen"

Deswegen wenn man 8 Kerne hat und 7 einem Spiel zuweist ,wäre das die bessere Wahl.

Die Anzahl der Kerne kann jedes Programm ( egal ob unter Linux / Windows oder anderes OS ) auslesen und so auch seine Anforderungen daran anpassen. die meistne Programmierer bzw. Entwickler von z.B. Spielen nutzen meist eine art Compiler weil sie in einer anderen Programmiersprache schreiben oder weil sie auf anderen Plattformen entwickeln . Dort sind sie oft schlichtweg zu faul solche Routinen mal sauber auszuarbeiten und auch korrekt einzusezten.

Woher ich das weiß:Berufserfahrung

lass doch den taskmanager imhintergrund laufen dann kannst du sehen wie ausgelastet die kerne sind.

Und... welcher programmierer steuert denn die Kerne direkt an, das wäre illusorisch, dann müsste ich ja für jeden cpu was anderes programmieren. der c-compiler wird die aufgabenverteilung übernehmen. man kann diese verteilung nur rudimentär beeinflussen.