Diskussion zur Peformance und fehlenden Features (Build 6181)

Willkommen in der Transport Fever Community

Wir begrüßen euch in der Fan-Community zu den Spielen Transport Fever und Train Fever, den Wirtschaftssimulatoren von Urban Games. Die Community steht euch kostenlos zur Verfügung damit ihr euch über das Spiel austauschen und informieren könnt. Wir pflegen hier einen freundlichen und sachlichen Umgang untereinander und unser Team steht euch in allen Fragen gerne beiseite.

 

Die Registrierung und Nutzung ist selbstverständlich kostenlos.

 

Wir wünschen euch viel Spaß und hoffen auf rege Beteiligung.

Das Team der Transport-Fever Community


  • ... ganz ehrlich? Ich finde das NICHT richtig! Es kann gut sein, dass es in TF so ist, aber dann ist es eher purer Aktionismus denn wirkliches Multithreading.

    Na ja, wenn man nun aber eine Aufgabe statt von einem von mehreren lösen läßt, ist die erst vollständig erledigt, wenn alle beteiligten fertig sind. Ob man die Kellermauern von einem oder mehreren mauern läßt, die Decke/den Fußboden kann man erst gießen, ich nehme mal Beton, wenn alle mit ihren Mauern fertig sind. Das meinten @eis_os und ich.




    ECHTE Paralellität erreicht man nur durch voneinander UNABHÄNGEN Berechnungen/Aufgaben. Punkt.

    Da hast Du vollkommen recht.
    Aber meistens hat man Abhängigkeiten und es kommt darauf an, wie gut sich ein Problem oder Teilprobleme parallelisieren lassen.



    Sobald die Zielfindung durch ist, aktualisiert sie den Wert (das ist auch noch bissl knifflig OS-intern, aber das soll hier mal aussen vorgelassen werden) und die Wegfindung rechnet plötzlich mit diesem Thread. Beide arbeiten völlig unabhängig voneinander, da muss nix aufs andre warten. Das ist Multithreading

    Also ist dein Beispiel doch nicht ganz unabhängig. Der "Datenaustausch" von Threads hat mit dem OS nichts zu tun. Die Threads laufen im gleichen Prozess und somit im selben Adressraum. Zwei Threads können lesend und schreibend auf ein und denselben Speicher gleichzeitig zugreifen. Hier kommt dann die vom Programmierer korrekt vorzunehmende Synchronisation des Zugriffs ins Spiel, sonst gibt es Datensalat.



    Und richtig echtes Multithreading ist auf nem Computer eh nich wirklich möglich,

    Doch. Wenn ich als Programmierer Threads nutze, interessiert mich die Welt außerhalb meines Programms nicht. Ich weiß, dass ich unter Multitasking-Betriebssystemen wie Windows, OS-X, Linux etc. mit meinem Programm nicht allein auf der Kiste bin. Bei einem Singletasking-System sieht das schon wieder anders aus. Im Embedded-Bereich noch einmal.


    Was die GPU rendert ist völlig losgelöst von der CPU. Allerdings ist für ein dynamisches interagieren halt immer wieder neuer Input von der CPU nötig. Ändert sich die Ansicht werden die Matrizen geändert und neu zur GPU geschickt, muss ein Objekt animiert werden, also seine Position/Ausrichtung/Größe ändert sich, müssen die Daten erneut zur GPU gehn.

    Dein Allerdings zeigt ja, dass die GPU nicht völlig losgelöst von einer höheren Instanz arbeiten kann, die ihr sagt, was zu tun ist. Und darauf bezog ich mich...

  • Da hast Du vollkommen recht.
    Aber meistens hat man Abhängigkeiten und es kommt darauf an, wie gut sich ein Problem oder Teilprobleme parallelisieren lassen.

    Und das predige ich immer, wenn sie alle mal wieder nach MultiCore Support schreien ^^ Es lässt sich schlicht nicht alles paralellisieren. Irgendwann kommt auch der Punkt, wo es eher Nachteilig wird, wenn man den Sheduler mit 1000 Threads zubombt hat er mehr Overhead durchs umverteilen wie das tatsächlich Arbeit verrichtet wird.



    Also ist dein Beispiel doch nicht ganz unabhängig. Der "Datenaustausch" von Threads hat mit dem OS nichts zu tun. Die Threads laufen im gleichen Prozess und somit im selben Adressraum. Zwei Threads können lesend und schreibend auf ein und denselben Speicher gleichzeitig zugreifen. Hier kommt dann die vom Programmierer korrekt vorzunehmende Synchronisation des Zugriffs ins Spiel, sonst gibt es Datensalat.

    Was ich meinte war genau diese Synchronisation, aber hast recht, Threads nutzen ja gemeinsame Prozessressourcen. Man muss halt aufpassen, dass da bei gemeinsamem Zugriff nix schief geht. Und sie sind insofern unabhängig von einander, dass keiner auf den anderen Warten muss. Natürlich dient ihr Tun einem Zweck, sonst wärs ja sinnlos. Aber A muss nicht warten bis B fertig "getut" hat ^^ (ehrlich, mir fehlt der ugly Smiley xD).



    Doch. Wenn ich als Programmierer Threads nutze, interessiert mich die Welt außerhalb meines Programms nicht.

    So war das nicht gemeint. Mir gings ums Sheduling. Der Sheduler unterbricht deinen Thread ob du willst oder nicht. Die Betriebsmittel werden frei gegeben, die Register gesichert und und und. Was du meinst ist die Sicht des Threads - der merkt davon nämlich nichts und denkt, er würde permanent laufen. Was ich meinte ist eben die Tatsache, das er das NICHT tut, die CPU/kern eben NICHT exklusiv hat. Ist sicher eine sehr weit gefasste Aufassung von Multithreading ^^



    Dein Allerdings zeigt ja, dass die GPU nicht völlig losgelöst von einer höheren Instanz arbeiten kann, die ihr sagt, was zu tun ist. Und darauf bezog ich mich...

    Hmm, joa. Wenn die Daten alle bei der GPU sind, dann kann die GPU DIESES Bild unabhängig von der CPU berechnen, dann hörts aber glaube schon auf ^^ Weil das Buffer swappen wird ja im mainloop erzeugt, die Datenaktualisierungen laufen über die CPU (Bewegungen, geänderte Daten zur GPU streamen...) und all das Gelumbsch. Hmm joa, also scheint wirklich nur dieser eine Renderdurchlauf durch die Pipeline zu sein für ein Bild was unabhängig geht, wenn ich so tiefer drüber nachdenk.

  • @DarkMo, ich sehe wir stimmen im Prinzip überein, drücken uns nur unterschiedlich aus.


    Was mich aber immer noch interessiert:
    Gibt es einen Zusammenhang zwischen "hoher FPS" und "langem Ruckler". Warum, weshalb und wie auch immer...


    Monatsruckler 10-11 sec

    Wenn ich keinen Post mit FPS-Angaben übersehen habe, haben wir hier mit 40-50 der eben solchen einen Spitzenreiten...

  • Den Zusammenhang kenne ich da auch nicht, hab mir auch schon den Kopf drüber zerbrochen. Man müsste genau wissen, wass da eigentlich passiert. Beim Jahreswechsel ists ja uU das Autosave, was auf die Platte geschrieben werden muss. Sind auch gerne mal 70mb. Wenn die Platte zudem alt, langsam, voll, defragmentiert... ist, dann ist das sicher auch nicht förderlich, aber da kann dann TF schlicht nix dazu. Zudem gibts noch die Problematik beim Filmen. Der Film muss auch gespeichert werden auf Platte. Ist das dabei die gleiche Platte? Handelt sichs um ne SSD oder HDD? Alles Faktoren die sowas potenzieren können.


    Bei meiner gezeigten Schwer-Erfolg-Map hab ich zum Monatswechsel vllt ne knappe Sekunde Lag. Das wars. Das OS liegt auf der SSD, TF und STEAM aber nur auf der HDD (ist halt kein Spiel, wo es auf Nanosekundn ankommt ^^). Zumal das Game selber ja wahnsinnig gut lädt. Kine nervigen Intros, einfach Zack drin und wenn man das erste mal die Map geladen hat dauern die folgenden Aufrufe nur noch Bruchteile. Bleiben die Daten im Speicher oder so? Durch Steam?


    Ist beim Mod testen jedenfalls sehr sehr angenehm. Und irgendwie kam ich jetzt vom Thema ab ><



    Edit:

    So, der gute OnkelTom alias Sekundenkleber

    Ich schmeiss mich weg, und ich hab mir so einen Kommentar noch verkniffen, weils mich so sehr an ihn erinnert hatte ^^ Fands aber nicht richtig unbegründete Vermutungen zu äussern und habs gelassen. Aber dass ich tatsächlich auch noch recht hatte - lol.

  • Ich schmeiss mich weg, und ich hab mir so einen Kommentar noch verkniffen, weils mich so sehr an ihn erinnert hatte

    Dann wollen wir mal hoffen, dass wir es demnächst früher merken - obwohl:

    Scheint ein Bruder von OnkelTom zu sein...

    Man schaue vier Posts über meinem... 8)

  • @DarkMo, ich sehe wir stimmen im Prinzip überein, drücken uns nur unterschiedlich aus.


    Was mich aber immer noch interessiert:
    Gibt es einen Zusammenhang zwischen "hoher FPS" und "langem Ruckler". Warum, weshalb und wie auch immer...


    Wenn ich keinen Post mit FPS-Angaben übersehen habe, haben wir hier mit 40-50 der eben solchen einen Spitzenreiten...


    Zum Thema CPU Belastung und GPU, es gibt einen Grund für Mantel, Vulkan, DirectX12 usw., einfach gesagt, waren alle bisherigen Konzepte zur GPU hin, single-threaded.


    Umso höher die FPS, umso flüssiger ist der Haupt-Thread.


    Zur veranschaulichen rede ich mal in Ticks, eine feste Zeiteinheit und Haupt und Nebenthread, der für die Wegberechnung.


    Ein Spiel Monat braucht 120 Ticks. Eine Nebenthread für den Monat 130 Ticks. Es fehlen 10 Ticks, also ist die Warte Zeit länger.
    Im Fast Modus brauch der Monat nur noch 90Ticks, nun fehlen uns schon 40 Ticks.


    So wenn jetzt der Monat gebremst wird. Sagen wir die GPU Leistung für den Hauptthread ist der limitierende Faktor:
    Der Hauptthread braucht nun 150 Ticks für einen Monat, am Monatsende haben wir kein Problem, der Nebenthread ist fertig. (Kann man mit ProcessExplorer sehen).



    Andere Probleme:
    CPU Ram Anbindung für die Datenmenge zu schwach.
    Beispiel:
    Nebenthread hat nur 90 Ticks gebraucht,
    120 Ticks Monat ist Fertig.
    Nun kommt der Threadjoin, wir brauchen aber um die Daten zusammenzuführen 5Ticks, das Spiel bleibt trotzdem stehen!



    Mikroruckler:
    Der Hauptthread beschäftigt sich mit Passagieren beim Rendern oder für die Kollisionsabfrage für Passagiere.


    Hoffe das Hilft bei verstehen der Komplexität.

  • Nun kommt der Threadjoin

    Ich versteh immer noch nicht, was du damit ausdrücken willst ^^ Threads laufen paralell, da wird nix gejoinded. Kommunikation läuft über gemeinsame Ressourcen/Variablen dere Zugriff eben geregelt sein muss. Das Schreiben der Werte muss atomar - also nicht unterbrechbar vom Sheduler - sein, gleichzeitiges Schreiben darf nicht passieren (fehlende Aktualisierung) und und und. Aber das hat alles nichts mit einem Zusammenschluss von Threads zu tun.

  • Wenn man eben nicht alles in Werten speichern kann, die atomar bearbeitbar sind (und ganze Graphen/Bäume/etc mit Wegfindungsdaten und Informationen über die Personen sind nicht wirklich atomar bearbeitbar) dann müssen diese Daten am ende irgendwie dem Haupthread übergeben werden.
    Ganz dumm gesagt: Thread 1 nutzt einen Datenblock, der die aktuellen Personen darstellt, Thread 2 berechnet mit einem anderen Datenblock gleichzeitig irgendwelche tollen Sachen für den nächsten Monat. Am Ende des Monats wird evtl ein "Snapshot" der aktuellen Daten erstellt, oder die vom 2. Thread berechneten Daten werden in die Daten des 1. Threads eingefügt.
    Natürlich könnte man auch hier ansetzen und versuchen Optimierungen zu implementieren. Sollten wirklich 2 Datensätze in Nutzung sein, könnte man zB einfach die Pointer vertauschen (bzw anderweitig umtauschen) statt wirklich die einzelnen Daten irgendwie zu übertragen. Oder man versucht den ganzen Quark direkt live zu ändern, und nicht erst am Monatsende, oder, oder oder.... Das hängt aber sehr stark von der aktuellen Implementierung ab und davon, was denn nun genau da alles Berechnet wird, und welche Informationen sonst noch so in den Datenstrukturen stecken.



    Die Erkenntnisse, die wir damals im Bezug auf die Thread gewonnen haben stimmen seit 2014 auch nicht mehr so ganz. Zu anfangs war es noch wirklich so, dass der 2. Thread stur "sein Ding durchgezogen hat", während der erste dann im Zweifelsfall warten musste. Das konnte man sehr leicht durch verändern der Spielgeschwindigkeit (schneller Vorlauf) feststellen. Seit einem der ersten Performance-patches direkt nach dieser Erkenntnis besteht dieser Zusammenhang nicht mehr. Zumindest auf meinem Rechner bricht der zweite Thread (falls er noch nicht fertig ist) so schnell wie möglich ab, wenn der erste Thread am Monatsende angekommen ist. Ein Lag besteht somit immer noch, wenn der zweite eigentlich noch mehr Zeit brauchen würde - aber dieser Lag ist deutlich kürzer als vorher.

  • Kurz und knapp, alle Berechnungen auf X Threads müssen irgendwann wieder zueinanderfinden, sollte die Zeit reichen, ist es flüssig, sonst macht TF eine Gedenkpause.


    Was macht TF Intern und warum es ruckelt


    Nun, diese Analyse ist ja jetzt schon einige Monate alt (28. Dezember) und seither gab es viele Performance updates:



    Build 5068 (January 30)

    • Improved general performance (pathfinding is now computed in a separate thread)
    • Improved “end-of-month” performance (that is e.g. when towns construct new buildings)


    Build 5112 (February 4)

    • Improved general performance


    Build 5541 (March 25)

    • Improved performance: GUI rendering



    Build 5746 (May 22)

    • Improved general performance
    • Improved end of month performance (less / shorter freezes)
    • Improved first view performance
    • Improved GUI rendering and update performance


    Wenn ich mir diese Liste mal so anschaue, könnte ich mir gut vorstellen, dass die Endmonatsberechnungen ganz anders ablaufen als damals. Das Lag damals hatte auch ein ganz anderes Verhalten: Die Freezdauer war entweder abhängig von der Spielgeschwindigkeit oder den Graphikeinstellungen. Heute ist die Dauer nicht mehr damit korreliert.


    @eis_os mal eine ganz generelle Frage: Wie hast du die Debug informationen damals erhalten? Würde das gerne auch mal versuchen (Linuxlösung wäre mir sympathisch).


    Gruss chrigulix



  • @Xanos mit atomar sind Operationen, nicht Daten gemeint. Also das Speichern von Daten, nicht die Daten selber. Es geht um folgendes, hier sehr schön beschrieben: http://www.ijon.de/comp/tutorials/threads/synchro.html - man muss halt ermöglichen, dass eben so eine Aktualisierung auch mehrerer Daten bzw Operationen in einem Rutsch durchlaufen kann. In dem Bsp setzt er die Variable (überschreibt sie) und versucht sie dann auszugeben (lesen). Das passiert alles in einem Rutsch hintereinander weg, aber das OS, dessen Sheduler kann das halt unterbrechen. Die Prozessorzeit für den Thread ist bspw abgelaufen, nun ist erstmal ein anderer dran. Nun hat er halt den Stern geschrieben, kam aber noch nicht zur ausgabe. In der Zwischenzeit kommt der andere Thread an die CPU und setzt das Minus, kann vllt gleich noch das minus ausgeben. Nun kommt wieder der Sternthread auf die CPU und macht seine Ausgabe - auch ein Minus, obwohl er den Stern geschrieben hatte. Um das zu verhindern wird eben der Zugriff für andere gesperrt. Ich glaube das ist noch NICHT atomar. Also der vom Mutex gesicherte kritische Bereich kann dennoch vom Sheduler unterbrochen werden, aber dieses Un/Set-Lock vom Mutex das MUSS atomar sein, darf nicht unterbrechbar sein. Das sind dann irgendwelche tiefen hochexklusiven OS-Operationen ^^


    Man, die Vorlesung is doch noch garnich sooo lange her >< Wenn man sich ned aktiv damit beschäftigt ist das echt schneller weg wie man denkt lol.

  • Ich versteh immer noch nicht, was du damit ausdrücken willst

    Ein Thread-Join ist eine Funktion in Thread-Bibliotheken, mit deren Hilfe ein Thread auf einen anderen wartet, bis dieser seine Arbeit erledigt hat.


    Beispiel Bildbearbeitungsfilter:
    Bild wird in vier gleichgroße Bereiche geteilt und jeder Bereich wird von einem Thread verarbeitet.
    Da mit fast absoluter Sicherheit nicht alle vier zur selben Zeit fertig werden (s. deine Ausführung zu OS und vielen anderen Threads, die auch noch ab und zu auf eine CPU möchten - aber auch anhand von Daten und Algorithmus), müssen sich die vier unabhängigen Threads nach getaner Arbeit wieder Treffen. Erst wenn sich alle vier an dem Treffpunkt eingefunden haben, kann z.Bsp. der nächste Filter oder die Anzeige des Ergebnisses in Angriff genommen werden.
    Es müssen nicht unbedingt Daten zwischen den Threads geschaufelt werden. Wenn ein Thread aber die Daten eines anderen Threads benötigt und darauf zugreifen möchte, muss er warten, bis der andere seinen Job erledigt hat, sonst werden FALSCHE Daten weiterverarbeitet...

  • @DarkMo Das ist mir alles bewusst :P Ich habe auch Vorlesungen drüber gehört und viel wichtiger, ich nutze Threads und Mutexe ausgiebig im TFMM ;) Man kann aber auch nicht blind alle Operation auf diesen Daten mit Mutexen absichern. Wenn dauernd nur auf die Freigabe der Mutex gewartet werden muss bremst man sein Programm damit so sehr das man quasi direkt auf Threads verzichten könnte ^^


    P.S.: Ich bin mir auch zu 99,9% sicher, dass eis_os auch all diese Dinge weiß ;)

  • Dann haben wir warscheinlich nur aneinander vorbei geredet. Von dem thread_join wie auch in meinem Link hatte ich garnicht gesprochen ^^ Das Beispiel von Toms ist zum Bsp etwas, was ich nichtmal direkt als wirkliche Parallelität bezeichnen würde. Man teilt zwar die Arbeit auf und hat einen Mehrnutzen in der Geschwindigkeit, aber die Threads bedingen immernoch einander. Wurde ja schön ausgeführt. Ist für mich halt irgendwie eher Pseudo-Parallelität. Würden sich die 4 Threads einen unbearbeiteten und freien Pixel zur Bearbeitung hernehmen, egal wie weit andere sind, dann wäre das mMn echte Parallelität. Alle 4 Threads würden gemeinsam an einem Bild arbeiten und "gleichzeitig" fertig werden (nur die Berechnung des letzten Pixels wäre natürlich dann ein möglicher Unterschied mit minimalster Wartezeit).

  • @DarkMo, ich sehe wir stimmen im Prinzip überein, drücken uns nur unterschiedlich aus.


    Was mich aber immer noch interessiert:
    Gibt es einen Zusammenhang zwischen "hoher FPS" und "langem Ruckler". Warum, weshalb und wie auch immer...


    Wenn ich keinen Post mit FPS-Angaben übersehen habe, haben wir hier mit 40-50 der eben solchen einen Spitzenreiten...

    Nur so zum Hintergrund: Ich habe auf einer SSD das OS laufen und auf der zweiten SSD das Spiel bzw. Steam...


    Als nicht Programmierer bzw. nicht annähernd so tief wie ihr in der Materie steckender noch eine Frage: Habt ihr einen Tipp zur Performance Verbesserung?
    ODER
    Könnte einer - der sich gut auskennt - diese Tipp noch einmal kurz zusammen fassen zur Performanceverbesserung? :saint:


    Verstanden hatte ich soviel:

    • möglichst wenig Mods
    • weiteres?

    Falls ich "dumm" geschrieben habe, bitte ich um entschuldigung, so manche Aussage sind für mich Böhmische-Dörfer! 8o


    Danke an euch alle für die vorherigen Infos!


    Grüße Marc

    "Ein Experte ist ein Mann, der hinterher genau sagen kann, warum seine Prognose nicht gestimmt hat!" (Winston Churchill)

  • Ich versuch mal ein paar Fragen abzuarbeiten.


    Performance: HDR und Schatten abschalten hilft bei GPU Leistungsproblemen.
    Nicht zu viele Linien bauen, ich kann jedes Spiel mit Monatsende Probleme verbessern indem man alle Linien und Züge entfernt :)




    Debugdaten:


    Ich hab mir die erste Linux Version gespeichert, und auch die ersten Mac Versionen per Steam Client besorgt. (Da waren sie gerade Aktuell)
    Dann kann man in die Trickkiste greifen, da Urban Exception nutzt, kann man über die Fehlermeldungen auf die Funktionsnamen schließen.


    Die generelle Performance ändert aber nichts an den internen Strukturen.



    Thread Join, dies ist ein Beispiel zu Veranschaulichung:
    Sagen wir haben den Status der Industrielieferketten:


    Haupt-Thread bewegt die Züge und macht das "Tagesgeschäft"
    Nebenthread errechnet neue Lieferketten.


    Am Ende des Monats, der Haupt-Thread benutzt noch die alten Daten.
    Was passiert nun?


    Thread-Join, die Nebenthread Daten werden genutzt um die neuen Lieferketten zu bestimmen.


    Unterschied zu deinen Pixel Beispiel. Dein Pixel hat nur bedingte Auswirkung auf die Nachbar-Pixel, meist stellt man einen Radius ein, bzw. intern gibt es einen.
    Das ist aber bei einer Wirtschaftssimulation nicht möglich. Das ist so ähnlich Fall zwischen Datenbanken, man kann bei bestimmten Sachen mit eventuell Konsistenz leben. Du möchtest aber auch nicht ein Bankkonto haben, das eventuell Konsistent ist, also der Guthaben-Betrag mal da ist und mal nicht, oder deine Bank einen Dauerauftrag nicht ausführt weil die letzte Abfrage ein eventuell falsches Ergebnis hat.


    Alle Algorithmen sind viel einfacher wenn man kein Feedback Loop hat.

    Zurzeit nicht aktiv im Forum :!:   Glaskugel rendert noch... Du möchtest meine Projekte unterstützen? You want to support my projects?   https://www.paypal.com/paypalme/eisos

    Einmal editiert, zuletzt von eis_os ()


  • Nicht zu viele Linien bauen, ich kann jedes Spiel mit Monatsende Probleme verbessern indem man alle Linien und Züge entfernt :)


    Fürein Spiel dieser Art natürlich die absolut ideale Lösung :D

    i7-5820 K | 32 GB | GTX 2070 Super 8 GB | Win 10 64bit | 10 TB HDDs
    i7-3770 K | 16 GB | GTX 1070 8 GB | Win 10 64bit | 4 TB HDDs

  • Ich sitze so vor meiner Juli-Karte, hab noch ein paar Schienen verlegt, nen Bahnhof vergrössert, Linien angepasst, Rollmaterial losgeschickt.
    Tja, was hat mir diese Map seit Juli Freude gemacht :) und fertig ist da noch lange nix, auch wenn schon 342 Jahre vergangen sind. :D


    Aber es nutzt nichts. Die Ruckler am Monatsende, sprich alle 60 Sekunden, gehen mir mittlerweile dermassen auf den, ähm, sag ich lieber doch nicht. :cursing:
    Was wäre ich glücklich, so UG dieses Problem lösen oder zumindest abmildern könnte. :thumbup::thumbsup::thumbup::thumbsup:


    So dann, geliebte Karte. Ruhe sanft...... :saint:


    LG Enno :)

    Auch ein alter Fuchs schaut gern ein Huhn, selbst wenn er's nicht mehr Reißen kann. ^^

    163393-cpuz-ryzen9-5900-png