FFTW / CUFFT (同様の API を持っています) を使用して、多次元配列の特定の軸に対して fft を実行する効率的な方法はありますか?
形状 (2, 3, 4) の 3D 配列があるとします。ストライドは (12, 4, 1) です。つまり、最後の軸に沿って 1 単位移動するには、フラット配列で 1 単位移動しますが、最初の軸に沿って 1 単位移動するには、ステップ オーバーする必要があります。 3 * 4 = 12 単位。(配列は、軸が転置されたときに他のストライドを持つことができるnumpy ndarrayですが、与えられたストライドでこの特定の3Dケースだけに対処する答えに満足しています)
ここで、中央の軸に沿って1D fftを計算したいとしましょう。CUFFT は次の関数を公開します。
cufftResult cufftPlanMany(
cufftHandle *plan, // Plan to be initialized
int rank, // Rank = 1 for 1D fft
int *n, // shape of the fft = 3
int *inembed,
int istride,
int idist,
int *onembed,
int ostride,
int odist,
cufftType type, // e.g. 64 bit float to 128 bit complex
int batch // Could use batch = 2 for the first axis
);
変換を行うには、、、パラメーターが必要nembed
だと思います。それらはここに文書化されています:
http://docs.nvidia.com/cuda/cufft/index.html#advanced-data-layoutstride
dist
デュメンテーションは、1D fft の場合、位置 x のバッチ b の要素が次から取得されることを示しています。
input[b * idist + x * istride]
ただし、位置 [b][x][z] の要素は次の場所に格納されます。
input[b * 12 + x * 4 + z]
そのため、CUFFT を 3 番目 (z) 軸でループさせる方法が明確ではありません。
私が設定した場合:
- idist と odist を 3*4=12 にします (b をインクリメントすると、最初の軸に沿って移動します)。
- istride と ostride を 4 にします (x の増分は、fft したい軸である 2 番目の軸に沿って移動します)。
- バッチ = 2
- inembed と onembed を 3 に (ただし、ドキュメントによると、これらは 1D 変換では無視されます)
次に、最後の軸インデックスが 0 である 2 つのバッチのそれぞれについて正しい fft を計算しますが、最後のインデックスが 1、2、または 3 であるサブ配列はそのままにします。
これは一般的なユースケースのように思えますが、複数の呼び出し (GPU ではコストがかかります) を実行したり、異なるメモリ レイアウトでコピーを作成したりせずに、指定されたパラメーターでこれを行う方法を理解できないようです。