A weird problem when using CUDA
다음은 CUDA by Example 책의 p.67에 있는 예제를 기반으로 작성한 코드이다.
#include <iostream> using namespace std; #include <cuda.h> #include <cuda_runtime.h> __global__ void Add( int* a, int* b, int* c, int N ) { int idx = threadIdx.x + blockIdx.x * blockDim.x; while( idx < N ) { c[idx] = a[idx] + b[idx]; idx += blockDim.x * gridDim.x; } } int main( int argc, char* argv[] ) { const int N = 35 * 1024; int* a = (int*)malloc(N*sizeof(int)); int* b = (int*)malloc(N*sizeof(int)); int* c = (int*)malloc(N*sizeof(int)); // fill the arrays 'a' and 'b' on the CPU for( int i=0; i<N; ++i ) { a[i] = i; b[i] = 3*i; c[i] = 0; } // allocate the memory on the GPU int* dev_a; cudaMalloc((void**)&dev_a,N*sizeof(int)); int* dev_b; cudaMalloc((void**)&dev_b,N*sizeof(int)); int* dev_c; cudaMalloc((void**)&dev_c,N*sizeof(int)); // copy the arrays 'a' and 'b' to the GPU cudaMemcpy(dev_a,a,N*sizeof(int),cudaMemcpyHostToDevice); cudaMemcpy(dev_b,b,N*sizeof(int),cudaMemcpyHostToDevice); Add<<<64,64>>>( dev_a, dev_b, dev_c, N ); // copy the array 'c' back from the GPU to the CPU cudaMemcpy(c,dev_c,N*sizeof(int),cudaMemcpyDeviceToHost); // verify that the GPU did the work we requested bool success = true; for( int i=0; i<N; ++i ) { if( (a[i] + b[i]) != c[i] ) { success = false; break; } } if( success ) { cout << "Success!" << endl; } else { cout << "Failed!" << endl; } // free the memory we allocated on the GPU cudaFree(dev_a); cudaFree(dev_b); cudaFree(dev_c); // free the memory we allocated on the CPU free(a); free(b); free(c); return 0; }
이 코드를 가지고 테스트를 하던 중 이상한 일을 겪게 되었다. Line 13을 주석(comment) 처리를 하더라도 정상적인 결과가 나오는 황당함을 겪게 되었다.
반나절 고민 끝에 찾아낸 이유는 너무나도 간단했다. 이전 실행에서의 dev_c에 대한 결과가 GPU memory상에 남아있었고, 주석 처리를 한 후에 다시 compile할 때 dev_c는 이전과 동일한 주소를 가리키도록 실행파일이 만들어 지기 때문에, 일단 한 번 실행을 한 이후에는 Line 13을 주석 처리 하더라도 정상적인 결과가 나오게 된다. 만약 Line 43에 다음과 같은 코드를 추가해주게 되면 주석 처리 후 예상했던 대로 작동하게 된다.
cudaMemcpy(dev_c,c,N*sizeof(int),cudaMemcpyHostToDevice);