Manugal
22-09-2010, 10:59
Ciao a tutti!
Sono giorni che sto impazzendo su questo problema. Devo fare il porting di un programma Matlab in CUDA. La situazione in CUDA è la seguente:
- Ho definito alcune variabili: Nblock = 1014, Ncell = 256
- Inizialmente lancio un kernel che restituisce una matrice di (Nblock-1)*Ncell elementi (in realtà è un array di cufftComplex di dimensione (Nblock-1)*Ncell). Tale array, chiamato snap_shot, ha gli stessi valori di quelli prodotti dal suo equivalente in Matlab (solo che in Matlab è proprio una matrice e non un array).
- Dopo questo kernel, ho bisogno di calcolare la FFT su questa matrice/vettore. Su Matlab viene lanciata la seguente istruzione:
// temp_fft alla fine del calcolo sarà una matrice di 1024*256 elementi
temp_fft = fft(snap_shot, 2^nextpow2(Nblock), 1); % 2^nextpow2(Nblock)==1024
In CUDA invece ho lanciato le seguenti istruzioni:
int main(int argc, char *argv[]) {
...
float2 *dAmb;
cudaMalloc((void **) &dAmb, nxtPow2Nblock*Ncell*sizeof(float2));
cufftComplex *dsnap_shot;
cudaMalloc((void **) &dsnap_shot, nxtPow2Nblock*Ncell*sizeof(cufftComplex));
cufftComplex *temp_fft;
cudaMalloc((void **) &temp_fft, nxtPow2Nblock*Ncell*sizeof(cufftComplex));
cufftHandle plan;
cufftPlan2d(&plan,Ncell,nxtPow2Nblock,CUFFT_C2C); // La eseguo con la dimensione x e y scambiata di posto, perché Matlab tratta le matrici in column-major order. Ma anche se metto x e y al loro posto il risultato è lo stesso
float2 *hAmb;
cudaMallocHost((void **) &hAmb, nxtPow2Nblock*Ncell*sizeof(float2));
...
ambfunc_kern<<<numBlocks,numThreads>>>(dhNc,dhNblock,Nblock,block_size,dsnap_shot); // Alla fine del kernel dsnap_shot avrà i valori calcolati correttamente (in confronto a Matlab)
cudaThreadSynchronize();
cufftExecC2C(plan,dsnap_shot,temp_fft,CUFFT_FORWARD); // Dopo la FFT, temp_fft avrà valori sballati (in confronto a Matlab)
cudaThreadSynchronize();
fftshift_kern<<<numBlocks,numThreads>>>(temp_fft,nxtPow2Nblock*Ncell,nxtPow2Nblock,block_size,dAmb);
cudaMemcpy(hAmb,dAmb,nxtPow2Nblock*Ncell*sizeof(float2),cudaMemcpyDeviceToHost);
...
}
Quindi il problema è che la FFT di CUDA mi restituisce risultati differenti da quella di Matlab. Non riesco a capire perché, mi pare di aver fatto tutto bene.
P.S.: Già ho cercato sui forum di nVidia e di Matlab e dicono che il problema è dovuto al fatto che CUDA tratta i vettori/matrici in row-major order mentre Matlab in column-major order e inoltre perché CUDA memorizza i numeri complessi in modo interfogliato (cioè attraverso un'Array of Struct), mentre Matlab memorizza la parte reale e immaginaria separatamente (cioè attraverso una Struct of Array). Però nel mio caso non capisco cosa altro debba fare per far combaciare i risultati.
Sono giorni che sto impazzendo su questo problema. Devo fare il porting di un programma Matlab in CUDA. La situazione in CUDA è la seguente:
- Ho definito alcune variabili: Nblock = 1014, Ncell = 256
- Inizialmente lancio un kernel che restituisce una matrice di (Nblock-1)*Ncell elementi (in realtà è un array di cufftComplex di dimensione (Nblock-1)*Ncell). Tale array, chiamato snap_shot, ha gli stessi valori di quelli prodotti dal suo equivalente in Matlab (solo che in Matlab è proprio una matrice e non un array).
- Dopo questo kernel, ho bisogno di calcolare la FFT su questa matrice/vettore. Su Matlab viene lanciata la seguente istruzione:
// temp_fft alla fine del calcolo sarà una matrice di 1024*256 elementi
temp_fft = fft(snap_shot, 2^nextpow2(Nblock), 1); % 2^nextpow2(Nblock)==1024
In CUDA invece ho lanciato le seguenti istruzioni:
int main(int argc, char *argv[]) {
...
float2 *dAmb;
cudaMalloc((void **) &dAmb, nxtPow2Nblock*Ncell*sizeof(float2));
cufftComplex *dsnap_shot;
cudaMalloc((void **) &dsnap_shot, nxtPow2Nblock*Ncell*sizeof(cufftComplex));
cufftComplex *temp_fft;
cudaMalloc((void **) &temp_fft, nxtPow2Nblock*Ncell*sizeof(cufftComplex));
cufftHandle plan;
cufftPlan2d(&plan,Ncell,nxtPow2Nblock,CUFFT_C2C); // La eseguo con la dimensione x e y scambiata di posto, perché Matlab tratta le matrici in column-major order. Ma anche se metto x e y al loro posto il risultato è lo stesso
float2 *hAmb;
cudaMallocHost((void **) &hAmb, nxtPow2Nblock*Ncell*sizeof(float2));
...
ambfunc_kern<<<numBlocks,numThreads>>>(dhNc,dhNblock,Nblock,block_size,dsnap_shot); // Alla fine del kernel dsnap_shot avrà i valori calcolati correttamente (in confronto a Matlab)
cudaThreadSynchronize();
cufftExecC2C(plan,dsnap_shot,temp_fft,CUFFT_FORWARD); // Dopo la FFT, temp_fft avrà valori sballati (in confronto a Matlab)
cudaThreadSynchronize();
fftshift_kern<<<numBlocks,numThreads>>>(temp_fft,nxtPow2Nblock*Ncell,nxtPow2Nblock,block_size,dAmb);
cudaMemcpy(hAmb,dAmb,nxtPow2Nblock*Ncell*sizeof(float2),cudaMemcpyDeviceToHost);
...
}
Quindi il problema è che la FFT di CUDA mi restituisce risultati differenti da quella di Matlab. Non riesco a capire perché, mi pare di aver fatto tutto bene.
P.S.: Già ho cercato sui forum di nVidia e di Matlab e dicono che il problema è dovuto al fatto che CUDA tratta i vettori/matrici in row-major order mentre Matlab in column-major order e inoltre perché CUDA memorizza i numeri complessi in modo interfogliato (cioè attraverso un'Array of Struct), mentre Matlab memorizza la parte reale e immaginaria separatamente (cioè attraverso una Struct of Array). Però nel mio caso non capisco cosa altro debba fare per far combaciare i risultati.