FFTを並列計算するためのアルゴリズム


12

テラバイトサイズの信号ファイルでFFTの計算を並列化しようとしています。現在、オープンソースライブラリを使用したこのようなFFTは、私が持っている最速のGPUでCUDAを介して実行する場合でも何時間もかかります。このプロセスに適応しようとしているフレームワークはHadoopです。非常に基本的な用語では、Hadoopは次の方法で任意の数のサーバーノードに問題を分散します。

•入力ファイルを(キー、値)のペアに分割します。
•これらのペアは「マップ」アルゴリズムに送られ、マップ内に配置したものに基づいて、(キー、値)ペアを他の(キー、値)ペアに変換します。
•次に、フレームワークは、マップからすべての(キー、値)出力を収集し、キーでソートし、同じキーを持つ値を単一のペアに集約するため、(key、list(value1、value2、 ..))ペア
•これらのペアは、「リデュース」アルゴリズムに送られ、最終結果(ファイルに書き込まれる)としてさらに(キー、値)ペアが出力されます。

サーバーログの処理など、このモデルには多くのアプリケーションがありますが、特にDSPにあまり詳しくないため、FFTを「マップ」タスクと「リデュース」タスクに分割するフレームワークを適用するのに苦労しています。

これはDSPのQ&Aであるため、私はプログラミングジャンボジャンボを気にしません。ただし、FFTを並列計算するためにどのアルゴリズムが存在するかについては混乱しています。MapとReduceタスクは(技術的に)相互に通信できないため、FFTを独立した問題に分割し、最後に結果を何らかの方法で再結合する必要があります。

Cooley-Tukey Radix 2 DITの簡単な実装をプログラミングしましたが、これは小さな例で動作しますが、10億バイトの奇数/偶数インデックスDFTを再帰的に計算するのに使用できません。MapReduce FFTアルゴリズム(Tsz-Wo SzeがSSA乗算に関する論文の一部として書いたもので、2つ以上のハイパーリンクをリンクすることはできません)と「4ステップFFT」を含む多くの論文を読むのに数週間費やしました。 (ここここ)、これは互いに似ており、私が達成しようとしていることと似ています。しかし、私は数学が絶望的に​​悪いので、{1,2、3、4、5、6、7、8}(すべての虚数成分が0)のような単純なセットにこれらの方法を手で適用すると、私は非常に間違った結果になりました。誰もが効率的な並列FFTアルゴリズムを簡単な英語(私がリンクしたものまたは他のリンク)で説明できるので、それを試してプログラムすることができますか?

編集:ジムクレイと私の説明で混乱する可能性のある他の人は、私はテラバイトファイルの単一のFFTをしようとしています。しかし、プロセスを高速化するために、複数のサーバーで同時に実行できるようにしたいと考えています。


1
正確に何を達成しようとしていますか?テラバイトの信号ファイルの単一のFFTを実行しますか、それとも各ファイルの複数の小さなFFTを実行しますか?
ジム・クレイ

回答:


13

あなたの主な問題は、アルゴリズムを並列化する方法(実際に実行可能)ではなく、数値精度であると思います。サイズが大きいFFTは、数値的に非常に注意が必要です。FFT係数はフォームである およびNが非常に大きい場合、係数の計算はノイズが多くなります。あなたが持っているとしましょうN=240を倍精度演算をビットとあなたは64を使用しています。最初の1000個の係数の実数部は正確に1であるため(そのようにするべきではありません)、より高精度の数学が必要になります。これは非常に非効率的で扱いにくいものです。ej2πkNN=240

また、単一の出力番号に入る膨大な数の操作も非常に大きいため、多くの丸めエラーと切り捨てエラーが発生します。FFTの「すべての出力はすべての入力に依存する」という性質のため、エラーの伝播はramp延しています。

私はそれを回避する簡単な方法を知りません。あなたの要求は珍しいものです。大規模なデータセットのスペクトル分析を行うほとんどのアプリケーションは、その問題がない場合に実行分析を行います。もしあなたがあなたのアプリケーションを記述できて、それがさらに多くの制約であるなら、私たちはあなたにもっと適切な解決策を示すことができます。


かなり有効なポイント..これについてもっと考えなければなりません。あなたが言うように、私は最終的に「実行分析」に頼るでしょう。
フィリップ

私は本当に遅れていることを知っていますが、万が一、あなたはそれができると言ったので、あなたはそれがどのようにできるかに関する情報源を持っていますか?
クラウディオブラッサー

4

代わりにしようとするあなたは(のような既存のFFTの実装使用して試みることができるFFT再書き込みFFTWたとえば)のいずれかを通して、あなたの信号の長さ(それがどのようにビッグに関係なく)に沿って繰り返し、それを適用するオーバーラップ加算またはオーバーラップメソッドを保存します。これは、FFTを畳み込みとして表現することで可能です。

これらの短いFFTは互いに通信する必要がなく、スキーム全体がmap-reduceステップと一致します。

一般に、目的とするのは、信号Xを、重複する可能性のある小さなセグメントに分割することです(たとえば、X [0:10]、X [5:15]、X [10:20] ... 。)。これらの小さなセグメントでFFTを実行し、最終的にそれらを再結合して最終的なセグメントを生成します。これはmap-reduce演算子に非常によく適合します。

