Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Multithread und File I/O bei SSD/HDD (https://www.delphipraxis.net/188980-multithread-und-file-i-o-bei-ssd-hdd.html)

Benmik 23. Apr 2016 16:19

Multithread und File I/O bei SSD/HDD
 
Ich lese JPG ein und erstelle Vorschaubilder. Jetzt habe ich mal überprüft, welche Auswirkungen das hat, wenn ich Multithreading verwende, und das jeweils bei einer SSD und zwei herkömmlichen Festplatten (FP).
Material waren ~1.200 JPG mit insgesamt ~5 GB. Gemessen habe ich einmal mit und einmal ohne Platten-Cache (Rechner-Neustart). Verwendet habe ich nach längerem Überlegen AsyncCalls von Andreas Hausladen in der Modifikation von Zarko Gajic, da ich das WaitAll benutze.

Ergebnisse (gerundet, kommt ja auf die Größenordnung an):

Nach Neustart (Singlethread):

SSD: 85 sec
FP1: 90 sec
FP2: 90 sec

Beim Zweitstart (Singlethread):

SSD: 85 sec
FP1: 85 sec
FP2: 85 sec

Nach Neustart (Multithread):

SSD: 30 sec
FP1: 180 sec
FP2: 290 sec

Beim Zweitstart (Multithread):

SSD: 23 sec
FP1: 25 sec
FP2: 25 sec

Von der HDD-LED und vom Kraspeln her vermute ich stark, dass die Dateien auf der FP2 sehr viel verstreuter lagen als auf der FP1.

Das vorläufige Fazit ist, dass bei einer SSD Multithreading ein Muss ist, bei einer HDD ein DarfNicht. Ich habe überlegt, ob ich das Datei-Einlesen in einen eigenen Threadpool auslagern könnte, aber das geht nicht, da ich ich die Extract-Methode des IExtractImage benutze.

Jetzt könnte ich feststellen, ob die Dateien auf einer SSD liegen, und die entsprechende Strategie wählen. Das würde auch klappen, aber wie ich hier feststellen musste, würde das Administratorrechte voraussetzen.

Gibt es da Ideen zu?

Benedikt Magnus 23. Apr 2016 16:37

AW: Multithread und File I/O bei SSD/HDD
 
Wenn das Prüfen auf SSD wegfällt, könntest du als Workaround auch einen kleinen Teil der Dateien normal und einen multithreaded auslesen, anschließend vergleichen, was schneller ging und damit fortfahren.

markus5766h 23. Apr 2016 16:38

AW: Multithread und File I/O bei SSD/HDD
 
Moin,

ich kann mich dunkel daran erinnern, dass es bei SCSI Laufwerken über SCSI INQUIRY die Möglichkeit gab,
die Rotationsgeschwindigkeit abzufragen, für "SSD"s (gab's damals noch nicht --> waren EPROM-Lösungen)
gab's dann einen entsprechenden Rückgabewert.
Ob sich das für "normale" Festplatten umsetzen lässt, weiß ich allerdings nicht . . .

Benmik 23. Apr 2016 16:50

AW: Multithread und File I/O bei SSD/HDD
 
Zitat:

Zitat von Benedikt Magnus (Beitrag 1336465)
... vergleichen, was schneller ging und damit fortfahren.

Das merk ich mir schon mal. Das könnte selbst dann gut sein, wenn sich eine Lösung fände.

Sir Rufo 23. Apr 2016 17:33

AW: Multithread und File I/O bei SSD/HDD
 
Das Zauberwort heißt Pipeline.
  1. Bild von der Platte lesen (1 Thread)
  2. Vorschau erstellen (CPU-Count Threads)
  3. Vorschau speichern (1 Thread)

Benmik 23. Apr 2016 18:30

AW: Multithread und File I/O bei SSD/HDD
 
War ja auch meine Idee, aber nach viel Experimentieren fand ich seinerzeit den Weg über IExtractImage (Achtung: Interface! :wink:) mit GetLocation und Extract am schnellsten. Und da kann man Bild-Lesen und Vorschau-Erstellen nicht trennen.

Sir Rufo 23. Apr 2016 20:44

AW: Multithread und File I/O bei SSD/HDD
 
Zitat:

Zitat von Benmik (Beitrag 1336471)
War ja auch meine Idee, aber nach viel Experimentieren fand ich seinerzeit den Weg über IExtractImage (Achtung: Interface! :wink:) mit GetLocation und Extract am schnellsten. Und da kann man Bild-Lesen und Vorschau-Erstellen nicht trennen.

Warum kann man die nicht trennen?

Benmik 23. Apr 2016 20:57

AW: Multithread und File I/O bei SSD/HDD
 
Äh - weil Extract beides macht und in der Shell32.dll sitzt (dachte ich jedenfalls) ???

In gewisser Weise hat sich das aber erledigt, weil ich Benedikt Magnus' simple, aber geniale Idee (fällt ja öfter zusammen) mal ausprobiert habe, und siehe da, Multithread ist auch bei HDD besser, wenn die Dateien noch im Cache sind (ich messe jetzt auch bei FP1 und FP2 um die 25 sec, wie bei der SSD, habe mich also vermutlich bei der ersten Auflistung vertan). Insofern entfällt die Unterscheidung zwischen HDD und SSD. Hat eigentlich auch was für sich, wenn man einfach das nimmt, was schneller ist.
Ich messe jetzt erst n Dateien Single-Thread, dann n Dateien Multi-Thread und vergleiche. n ermittle ich nach der Formel von MaxThreads von AsyncCalls, NumberOfCores * 2 - 2, also einmal eine Poolgröße. Ist die Gesamtanzahl Dateien kleiner als 2 * n, dann ist es eh egal.

Valle 24. Apr 2016 08:07

AW: Multithread und File I/O bei SSD/HDD
 
Hi,

wenn du noch Optimierungsbedarf hast, dann hab ich noch zwei Anregungen.

Zum einen stelle ich mir die Frage, ob du nach jedem einzelnen Testlauf einen Rechnerneustart durchgeführt hast. Der Festplattencache des Betriebssystems kann dir sonst ganzschön die Ergebnisse versauen.

Zum anderen muss ich Sir Rufo zustimmen. Deine CPU ist immernoch den größten Teil der Zeit damit beschäftigt auf die Festplatte zu warten. Erst wenn das Bild vollständig geladen wurde, kann sie rechnen. Anschließend ist sie erneut mit warten (speichern + neues Bild laden) beschäftigt.

Mitteils einer Pipeline kannst du Laden, Bearbeiten und Speichern in mehrere Threads auslagern. Du kannst damit einen Puffer benutzen, der immer so viele Bilder wie möglich im RAM vorhält; egal ob gerade erst gelesen und fertig zum abspeichern. Mit einer ausreichenden Menge Arbeitsspeicher lässt sich dein Vorgang so sicherlich nochmals drastisch beschleunigen.

Hier ist noch eine Grafik die das schön anzeigt.

Luckie 24. Apr 2016 09:55

AW: Multithread und File I/O bei SSD/HDD
 
Kann man das nicht Paralleliesieren?
1. Schritt 1. Bild lesen
2. Schritt 1. Bild verarbeiten 2. Bild lesen
3. Schritt 3. Bild lesen 2 Bild verarbeiten
Wenn man das erste Bild verarbeitet, das zweite Bild lesen. Also eben versetzt.

Sir Rufo 24. Apr 2016 09:57

AW: Multithread und File I/O bei SSD/HDD
 
@Luckie

Das ist das Grundprinzip der Pipeline, bzw. so sollte man das mit einer Pipeline aufbauen ;)

Luckie 24. Apr 2016 11:03

AW: Multithread und File I/O bei SSD/HDD
 
Mist. Ich wollte das Prinzip gerade zum Patent anmelden. Aber vielleicht mache ich noch runde Ecken dran und versuche es trotzdem. :mrgreen:

Benmik 24. Apr 2016 12:03

AW: Multithread und File I/O bei SSD/HDD
 
Zitat:

Zitat von Valle (Beitrag 1336485)
...nach jedem einzelnen Testlauf einen Rechnerneustart durchgeführt...

Hab ich! Und sogar die Festplatten dabei noch kurz stromlos gemacht, für alle Fälle.

Ich finde ja auch, dass Sir Rufo Recht hat, aber ich hatte seinerzeit sehr viel ausprobiert, um den schnellsten Weg zu einem Vorschaubild zu finden, und IExtractImage fand ich einfach am besten. Ich bin auch gar nicht so sicher, ob ein Einlesen in einem separaten Thread etwas bringen würde, denn vermutlich ist nicht das Einlesen selbst, sondern das Positionieren des Lesekopfes der entscheidende Flaschenhals. Ich habe mal die Dateien von FP1 in den FastStone Image Viewer eingelesen. Der brauchte 5 Sekunden länger als mein Programm. Merkwürdigerweise brauchte er die gleiche Zeit, wenn ich die JPG von der SSD eingelesen habe. IrfanView braucht 30 Sekunden weniger, aber ich vermute, das zeigt nur die Vorschaubilder an und speichert keine weitere Daten, so wie mein Programm und offensichtlich auch FastStone das tun. Insgesamt liege ich also offenbar nicht schlecht.

Nun kommen mir ganz verwegene Gedanken (wobei auch ein gewisser Spaßfaktor dabei ist): Wie wäre es, wenn man die Position der Dateien auf der Festplatte ermitteln (siehe mal hier und hier und hier) und sie dann entsprechend ihrer physischen Position einlesen würde? Wäre das sinnvoll? Was ist eigentlich mit Native Command Queuing?

Valle 24. Apr 2016 15:48

AW: Multithread und File I/O bei SSD/HDD
 
Dein Betriebssystem und dein Dateisystem sollten sich gut genug darum kümmern können. Ich glaube kaum dass du hier sinnvoll optimierne kannst. Wichtig ist nur, dass du eindeutige Signale für dein Betriebssystem setzen kannst. Wenn du ein Verzeichnis an Dateien iterierst, dann können moderne Heuristiken dich schon sehr gut dabei unterstützen. Es wird dann oft schon präventiv eingelesen. Funktioniert natürlich nicht, wenn Dateien überall verteilt sind.

Mein Ansatz wäre es dann, eine Queue im RAM anzulegen und einen Thread (bis zur maximalen Befüllung) diese Queue befüllen zu lassen. (n-1) andere Threads arbeiten die Queue ab. Der einlesende Thread speichert die Ergebnisse der anderen Threads gelegentlich zurück. Wenn du blockweise arbeitest (nicht ein Bild abspeichern, sondern immer gleich 100 oder so; je nach RAM; währenddessen das Einlesen einstellen) solltest du die besten Ergebnisse haben.

Benmik 24. Apr 2016 18:42

AW: Multithread und File I/O bei SSD/HDD
 
Ich denke auch, dass ich diesen Ansatz jetzt erstmal nicht weiter verfolgen werde. Das Plattenkraspeln bei FP2 und die deutlichen Unterschiede zwischen FP1 und FP2 lassen mich aber doch glauben, dass man das Einlesen verbessern kann.

Ich arbeite ja schon mit einem Threadpool. Wenn die Dateien erstmal im Arbeitsspeicher sind, ist, glaube ich, wenig an Geschwindigkeit herauszuholen. 23 Sekunden für ~1.200 Dateien macht rechnerisch 19 msec für das Dekodieren und Verkleinern eines JPG bei einem älteren Vierkerner. Damit kann man zufrieden sein. Dank an euch.


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:46 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz