2012-04-29 4 views
0

後のメモリ内のデータの破損は、このコードを見てください:クーダ:カーネルコール

#include <stdlib.h> 
#include <stdio.h> 

int N, L, I; 
float * inputs; 
float * temp; 

// first kernel 
__global__ void mulKernel (float * output, float * inputs)///, float * weights) 
{ 
    int idx = blockIdx.x * blockDim.x + threadIdx.x; 

    output [idx] = inputs [idx] * 3;//weights [idx]; 
    //weights [idx] = 4; 

    //__syncthreads(); 
} 

//second kernel 
__global__ void sumKernel (float * output, float * input) 
{ 
    int idx = blockIdx.x * blockDim.x + threadIdx.x; 
    output [idx] = input[idx]*2; 

    __syncthreads(); 
} 

void printVector (const float *p, const int N) { 
    for (int i=0; i<N; i++) 
    printf("%f\n",p[i]); 
} 

int main(int argc, char *argv[]) 
{ 
    if(argc < 3) 
     printf("Usage: cuda <layers> <inputs>\n"); 
    else 
    { 
     L = atoi(argv[1]); 
     N = atoi(argv[2]); 
     I = atoi(argv[2]); 
     inputs = (float*)malloc(I*sizeof(float)); 
     float * weights = (float*)malloc(I*sizeof(float)); 

     // and fill with some arbitrary values 
     for (int i=0; i<I; i++) 
     { 
      inputs[i] = 1; 
     } 
     for (int i=0; i<I; i++) 
     { 
      weights[i] = 1.5; 
     } 

     // allocate device memory 
     float * devInputs = NULL; 
     float * devTemp = NULL; 
     float * devWeights = NULL; 

     cudaMalloc ((void**)&devInputs, I*sizeof(float)); 
     cudaMalloc ((void**)&devTemp, I*sizeof(float)); 
     cudaMalloc ((void**)&devWeights, I*sizeof(float)); 

     // set kernel launch configuration 
     dim3 threadsMul = dim3(512, 1); 
     int blocksCount = floor(I/threadsMul.x) + 1; 
     dim3 blocksMul = dim3(blocksCount, 1); 

     dim3 threadsSum = dim3(512, 1); 
     blocksCount = floor(I/threadsSum.x) + 1; 
     dim3 blocksSum = dim3(blocksCount, 1); 

     cudaMemcpy  (devInputs, inputs, I*sizeof(float), cudaMemcpyHostToDevice); 
     cudaMemcpy  (devWeights, weights,I*sizeof(float), cudaMemcpyHostToDevice); 

     //kernels calling in this cycle 
     for(int j=0;j<L;j++) 
     { 
      // copying data to see that's ok 
      cudaMemcpy  (inputs, devInputs, I*sizeof(float), cudaMemcpyDeviceToHost); 
      cudaMemcpy  (weights, devWeights, I*sizeof(float), cudaMemcpyDeviceToHost); 

      // print it 
      printf("inputs:\n"); 
      printVector (inputs, N); 
      printf("weights:\n"); 
      printVector (weights, N); 
      printf("\n"); 

      // running first kernel 
      mulKernel<<<blocksMul, threadsMul>>>(devTemp, devInputs);//, devWeights); 

      // copying and printing data. We can see thats array weights contains a wrong values 
      cudaMemcpy  (inputs, devInputs, I*sizeof(float), cudaMemcpyDeviceToHost); 
      cudaMemcpy  (weights, devWeights, I*sizeof(float), cudaMemcpyDeviceToHost); 

      printf("inputs:\n"); 
      printVector (inputs, N); 
      printf("weights:\n"); 
      printVector (weights, N); 
      printf("\n"); 

      if(cudaDeviceSynchronize() == cudaSuccess) 
      printf("threads syncronized\n"); 

      cudaMemcpy  (inputs, devInputs, I*sizeof(float), cudaMemcpyDeviceToHost); 
      cudaMemcpy  (weights, devWeights, I*sizeof(float), cudaMemcpyDeviceToHost); 

      printf("inputs:\n"); 
      printVector (inputs, N); 
      printf("weights:\n"); 
      printVector (weights, N); 
      printf("\n"); 

      sumKernel<<<blocksSum, threadsSum>>>(devInputs, devTemp); 

      cudaMemcpy  (inputs, devInputs, I*sizeof(float), cudaMemcpyDeviceToHost); 
      cudaMemcpy  (weights, devWeights, I*sizeof(float), cudaMemcpyDeviceToHost); 

      printf("inputs:\n"); 
      printVector (inputs, N); 
      printf("weights:\n"); 
      printVector (weights, N); 
      printf("\n\n"); 

      if(cudaDeviceSynchronize() == cudaSuccess) 
      printf("threads syncronized\n"); 

      cudaMemcpy  (inputs, devInputs, I*sizeof(float), cudaMemcpyDeviceToHost); 
      cudaMemcpy  (weights, devWeights, I*sizeof(float), cudaMemcpyDeviceToHost); 

      printf("inputs:\n"); 
      printVector (inputs, N); 
      printf("weights:\n"); 
      printVector (weights, N); 
      printf("\n\n"); 
     } 

     cudaMemcpy  (inputs, devInputs, I*sizeof(float), cudaMemcpyDeviceToHost); 

     cudaFree   (devInputs ); 
     cudaFree   (devTemp ); 
     cudaFree   (devWeights ); 

     printVector (inputs, N); 

     free(inputs); 
     free(weights); 
    } 
    return 0; 
} 

を、出力を見て。最初のカーネルを呼び出した後、devWeights配列はそのデータを失いました。しかし、それはどこにも使われていません。私はそれをメモリにコピーし、カーネル(それには影響しません)を実行し、ホストにコピーし直します。そして出力において、私はそれが変わったことが分かります。どうして?私は間違って何をしていますか?

主な機能では、サイクルが表示されます。その中で私は2つのカーネル、sumKernelとmulKernelを実行します。カーネルを走らせる前、同期後、同期後にスレッドをホストして印刷します。だから、私はカーネルを呼び出した後に間違ったデータを見る。コードのコメントを参照してください。

エラーは表示されません(cudaSuccessのみ)。

+3

CUDAエラーはまったくチェックされません。エラーをチェックしないと、何かが間違っているかどうかは決して分かりません。 – harrism

+1

カーネルのコールコードがなければ、私たちはちょうど推測することができます。どのように変わったのですか?正しい引数で正しい順序でカーネルを呼び出したことは確かですか? – djmj

+1

「出力を見てください」と尋ねます。しかし、どのように見えるか、コードが何をするか(あるいは問題が発生したときに使用するコマンドライン引数の値)について何も説明していない。あなたのコードが何をすべきかを知っている他の人はどうやってその問題を特定するのに役立つのでしょうか?あるいは、問題を引き起こすためにコードをどのように実行するのかを教えてください。 – talonmies

答えて

0

ああ、エラーが見つかりました。カーネルで(idx < N)を使用していて、CUDAが配列の次元を外したときにCUDAがエラーを出力しなかった場合、使用するのを忘れました。ですから、入力配列を変更したとき、入力後にメモリ内にあるデータも変更しました。