「マップ」中に、(キー、値)のペアを生成できます。「キー」は各セグメントの連続ID(0、1、2、3、4、5、....)で、「値」は信号のファイル内のセグメントの最初の値のINDEX(またはファイル位置)。したがって、たとえば、ファイルがINT32でいっぱいの場合、2番目のセグメント(上記)のインデックスは5 * sizeof(INT32)になります。(または、それが他の形式の場合は、libを使用できます)

これで、各ワーカーは(key、value)を受け取り、ファイルを開き、適切なポイントを探し、そこからM個のサンプルを読み取り(Mは上記の10)、FFTを実行し、名前を付けてファイルに保存します。 RES_ [INKEY] .dat "と(キー、値)のペアを返します。この場合、「キー」はINDEX(着信(キー、値)タプルの「値」)になり、「値」はFFT結果を含むファイルの名前になります。(これに戻ります)

「reduce」内で、「map」ステップから(key、value)を受け入れ、そのファイルを開き、FFT結果をロードし、oaまたはosのいずれかを実行してから、それらを出力ファイルの正しいINDEX。(この(またはthis)の擬似コード参照してください。「map」ステップは「yt = ...」を並行して処理し、「reduce」ステップは「y(i、k)= ...」部分を処理します。)

ここでは、ネットワーク上のトラフィックや実際のデータファイルを含むサーバーの負荷を軽減するために、ファイルジャグリングが必要になる場合があります。


1
私は小さな塊を組み合わせて大きなサイズのFFTを取得するためのオーバーラップ加算とオーバーラップ保存の有効性についてはわかりません-それを行うために必要なFFTの2番目のパスがあることを知っている限り(サイズNのDFT = ABは、サイズBのA DFT、回転因子アプリケーション、次にサイズAのB DFTに分割できます。ただし、低解像度の出力が必要な場合は機能する可能性があります
...-pichenettes

こんにちはpicenettes、これに感謝します、私の心にあったのはこれでした(engineeringproductivitytools.com/stuff/T0001/PT11.HTM)これを答えに含めます。
A_A

2

2N

以降2N/2N/22N/2

より明確にするために、再帰全体でMRを使用する必要はありません。これは実際には非常に非効率的です。あなたの問題は数百万メガバイトのサイズの内側と外側のFFTに分解でき、それらのメガバイトFFTはFFTWなどを使用して完全に計算できます。MRは、実際のFFT計算ではなく、データのシャッフルと再結合を監視するだけです...

私の最初のアイデアは次のとおりですが、よりスマートなデータ表現を備えた単一のMRでこれを行うことができると思います。

sR=2N/2

最初のMR:内部FFT

マップ:時間内にデシメーションを実行し、内部FFTのサンプルをブロックにグループ化します

(k,v)k0..2N1vs[k]

(k%R,(k/R,v))

削減:内部FFTの計算

(k,vs)kvs(i,v)

inRin[i]=v

サイズ実行しますRinoutR

i0..R1(k,(i,out[i]))

2番目のMR:外部FFT

マップ:外側のfftのサンプルをグループ化し、回転因子を適用します

(k,(i,v))k(i,v)

kv×exp2πjk2N

削減:外部FFTを実行します

入力: kvs どこ kはブロックインデックスです。そしてvs のリストです v ペア

ベクトルを投入する n サイズの R そのような n[]=v リスト内のすべての値に対して。

サイズを実行する R FFTオン n ベクトルを取得する oあなたはt サイズの R

にとって 0R1、放出 ×R+koあなたはt[]

概念実証のPythonコードはこちら。

ご覧のとおり、マッパーはデータの順序のみをシャッフルしているため、次の前提の下で:

  • 時間の間引き(マッパー1)は、前の手順で実行できます(たとえば、データを正しい入力形式に変換するプログラムによって)。
  • MRフレームワークは、入力キーとは異なるキーへのリデューサーの書き込みをサポートしています(Googleの実装では、リデューサーは受信したキーと同じキーにのみデータを出力できます。これは、出力形式としてSSTableが使用されているためだと思います)。

これはすべて、単一のMR、マッパーの内部FFT、レデューサーの外部FFTで実行できます。ここで概念実証


あなたの実装は有望であると私は今それを行っていますが、内側のFFTリデューサーでは、「サイズ2 ^ Rからベクトルを得るためにサイズ2 ^ R FFTを実行します」と書きます。Rが2 ^(N / 2)の場合、このFFTはサイズ2 ^(2 ^ N / 2)ではなく、したがって正しくありませんか?サイズRのFFTを意味しましたか?
フィリップ

はい、混同しているようです R そして 2Rいくつかの場所で...編集しました。ヒルマーのコメントは私のアプローチに適用されることに注意してください-それ以外の場合、いくつかの回転因子(exp2πjk2N)あるべきではないが1の実数部を持つことになり、数値の不正確さをもたらします。
ピクネット

0

信号が多次元の場合、FFTの並列化はかなり簡単に実現できます。MPIプロセスで1つの次元を連続に保ち、FFTを実行し、次の次元で作業するために転置(全体)します。FFTWはこれを行います。

データが1Dの場合、問題ははるかに困難です。たとえば、FFTWはMPIを使用して1D FFTを作成しませんでした。基数2の周波数間引きアルゴリズムを使用する場合、最初のいくつかの段階は単純なDFTとして実行でき、精度を失うことなく2つまたは4つのノードを使用できます(これは、最初の段階は-1またはiのいずれかであり、どちらを使用するのが適切か)

ちなみに、データを変換したら、そのデータをどのように使用する予定ですか?出力(コンボリューション、ローパスフィルターなど)に何が起こるかを知っていれば、何かをするでしょう。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.