Multicore-MP3-Encoder: MDCT im asynchronen Fluss

Die Entwicklung des Encoders schreitet leider nicht so schnell voran, jedoch sind kleine Fortschritte erkennbar.

In der aktuellen Version, die an bekannter Stelle zum Download bereitsteht, wird nun die MDCT-Phase asynchron ausgeführt.

Da MDCT im Vergleich zu den anderen Phasen relativ schnell berechnet wird, ist der Performancegewinn nicht besonders hoch. Auf meinem System lag er bei etwa 8%.

Die Portierung des seriellen in asynchronen Code habe ich in mehreren Schritten durchgeführt, die ich hier näher beschreiben möchte:

Ursprünglicher Zustand:
Die folgende Abbildung zeigt die MDCT-Phase beim Ausführen des seriellen Codes:

MDCT 1

Aus den eingehenden Samples wird zunächst das psychoakustische Modell (PSY) berechnet, bevor darauf MDCT angewandt wird. Nach der MDCT wird der Quantisierer ausgeführt.

Die Abhängigkeiten sind wie folgt: Die MDCT ist abhängig von PSY, weil dort die Block Types (long/short) berechnet werden. Der Quantisierer ist abhängig von dem Ergebnis der MDCT.

Schritt 1: Erzeugen einer MDCT-Task
Für eine gute Basis zur MDCT-Parallelisierung werden nun alle Aktivitäten, die mit MDCT zu tun haben, in eine Task ausgegliedert:

MDCT 2

Die wichtigste Änderung gegenüber dem ursprünglichen Zustand ist, dass die Task nun den MDCT-Zustand selbst (Subband-Samples) verwaltet und er nicht mehr in der globalen Datenstruktur gespeichert wird.

Obwohl es sich noch um eine parallel ausgeführte Task handelt, wird sie durch die eingesetzten Synchronisationsprimitiven seriell ausgeführt.

Schritt 2: Überlappende Berechnung der Subbänder
In der vorherigen Abbildung wurde schon angedeutet, dass die Berechnung der Subband-Samples nicht von PSY, sondern nur von den eingehenden Samples abhängig ist. Daher wird die MDCT-Task nun zusätzlich mit ihnen synchronisiert:

MDCT 3

Die Subband-Samples eines Frames können nun parallel zum PSY berechnet werden.

Schritt 3: Überlappen mit dem Quantisierer
Die MDCT berechnet für ein Frame insgesamt vier xr-Arrays, jeweils zwei für jeden Kanal. Da der Quantisierer zu seiner Ausführung nicht sofort alle vier Arrays benötigt, kann er bereits nach der Berechnung des ersten Arrays gestartet werden. Die restlichen drei werden überlappend berechnet:

MDCT 4

Schritt 4: Parallele Ausführung der MDCT
Die MDCT kann für jeden Kanal unabhängig voneinander ausgeführt werden. Dafür wird die Task in zwei Sub-Tasks aufgeteilt:

MDCT 5

Schritt 5: Weitere Überlappungen mit PSY
Die Block Types werden in PSY in zwei Phasen berechnet. Bereits nach der ersten Phase können die ersten beiden xr-Arrays berechnet werden:

MDCT 6

Schritt 6: Entfernen der MDCT-Container-Task
Durch die Aufteilung der MDCT in zwei Sub-Tasks hat die eigentliche Task keine sinnvolle Aufgabe mehr. Sie wird entfernt und die bisherigen Sub-Tasks greifen nun direkt auf die Samples und die Block Types zu:

MDCT 7

Der nächste Schritt
Die aktuelle Version implementiert Schritt 6, es geht aber noch besser: Die Berechnung der Subband-Samples kann in eine separate Task übertragen werden, in der schon Samples für die kommenden Frames berechnet werden können. Das werde ich als Nächstes in Angriff nehmen.

Welche Phase (PSY oder Quantisierer) ich danach parallelisieren werde, weiss ich aktuell noch nicht. Eins kann ich aber schon vorweg sagen, dass auf ähnliche Weise wie hier bei der MDCT einiges herauszuholen ist!

Bis bald!

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>