DirectX-Anwendung "Schluckauf" alle 3 Sekunden

9

Ich habe seit über einer Woche ein Problem in meiner DirectX 11 C ++ - Anwendung untersucht, und deshalb wende ich mich an die guten Leute in StackOverflow, die mir helfen könnten, diesen Fehler nachzuverfolgen.

Meine Anwendung wird meistens mit 60-90 Frames pro Sekunde laufen, aber alle paar Sekunden bekomme ich einen Frame, der etwa eine Drittelsekunde dauert. Nach vielen Nachforschungen, dem Debuggen und der Verwendung verschiedener Code-Profiler habe ich mich auf Aufrufe der DirectX-API beschränkt. Von einem langsamen Frame zum nächsten ist es jedoch nicht immer derselbe API-Aufruf, der die Verlangsamung verursacht. In meinem letzten Lauf sind die Aufrufe, die anhalten (immer für etwa eine Fünftelsekunde)

  • ID3D11DeviceContext: UpdateSubresource
  • ID3D11DeviceContext: DrawIndexed
  • IDXGISwapChain: Präsens

Nicht nur ist es nicht die gleiche Funktion, die zum Stillstand kommt, sondern jede dieser Funktionen (hauptsächlich die ersten zwei) kann der langsame Aufruf von verschiedenen Stellen in meinem Code von einem zum anderen sein.

Nach mehreren Profiling-Tools und meinen eigenen hochauflösenden Timern, die ich in meinen Code eingesetzt habe, um die Dinge zu messen, habe ich festgestellt, dass dieser "Schluckauf" in gleichmäßigen Abständen von knapp 3 Sekunden (~ 2,95) auftreten würde.

Diese Anwendung sammelt Daten von externer Hardware und verwendet DirectX, um diese Daten in Echtzeit zu visualisieren. Während die Anwendung ausgeführt wird, kann die Hardware im Leerlauf oder mit verschiedenen Geschwindigkeiten ausgeführt werden. Je schneller die Hardware geht, desto mehr Daten werden gesammelt und müssen visualisiert werden. Ich weise darauf hin, weil es nützlich sein kann, wenn man einige der Eigenschaften dieses Fehlers betrachtet:

  • Die langen Frames treten nicht auf, wenn die Hardware inaktiv ist. Das macht für mich Sinn, weil die Software nur Daten neu zeichnen muss, die sie bereits hat und keine neuen Daten an die GPU übertragen muss.
  • Die langen Frames treten jedoch in diesen konsistenten 3-Sekunden-Intervallen auf, unabhängig von der Geschwindigkeit, mit der die Hardware ausgeführt wird. Selbst wenn meine Anwendung die doppelte Datenmenge pro Sekunde sammelt, ändert sich die Frequenz der langen Frames nicht.
  • Die Dauer dieser langen Frames ist sehr konsistent. Immer zwischen 0,25 und 0,3 Sekunden (ich glaube, es ist der langsame Aufruf an die DirectX-API, der konsistent ist, so dass jede Variation der Gesamtrahmen-Dauer extern zu diesem Aufruf ist).
  • Während der Feldtests in der letzten Woche (als ich das Problem zum ersten Mal entdeckte), bemerkte ich, dass bei ein paar Läufen der Anwendung nach einer langen Zeit (wahrscheinlich 20 Minuten oder länger) kontinuierliche Tests ohne viel Interaktion mit dem Programm stattfanden beobachtete es, das Schluckauf würde verschwinden. Der Schluckauf würde zurückkommen, wenn wir mit einigen Funktionen der Anwendung interagierten oder das Programm neu starteten. Für mich ergibt das keinen Sinn, aber fast so, als ob die GPU "herausgefunden" hätte und das Problem behoben hätte, aber dann wieder rückgängig gemacht wurde, als wir das Arbeitsmuster, das es vorher gemacht hatte, verändert hatten. Leider macht es die Beschaffenheit unserer Hardware schwierig, dies in einer Laborumgebung nachzubilden.

Dieser Fehler tritt konsistent auf zwei verschiedenen Computern mit sehr ähnlicher Hardware auf (zwei GTX580-Karten). In neueren Versionen der Anwendung ist dieses Problem jedoch nicht aufgetreten. Leider hat der Code seitdem viele Änderungen erfahren, so dass es schwierig sein würde festzustellen, welche spezifische Änderung das Problem verursacht.

