Ich versuche, die Berechnung einer FFT für Terabyte große Signaldateien zu parallelisieren. Im Moment dauert eine solche FFT mit einer Open-Source-Bibliothek viele Stunden, selbst wenn sie mit der schnellsten GPU, die ich habe, durch CUDA läuft. Das Framework, das ich an diesen Prozess anpassen möchte, ist Hadoop. Grundsätzlich verteilt Hadoop ein Problem auf folgende Weise auf eine beliebige Anzahl von Serverknoten:
• Sie teilen Ihre Eingabedatei in Paare (Schlüssel, Wert) auf.
• Diese Paare werden in einen "Map" -Algorithmus eingespeist, der Ihre (Schlüssel-, Wert-) Paare in einige andere (Schlüssel-, Wert-) Paare umwandelt, je nachdem, was Sie in die Map einfügen.
• Das Framework sammelt dann alle (Schlüssel-, Wert-) Ausgaben der Maps und sortiert sie nach Schlüssel. Außerdem werden die Werte mit demselben Schlüssel zu einem einzigen Paar zusammengefasst, sodass Sie am Ende (Schlüssel, Liste (Wert1, Wert2, ..)) Paare
• Diese Paare werden dann in einen "Reduzieren" -Algorithmus eingespeist, der wiederum mehr (Schlüssel, Wert) Paare als Ihr Endergebnis ausgibt (in eine Datei geschrieben).
Es gibt viele Anwendungen für dieses Modell in praktischen Dingen wie der Verarbeitung von Serverprotokollen, aber es fällt mir schwer, das Framework zum Zerlegen einer FFT in "Map" - und "Reduction" -Aufgaben anzuwenden, zumal ich mit DSP nicht wirklich vertraut bin.
Ich werde Sie mit dem Programmier-Hokuspokus nicht belästigen, da dies eine DSP-Frage und Antwort ist. Ich bin jedoch verwirrt darüber, welche Algorithmen für die parallele Berechnung von FFTs existieren. Map- und Reduce-Aufgaben können (technisch) nicht miteinander kommunizieren, daher muss die FFT in unabhängige Probleme aufgeteilt werden, aus denen die Ergebnisse am Ende irgendwie wieder zusammengeführt werden können.
Ich habe eine einfache Implementierung von Cooley-Tukey Radix 2 DIT programmiert, die an kleinen Beispielen funktioniert, aber die Verwendung für die rekursive Berechnung von DFTs mit ungeraden / geraden Indizes für eine Milliarde Bytes wird nicht funktionieren. Ich habe ein paar Wochen damit verbracht, viele Artikel zu lesen, darunter einen über einen MapReduce-FFT-Algorithmus (geschrieben von Tsz-Wo Sze als Teil seines Beitrags zur SSA-Multiplikation, ich kann nicht mehr als zwei Hyperlinks verknüpfen) und die "Vier-Schritt-FFT". ( hier und hier), die einander und dem, was ich zu erreichen versuche, ähnlich zu sein scheinen. Ich bin jedoch hoffnungslos schlecht in Mathematik und wende eine dieser Methoden von Hand auf eine einfache Menge von Dingen wie {1,2, 3, 4, 5, 6, 7, 8} an (wobei alle imaginären Komponenten 0 sind) mir wild falsche ergebnisse. Kann mir jemand einen effizienten parallelen FFT-Algorithmus im Klartext erklären (einen, den ich verknüpft habe oder einen anderen), damit ich ihn programmieren kann?
Edit: Jim Clay und jeder andere, der durch meine Erklärung verwirrt sein könnte, ich versuche, eine einzelne FFT der Terabyte-Datei zu machen. Ich möchte es jedoch auf mehreren Servern gleichzeitig ausführen können, um den Vorgang zu beschleunigen.
Antworten:
Ich denke, Ihr Hauptproblem ist nicht, wie der Algorithmus parallel geschaltet werden soll (was tatsächlich möglich ist), sondern die numerische Genauigkeit. FFTs einer so großen Größe sind zahlenmäßig recht knifflig. Die FFT-Koeffizienten haben die Form und wenn N sehr groß ist, wird die Koeffizientenberechnung verrauscht. Nehmen wir an, Sie habenN=240und verwenden eine 64-Bit-Arithmetik mit doppelter Genauigkeit. Die ersten 1000 Koeffizienten haben einen Realteil, der genau eins ist (obwohl dies nicht der Fall sein sollte), sodass Sie eine genauere Mathematik benötigen, die sehr ineffizient und umständlich zu verwenden ist.e−j⋅2⋅π⋅kN N=240
Sie werden auch viele Rundungs- und Kürzungsfehler ansammeln, da die Anzahl der Operationen, die in eine einzelne Ausgabenummer fließen, ebenfalls sehr groß ist. Aufgrund der Natur der FFT "jeder Ausgang hängt von jedem Eingang ab" ist die Fehlerausbreitung weit verbreitet.
Mir ist kein einfacher Weg bekannt, das zu umgehen. Ihre Anfrage ist ungewöhnlich. Die meisten Anwendungen, die eine Spektralanalyse großer Datenmengen durchführen, führen eine laufende Analyse durch, bei der dieses Problem nicht auftritt. Wenn Sie Ihre Anwendung und die damit verbundenen Einschränkungen besser beschreiben können, können wir Sie möglicherweise auf eine geeignetere Lösung hinweisen.
quelle
Anstatt zu versuchen, die FFT neu zu schreiben, können Sie versuchen, eine vorhandene FFT-Implementierung (wie z. B. die FFTW ) zu verwenden und sie wiederholt über die Überlappungs-Addition oder die Überlappungs-Addition entlang der Länge Ihres Signals (egal wie groß sie ist) anzuwenden. Methoden speichern . Dies ist möglich, indem die FFT als Faltung ausgedrückt wird .
Diese kürzeren FFTs müssen nicht miteinander kommunizieren, und das gesamte Schema entspricht den Schritten zur Kartenreduzierung.
Im Allgemeinen möchten Sie Ihr Signal X in kleinere Segmente aufteilen lassen, die sich ebenfalls überlappen können (z. B. X [0:10], X [5:15], X [10:20] ... .). Führen Sie die FFT für diese kleinen Segmente durch und kombinieren Sie sie am Ende neu, um das endgültige Segment zu erstellen. Dies passt sehr gut zu den Kartenreduzierungsoperatoren.
Während "map" können Sie Paare (Schlüssel, Wert) erzeugen, wobei "key" eine fortlaufende ID jedes Segments ist (0,1,2,3,4,5, ....) und "value" der Wert ist INDEX (oder Dateiposition) des ersten Wertes eines Segments in der Datei Ihres Signals. Wenn Ihre Datei beispielsweise mit INT32s gefüllt ist, hat der Index des zweiten Segments (oben) die 5-fache Größe von (INT32). (Oder wenn es in einem anderen Format ist, haben Sie vielleicht eine Bibliothek dafür)
Jetzt erhält jeder Worker einen (Schlüssel, Wert), öffnet eine Datei, sucht nach dem richtigen Punkt, liest M Samples daraus (wobei M 10 oben ist), führt die FFT durch und speichert sie in einer Datei mit einem Namen, zum Beispiel " RES_ [INKEY] .dat "und gibt ein (Schlüssel-, Wert-) Paar zurück. In diesem Fall wäre "Schlüssel" der INDEX (der "Wert" des eingehenden (Schlüssel, Wert) Tupels) und "Wert" der Name der Datei, die die FFT-Ergebnisse enthält. (Wir werden darauf zurückkommen)
In "Reduzieren" können Sie jetzt entweder Überlappung hinzufügen oder Überlappung speichern, indem Sie einen (Schlüssel, Wert) aus dem Schritt "Map" akzeptieren, diese Datei öffnen, die FFT-Ergebnisse laden, entweder oa oder os ausführen und sie dann speichern den richtigen INDEX in Ihrer Ausgabedatei. (Siehe Pseudocode in diesem (oder jenem ) Schritt "map" behandelt das "yt = ..." parallel und der Schritt "reduction" behandelt den Teil "y (i, k) = ...".)
Möglicherweise müssen Sie einige Dateien jonglieren, um den Datenverkehr im Netzwerk oder die Auslastung eines Servers zu verringern, auf dem sich möglicherweise Ihre eigentliche Datendatei befindet.
quelle
Genauer gesagt, es ist nicht erforderlich, MR während der gesamten Rekursion zu verwenden. Dies ist in der Tat recht ineffizient. Ihr Problem kann in eine Million Megabyte große innere und äußere FFTs unterteilt werden, und diese Megabyte-FFTs können perfekt mit FFTW oder dergleichen berechnet werden. MR wird nur für die Überwachung des Daten-Shufflings und der Rekombination verantwortlich sein, nicht für die eigentliche FFT-Berechnung ...
Meine allererste Idee wäre die folgende, aber ich vermute, dass dies in einem einzigen MR mit einer intelligenteren Datendarstellung möglich ist.
Erste MR: innere FFT
Map: Führen Sie eine zeitliche Dezimierung durch und gruppieren Sie die Abtastwerte in Blöcken für die innere FFT
Reduzieren: innere FFT berechnen
Zweiter MR: äußere FFT
Karte: Gruppieren Sie die Muster für das äußere Feld und wenden Sie zwei Faktoren an
Reduzieren: äußere FFT durchführen
Proof-of-Concept-Python-Code hier.
Wie Sie sehen, mischen die Mapper nur die Reihenfolge der Daten, also unter den folgenden Annahmen:
All dies kann in einem einzigen MR durchgeführt werden, der inneren FFT im Mapper und der äußeren FFT im Reducer. Proof of Concept hier .
quelle
Wenn Ihr Signal mehrdimensional ist, kann die Parallelisierung der FFT relativ einfach durchgeführt werden. Halten Sie eine Dimension in einem MPI-Prozess zusammenhängend, führen Sie die FFT durch und transponieren Sie (altoall), um an der nächsten Dimension zu arbeiten. FFTW macht das.
Wenn die Daten 1D sind, ist das Problem viel schwieriger. Beispielsweise hat FFTW keine 1D-FFT mit MPI geschrieben. Wenn man einen Radix-2-Algorithmus für die Frequenzdezimation verwendet, können die ersten Stufen als naive DFT ausgeführt werden, sodass 2 oder 4 Knoten ohne Genauigkeitsverlust verwendet werden können (dies liegt daran, dass die Einheitswurzeln für die Die ersten Stufen sind entweder -1 oder i, mit denen man gut arbeiten kann.
Übrigens, was haben Sie mit den Daten vor, nachdem Sie sie transformiert haben? Es könnte sein, dass man etwas tut, wenn man weiß, was mit dem Ausgang passiert (z. B. eine Faltung, ein Tiefpassfilter usw.).
quelle