[FIXED] Verbesserte Leistung beim Speichern/Importieren von Bildern auf der Festplatte

Ausgabe

Frage

Hallo, ich habe eine Frage zu Threadpool, HDD lesen/schreiben gleichzeitig. Es ist das erste Mal, dass ich eine Frage hinterlasse, also entschuldige ich mich im Voraus, weil das Schreiben langwierig ist …

Auf einem PC

laufen die Bildverarbeitungs- und Bildspeicherprogramme sowie das Bildladeprogramm.

Wenn die Bildspeicher- und Bildimportvorgänge gleichzeitig auf einer Festplatte ausgeführt werden, scheint sich die Bildverarbeitung zu verlangsamen.

Die Festplatte hat nur einen Festplattenkopf, daher weiß ich, dass es am schnellsten ist, jeweils nur eine Bewegung auszuführen … An diesem Teil können wir nichts ändern, daher möchte ich minimieren oder verlangsamen.

Als nächstes die Entwicklungsumgebung und die Implementierungssituation.

Ich habe mit MFC + OpenCV gearbeitet (Windows 10.0.19044)

Das Bildverarbeitungsprogramm wird bei jeder Anweisung wiederholt und läuft 24 Stunden am Tag. Das Bild ist 16384 * 40000 Pixel * 1 Bytes 2 Blätter. Da es sich um ein Bild mit hoher Kapazität handelt, werden sowohl die Bildverarbeitung als auch die Bildspeicherung nach der Bildbereichsteilung in einem Thread-Pool durchgeführt.

Das Bildladeprogramm arbeitet, wenn der Benutzer es benötigt. Bei der Abfrage fragt DB Videoinformationen ab und ruft Bilder von der Festplatte ab.

Der PC ist mit SSD und zwei HDDs (13TB) ausgestattet. Der Prozessor ist i9-12900KF, 16core, 24thread.

Jeder Job wird herausgenommen, indem er in eine Warteschlange gestellt wird, und sowohl Bildverarbeitungs- als auch Bildspeicherjobs werden in einem Thread-Pool verarbeitet.

Ich teile denselben Thread-Pool und verwende ihn, daher vermute ich, dass während der Bildspeicherung die Anzahl der für die Bildverarbeitung verwendeten Threads abnimmt.

Ich habe die Anzahl der Threads für beide Programme auf 40 gesetzt. Es gibt keinen besonderen Grund. Ich habe gehört, dass wir es abhängig von der Anzahl der Kerne effizient abfangen müssen, aber ich denke darüber nach.

Ich speichere das Bild im PNG-Format bzw. im JPG-Format.

Die Standardaktion für das Laden von Bildern besteht darin, die Datei in ein kleines JPG zu laden, und die Funktion ist so unterteilt, dass der Benutzer sie bei Bedarf direkt in PNG laden kann.

Beim Speichern eines geteilten Bildes wird der Bildcodierungsvorgang gleichzeitig im Thread-Pool-Speicher ausgeführt -> HDD-Übertragungen werden sequentiell nacheinander in einem einzigen Thread übertragen.

Zum Laden von Bildern wird hdd -> Speicher nacheinander geladen. Die Bilddecodierungsoperation wird gleichzeitig im Thread-Pool durchgeführt.

Das Bildverarbeitungsergebnis soll in der DB gespeichert und das Ergebnis schnell versendet werden.

Es spielt keine Rolle, ob die Bildspeicherung verlangsamt wird. Der Bildladevorgang ist für den Benutzer nicht zufriedenstellend, kann aber bis zu einem gewissen Grad beeinträchtigt werden. (Trotzdem möchte ich es implementieren, um das Ergebnis so schnell wie möglich zu liefern …)

Also was ich dachte

  1. Wenn Threads zum Speichern/Importieren von Bildern die Threadpriorität verringern, werden Bildverarbeitungsthreads dann mehr Arbeit und Arbeit leisten?
  2. Ist es sinnvoll, anstelle eines Threadpools den Threadpool für die Bildspeicherung/Bildverarbeitung aufzuteilen?
  3. Warum speichern Sie das Image nicht auf SDD, erstellen ein separates Dienstprogramm und senden es langsam an die Festplatte?
  4. Eigentlich gibt es kein Problem mit der Festplatte?

1, 2, werden entwickelt und veröffentlicht. (Es ist schwierig, Probleme im Büro zu reproduzieren…)

Die dritte Methode besteht darin, auf eine HDD in SDD zu schreiben, sofort auf eine HDD zu schreiben und sich mit dem HDD-Lesen zu überschneiden. Ich denke, es ist nur die Entwicklung, die kompliziert wird. Beim Speichern von Bildern ist es jedoch deutlich schneller als die Festplatte.

Im Fall von Nummer 4 ist jpg aufgrund der geringen Dateikapazität beim Laden von Bildern nicht langsam … Der Decodierungsprozess ist langsam. Ich dachte, es hätte nichts mit HDD aus der Dekodierungsphase zu tun.