Ich habe den Grafiktreiber berücksichtigt und so auf die neueste Version aktualisiert, aber das hat keinen Unterschied gemacht. Ich erwog auch die Möglichkeit, dass eine andere Änderung an beiden Computern vorgenommen wurde, oder dass möglicherweise eine Aktualisierung der Software, die auf beiden Computern ausgeführt wird, Probleme mit der GPU verursachen könnte. Aber ich kann mir nichts anderes als Microsoft Security Essentials vorstellen, das auf beiden Computern ausgeführt wird, während die Anwendung ausgeführt wird, und ich habe bereits versucht, die Echtzeitschutzfunktion zu deaktivieren, ohne Erfolg.

Obwohl ich gerne die Ursache dafür hätte, ein externes Programm zu sein, das ich einfach ausschalten kann, mache ich mir schließlich Sorgen, dass ich etwas falsch / falsch mit der DirectX-API machen muss, die die GPU veranlasst, alle paar Anpassungen vorzunehmen Sekunden. Vielleicht mache ich etwas falsch in der Art, wie ich Daten auf der GPU aktualisiere (da die Verzögerung nur auftritt, wenn ich Daten zur Anzeige sammle). Dann hält der GPU alle paar Sekunden an und welche API-Funktion, die während eines Stalls aufgerufen wird, kann nicht so schnell zurückkehren, wie es normalerweise wäre?

Irgendwelche Vorschläge würden sehr geschätzt!

Danke, Tim

UPDATE (2013.01.21):

Ich gab schließlich nach und ging zurück durch vorherige Überarbeitungen meiner Anwendung, bis ich einen Punkt fand, an dem dieser Fehler nicht auftrat. Dann ging ich von Revision zu Revision, bis ich genau herausgefunden hatte, wann der Bug begann und die Quelle meines Problems ausfindig machte. Das Problem trat auf, nachdem ich ein "vorzeichenloses Integer" -Feld zu einem Vertex-Typ hinzugefügt hatte, dem ich einen großen Vertex-Puffer zuteile.Aufgrund der Größe des Vertexpuffers erhöhte diese Änderung die Größe 184,65 MB (1107,87 MB bis 1292,52). Da ich tatsächlich dieses zusätzliche Feld in meiner Vertex-Struktur benötige, habe ich andere Möglichkeiten gefunden, um die Gesamtgröße des Vertex-Puffers zu reduzieren, und habe es auf 704,26 MB heruntergesetzt.

Meine beste Vermutung ist, dass das Hinzufügen dieses Feldes und der zusätzliche Speicher, den es benötigt, dazu geführt haben, dass ich einen Grenzwert / Grenzwert für die GPU überschritten habe. Ich bin mir nicht sicher, ob es eine Überschreitung der Gesamtspeicherzuweisung oder eine Überschreitung einer Grenze für einen einzelnen Vertexpuffer war. Wie auch immer, es scheint, dass diese Überschreitung dazu führte, dass die GPU alle paar Sekunden einige zusätzliche Arbeit verrichten musste (vielleicht mit der CPU kommunizieren), und deshalb mussten meine Aufrufe an die API darauf warten. Wenn jemand irgendwelche Informationen hat, die die Implikationen großer Eckenpuffer verdeutlichen würden, würde ich es gerne hören!

Danke an alle, die mir ihre Zeit und Vorschläge gegeben haben.

    
Tim Coolman 18.01.2013, 20:31
quelle

1 Antwort

1

1) Versuchen Sie, VSYNC zu drehen

2) Sie reservieren große Speicherbereiche? Versuchen Sie, Speicher zu Beginn des Programms zu reservieren und nicht zu löschen, überschreiben Sie es einfach (was Sie wahrscheinlich mit updatesupresource tun)

3) Fügen Sie die Interaktion mit dem Hardwaregerät in einen separaten Thread ein. Nachdem das Gerät die Daten vollständig an Ihre Anwendung übergeben hat, laden Sie es in die GPU. Lassen Sie das Gerät nicht die Kontrolle über den Haupt-Thread übernehmen. Ich vermute, dass das Gerät den Haupt-Thread immer wieder blockiert, und ich spekuliere völlig , aber wenn du Daten direkt vom Gerät auf die GPU kopierst, blockiert das Gerät gelegentlich und das verursacht die Verlangsamung.

    
bobobobo 18.01.2013 20:38
quelle