LAME: Asynchrone Dateiverarbeitung
Der Enkodiervorgang auf Dateiebene in LAME ist in folgender Abbildung dargestellt:
Die unkomprimierte Datei wird blockweise eingelesen und die komprimierte Datei blockweise
geschrieben. Hierbei wechseln sich Lese- und Schreiboperationen ab.
Obwohl diese Vorgehensweise und die Verwendung von synchronen I/O-Operationen nicht optimal ist,
wird die Geschwindigkeit beim Enkodieren einer einzelnen Datei dadurch nicht beeinträchtigt.
Als Pseudocode lässt sich der Vorgang in einer imperativen Programmiersprache wie folgt beschreiben:
MP3EncodeFile(wavFilename, mp3Filename)
{
infile = OpenFile(wavFilename);
outfile = OpenFile(mp3Filename);
for (i = 0; i < maxBlocks; ++i) {
inblock = ReadBlock(infile);
outblock = EncodeBlock(inblock);
WriteBlock(outfile, outblock);
}
}
Prinzipiell ist es möglich, die Funktion "MP3EncodeFile" für mehrere Dateien parallel auf
verschiedenen Threads auszuführen. Dies eignet sich für zwei bis drei Threads.
Bei noch mehr Threads konkurrieren jedoch zu viele I/O-Operationen parallel um einen seriellen Datenträger,
sodass die dadurch entstehenden Effizienzverluste den Nutzen weiterer Prozessoren übersteigen.
Um solche Probleme behandeln zu können, besitzt Fiber Pool einen I/O-Scheduler.
Diesem kann man eine beliebige Anzahl an Aufträgen geben, die dann mit bestmöglicher I/O-
Performance abgearbeitet werden.
Der Pseudocode dazu könnte in einer asynchronen Programmiersprache wie folgt aussehen:
MP3EncodeFile(wavFilename, mp3Filename)
{
Memory inMemory;
Memory outMemory;
ReadFile(wavFilename, inMemory);
WriteFile(mp3Filename, outMemory);
Encode(inMemory, outMemory);
}
Beim Aufrufen dieser Funktion werden die drei Aufträge "ReadFile", "WriteFile" und "Encode" dem
darunterliegenden System (hier: Fiber Pool) zur Bearbeitung übergeben.
Für die Bearbeitung mehrerer Dateien kann die Funktion beliebig oft aufgerufen werden, sodass bei
n Dateien 3n Aufträge an das System übergeben werden.
Im Gegensatz zur imperativen Lösung, in der die Sichtweite eines Threads die aktuell ausgeführte
Programmzeile ist und keine Kenntnisse über weitere Threads existieren, erhält das asynchrone System
ausreichend Informationen, um Strategien hinsichtlich der Verwendung von CPU, I/O und Speicher
bis zum nächsten Synchronisationspunkt entwickeln zu können.
Implementierung in fpMP3:
Die asynchrone Funktion "MP3EncodeFile" wurde als C++-Klasse "MP3EncodingTask" implementiert. Als
I/O-Strategie wurde festgelegt, lesende Operationen gegenüber schreibenden zu bevorzugen (s. auch
Dokumentation zu "SetDefaultFileIOSchedulingStrategy").
Über die Kommandozeile können CPU- und Speicherverwaltungsstrategie angepasst werden.
|