Beide Programme haben also 40 Threads im Thread-Pool. Das Bildimportprogramm hat die Anzahl der Threads auf zwei reduziert und ein Update gesendet, aber es wurde berichtet, dass der Bildimportvorgang nur langsam war und das Problem weiterhin bestand.

Die Situation ist kompliziert und es gibt viele verdächtige Dinge, aber ich frage Sie, weil ich glaube, dass es Teile gibt, die ich nicht kenne oder die Fehler enthalten…

Lösung

Zunächst einmal verwenden Sie einen Thread-Pool mit weit mehr Threads als die Anzahl der Kerne auf dem i9-12900KF-Prozessor. Wenn zwei Threads auf demselben physischen Kern ausgeführt werden, sind sie im Allgemeinen langsamer. Wenn sie auf demselben logischen Kern ausgeführt werden, können sie nicht gleichzeitig ausgeführt werden (sie werden ständig unterbrochen). Selbst wenn sie auf verschiedenen physischen Kernen ausgeführt werden, kann ein Thread einen anderen erheblich verlangsamen, wenn er den L3-Cache oder den Speicher intensiv nutzt, was wahrscheinlich Ihr Fall ist. Der Betrieb auf einem großen Puffer kann dazu führen, dass Cache-Zeilen des Caches anderer Kerne entfernt und somit später neu geladen werden. Dies wird als Cache-Trashing bezeichnet. Dieses Problem kann bei nicht zusammenhängenden Lade-/Speichervorgängen kritisch werden.

Der Zielprozessor ist klein und groß, daher ist die Planung von Threads auf einem solchen Prozessor komplexer als gewöhnlich. Tatsächlich unterstützen viele Bibliotheken eine solche Architektur noch nicht gut (sie laufen nicht effizient). Selbst OS-Stacks sind für eine solche Architektur kaum geeignet (zumindest unter Windows und Linux). Die Anzahl der Threads pro Kern ist nicht für alle Kerne gleich: Ein großer Kern kann 2 Threads gleichzeitig ausführen (gemeinsame Nutzung verfügbarer Ressourcen), während ein kleiner Kern nur 1 Thread gleichzeitig ausführen kann. Es ist erwähnenswert, dass die Frequenz des kleinen Kerns nicht dieselbe ist wie die des großen Kerns: 2,4 GHz vs. 3,2 GHz für die Basisfrequenz und 3,9 GHz vs. 5,1 für die Turbofrequenz). In Bezug auf das Scheduling des Threads zum Kern kann sich die Leistung des Ziel-Threads ändern.

Die Frequenz der Kerne, die die Threads ausführen, hängt von der Anzahl der verwendeten Kerne und der Arbeit ab, die auf jedem Kern ausgeführt wird. Beispielsweise kann die Ausführung eines rechenintensiven Codes mit den FP AVX-2-Einheiten (oder den nicht offiziell unterstützten AVX-512-Einheiten) auf einem Kern die Frequenz anderer Kerne erheblich reduzieren. Je höher die Anzahl der aktiven Kerne, desto niedriger die Frequenz. Dynamische Frequenzverzögerungen wirken sich auf die Skalierbarkeit der Anwendung aus, aber diese Skalierung ist wichtig, damit der Prozessor sein Leistungsbudget erfüllt (und nicht zu sehr schmilzt).

Caching spielt auch eine große Rolle. In der Tat neigen Mainstream-Betriebssysteme dazu, HDD-Lese-/Schreibdaten in den Speicher zu legen, um schneller zu arbeiten. Dies erfordert etwas zusätzlichen Speicher, der nicht als zugewiesen betrachtet wird. Wenn ein Prozess eine große Speichermenge anfordert, leert/invalidiert das Betriebssystem den IO-Cache in Bezug auf den angeforderten Speicherplatz, und spätere Zugriffe führen dazu, dass Daten vom Speichergerät neu geladen werden (viel langsamer). Die Lösung besteht darin, den vollständig verfügbaren Speicher (den nicht zwischengespeicherten Teil) zu überprüfen und nicht zu viel Speicher zu verwenden, wenn der verbleibende Speicherplatz vom Cache des Speichergeräts verwendet wird.

Wenn zwei Threads E / A-Vorgänge ausführen, ist dies im Allgemeinen nicht schneller als 1 Thread auf der Festplatte (insbesondere mit 1 Kopf). Einige OS-Stacks verwenden Sperren, wenn nicht einmal eine riesige Sperre. Aus diesem Grund kann ein Ladethread mit asynchronem IO schneller sein als das Blockieren von IO auf einem/mehreren Threads. In der Tat kann das Betriebssystem Anforderungen neu ordnen, damit sie in diesem Fall zusammenhängender sind (um die Suchzeit zu reduzieren, indem Daten unterwegs geladen werden).


Beantwortet von –
Jérôme Richard


Antwort geprüft von –
Gilberto Lyons (FixError Admin)

0 Shares:
Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like