Performance Probleme



  • Hi

    Ich arbeite zur Zeit an einem großen Projekt.

    Als Oberfläche kommt QT zum einsatz aber das ist wahrscheinlich eher nebensächlich.
    Es handelt sich dabei um eine Art Flugsimulator.

    Ein vorher berechneter Flugpfad soll sowohl als Linie in einem 3D-Tool als auch in numerischer Weise ( Höhe, Neigungswinkel etc. ) in einer Tabelle angezeigt werden.
    Diese beiden Aufgaben werden in separaten Threads bearbeitet.

    Die Flugpfaddaten liegen in folgender Form vor:

    std::map< Zeitpunkg in ms , std::vector< Wegpunktdaten > >

    Dieser Container wird im voraus aus einer Datenbank befüllt.

    Nun greift sowohl der Thread in dem das 3D-Tool läuft als auch der in dem die Tabelle befüllt wird darauf zu.

    Vor allem die Performance des 3D-Tools ist sehr schlecht und schwankt sehr stark. Ich habe daraufhin testweise alle Funktionen die mit dem Befüllen der Tabelle zu tun haben auskommentiert, die Geschwindigkeit des 3D-Tools verbesserte sich daraufhin rapide und blieb auch konstant.
    Meine Annahme: Der Tabellen-Thread nimmt dem 3D-Thread zu viel leistung weg (beide laufen übrigens mit der selben Priority (WinXP) )

    Nun meine Frage: Worauf lässt sich dieses Problem am ehesten zurückführen?

    Liegt es an dem parellelen Zugriff auf den selben Speicherbereich?
    Das halte ich zwar für eher unrealistisch aber würde in diesem Fall eine Kopie des Containers abhilfe schaffen?

    Oder kann es nicht daran liegen und ich muss nach einer anderen Ursache suchen?

    MFG
    stein



  • Veränderst du die Flugpfaddaten irgendwo zwischendurch, oder bleiben die konstant? Und in welchen Größenordnungen liegen sie ungefähr, wieviele Zeitpunkte, wieviele Wegpunktdaten pro Zeitpunkt?
    Und letzte Frage vorerst: Sind die Zeitpunkte sequentiell in gleichem Abstand oder varriert der Abstand?



  • stein schrieb:

    voraus

    Das schreibt man Forrau`s.



  • Nein die Daten werden nach dem Laden nicht mehr verändert. Sonst wäre das ganze ja noch nichtmal threadsafe und würde mir sicher mächtig Exceptions hageln.

    Bei meinem Testbeispiel sind knapp 30000 Wegpunkte vorhanden, aufgeteilt auf 9 Flugobjekte.
    In diesem Beispiel sind die vectors immer gleich groß ( 9 ), können bei anderen Beispielen aber auch variieren.
    Die Wegpunkte sind immer in 100ms Schritten in der map abgespeichert.

    Meine Schleife in der die Wegpunkte gezeichnet werden habe ich schon sehr stark optimiert. Bei 30000 Wegpunkten macht sie ca. 30500 Wiederholungen.



  • Hm. Synchronisierst du die Framerate bei dem 3D-Tool? So wie du die Daten beschreibst, sieht es nicht so aus, als ob die Performance-Hürde dort liegt. Und bei gleichzeitigem Lesezugriff dürfte sich kein Unterschied bemerkbar machen, soweit ich weiß läuft das alles auf dem Thread-eigenen Stack ab.



  • Also ich würde da einfach mal darauf tippen, dass du die Daten in jedem Frame lädst, was in einem solchen Einbruch hervorrufen kann.



  • Was genau verstehst du mit Framerate synchronisieren?

    Noch etwas mehr zum Ablauf:

    Das Grafiktool wird gestartet und rendert den Frame zum Zeitpunkt 0, danach sagt es dem Tabellen-Thread (Hauptprogramm) dass es fertig ist und die neue Zeit haben will, daraufhin kriegt das 3D-Tool die aktuelle Zeit and so on.

    Die Kommunikation läuft über WindowsMessages ab, die sind aber nicht die Engstelle.



  • stein schrieb:

    Was genau verstehst du mit Framerate synchronisieren?

    Ups, doof ausgedrückt 😉 Gemeint war, ob du mit einem Timer o.ä. sicherstellst, dass du eine konstante Frames-Per-Second-Zahl erreichst. Ansonsten kann gerade bei der Grafikausgabe die Dauer beim Darstellen recht schnell schwanken. Zeichnest du eigentlich mittels der WinAPI? Und wenn ja, wird ein Backbuffer benutzt?

    stein schrieb:

    Das Grafiktool wird gestartet und rendert den Frame zum Zeitpunkt 0, danach sagt es dem Tabellen-Thread (Hauptprogramm) dass es fertig ist und die neue Zeit haben will, daraufhin kriegt das 3D-Tool die aktuelle Zeit and so on.

    Die Kommunikation läuft über WindowsMessages ab, die sind aber nicht die Engstelle.

    Nur aus Interesse: Wie übermittelst du denn per Windows-Nachrichten die Daten?



  • Zum Zeichnen wird OpenGL verwendet.

    Ich muss dazu sagen dass das 3D-Tool nicht von mir ist sondern von Extern kommt.
    Es wurde bereits in einer früheren Version des Programms verwendet und lief dort auch bis auf ein paar Bugs zufriedenstellend.

    Das Hauptprogramm wird gerade komplett neu entwickelt aber weil die Zeit knapp ist wird das alte 3D-Tool weiterverwendet.

    In der alten Version wurde die Tabelle allerdings im selben Thread befüllt in dem auch das 3D-Tool lief, also praktisch nebenher.
    Nun soll aber das Hauptprogramm sozusagen der Treiber für das 3D-Tool sein da dieses in der nächsten Version aus unten genannten Gründen ausgetauscht wird.

    Meine Aufgabe ist lediglich das alte Tool an das neue Programm zu klemmen, was nicht gerade einfach war weil der Stil echt bescheiden ist.
    Fast alle Zeichenroutinen liegen in einer(!) mehrere hundert Zeilen langen Routine, außerdem ist das Teil noch in C mit haufenweisen globalen Variablen mit wirklich toll gewählten Namen (xya oder lolalat z.B.) geschrieben.

    Solange die Tabelle nicht befüllt wird läuft das Tool ja auch sehr zufriedenstellend, ich glaube also nicht dass es an sowas wie der Framerate liegt.

    Zu deiner Frage:

    Die Flugpfaddaten liegen wie gesagt in einem Speicherbeich zu dem beide Threads Zugang haben. In den Messages übermittle ich lediglich die aktuelle Zeit:

    #define WM_GIVETIME WM_APP + 100
    #define WM_SETTIME WM_APP + 101
    
    // 3D-Tool
    
    PostMessage( hwndMainWindow, WM_GIVETIME, 0, 0); // bin fertig, gib zeit
    
    // Mainthread
    
    PostMessage( hwnd3DWindow, WM_SETTIME, 0, (LPARAM) m_iCurrentTime ); // da hast du
    


  • Hm, mir gehen die Ideen aus.. 🙂 Aber eine Sache noch: Sitzt die Prozessorauslastung auf 100%? Und sonst probier doch einfach mal aus, eine Kopie der map zu machen, dürfte ja schnell gehen. Ansonsten kannst du mit diversen Profilern noch schauen, wo genau der Engpass ist, spätestens das sollte Klarheit verschaffen.



  • Anstatt mit einem Profiler kannst du ja auch noch mit dem auskommentieren weitersuchen. Das klappt manchmal recht gut. Somit kannst du es noch weiter eingrenzen.

    Was mich allerdings immernoch stuzig macht, ist, dass wenn du das befüllen ausklammerst es geht. Das lässt mich auf 2 Sachen schlissen.
    1. Dass du das in der Schleife machst oder
    2. Es einfach zu viele Daten gibt, die du jedesmal abgleichen musst.



  • Das mit der Prozessorauslastung hab ich tatsächlich vergessen mir anzuschauen.
    Allerdings schien der Rechner nicht übermässig belastet zu sein.
    Ich werds morgen überprüfen.

    Das mit der Kopie wollte ich sowieso versuchen, eine akpzeptable Lösung wäre das aber nicht da bei millionen von Wegpunkten ein riesen Haufen redundanter Daten vorliegen würde.

    Naja die Schleife zum Befüllen der Tabelle wird nicht so besonders oft durchlaufen, außerdem werden darin bloß die Werte aus dem Container gelesen und in die entsprechenden Zellen gepackt.

    Mir bleibt wohl nichts anderes übrig als meine Testreihen fortzusetzen.

    Danke für eure Ideen.



  • stein schrieb:

    Nein die Daten werden nach dem Laden nicht mehr verändert. Sonst wäre das ganze ja noch nichtmal threadsafe und würde mir sicher mächtig Exceptions hageln....

    Leicht OT: Schön wär's.
    Leider werden threadsafe-Fehler nur seeeehr selten mit exceptions sanktioniert ... falsche Daten, segfaults, deadlocks .... (alles natürlich kaum reproduzierbar) sind da eher die Regel.

    Gruß,

    Simon2.


Anmelden zum Antworten