-1

FFT とウィンドウ法を使用して相互相関を比較しようとしています。

私のMatlabコードは次のとおりです。

isize = 20;
n = 7;
for i = 1:n %%7x7 xcorr
  for j = 1:n
    xcout(i,j) = sum(sum(ffcorr1 .* ref(i:i+isize-1,j:j+isize-1))); %%ref is 676 element array and ffcorr1 is a 400 element array
  end
end

同様の CUDA カーネル:

__global__ void xc_corr(double* in_im, double* ref_im, int pix3, int isize, int n, double* out1, double* temp1, double* sum_temp1)
{

    int p = blockIdx.x * blockDim.x + threadIdx.x;
    int q = 0;
    int i = 0;
    int j = 0;
    int summ = 0;

    for(i = 0; i < n; ++i)
    {
        for(j = 0; j < n; ++j)
        {
            summ  = 0; //force update
            for(p = 0; p < pix1; ++p)
            {
                for(q = 0; q < pix1; ++q)
                {
                    temp1[((i*n+j)*pix1*pix1)+p*pix1+q] = in_im[p*pix1+q] * ref_im[(p+i)*pix1+(q+j)];               
                    sum_temp1[((i*n+j)*pix1*pix1)+p*pix1+q] += temp1[((i*n+j)*pix1*pix1)+p*pix1+q];
                    out1[i*n+j] = sum_temp1[((i*n+j)*pix1*pix1)+p*pix1+q];
                }
            }       
        }
    }

これをカーネルで次のように呼び出しました

int blocksize = 64; //multiple of 32
int nblocks = (pix3+blocksize-1)/blocksize; //round to max pix3 = 400
xc_corr <<< nblocks,blocksize >>> (ffcorr1, ref_d, pix3, isize, npix, xcout, xc_partial);
cudaThreadSynchronize();

どういうわけか、出力ファイルで diff を実行すると、CUDA カーネルが最初の 400 要素のみを計算することがわかります。

このカーネルを書く正しい方法は何ですか??

また、カーネルで以下に示すように i,j を宣言することの違いは何ですか??

int i = blockIdx.x * blockDim.y + threadIdx.x * threadIdx.y;
int j = blockIdx.y * blockDim.x + threadIdx.x * threadIdx.y;
4

1 に答える 1

5
int blocksize = 64; //multiple of 32
int nblocks = (pix3+blocksize-1)/blocksize; //round to max pix3 = 400
xc_corr <<< nblocks,blocksize >>> (ffcorr1, ref_d, pix3, isize, npix, xcout, xc_partial);

は、ブロックごとに 64 スレッドを起動していることを意味し、スレッドブロックの数は、pix3 要素を処理するために必要な数よりも 1 つ多いことを意味します。pix3 が実際に 400 の場合、7 つのスレッドブロックを起動し、それぞれが 64 ポイントを実行し、そのうち 48 は何も実行しないため、400 の要素を処理していることになります。

ここで何が問題なのかよくわかりません。

また、

int i = blockIdx.x * blockDim.y + threadIdx.x * threadIdx.y;
int j = blockIdx.y * blockDim.x + threadIdx.x * threadIdx.y;

blocksize と nblocks は実際には dim3 ベクトルに変換されるため、(x,y,z) 値を持ちます。<<64,7>> でカーネルを呼び出すと、次のように変換されます。

dim3 blocksize(64,1,1);
dim3 nblocks(7,1,1);
kernel<<blocksize,nblocks>>();

したがって、カーネル呼び出しごとに、blockIdx にはスレッド ID x、y、および z の 3 つのコンポーネントがあり、現在のスレッドの 3D グリッドに対応しています。あなたの場合、x コンポーネントしかないため、blockIdx.y および threadIdx .y はすべて 1 になります。したがって、本質的に、それらは役に立たない.

正直なところ、欠けていると思われる基本がたくさんあるので、ユーザーマニュアルから CUDA の基本を読み直す必要があるようです。ここで説明するのは経済的ではありません。ここで入手できる優れたドキュメントにすべてが書かれているからです。また、cuda でより高速な FFT が必要な場合は、CUDA の学習に関心がなければ、Nvidia の CUDA ゾーンにダウンロードしてインストールするだけで実行できるライブラリが多数あります。

頑張ってください。

PS。各カーネルの後に cudaThreadSynchronize を呼び出す必要はありません;)

于 2010-08-05T23:35:47.060 に答える