2013-04-30 5 views
1
나는 오류가 오전

을 당 레지스터의 수 나는이 제안 오류 메시지에 대한 어떤 힌트, 온라인 확인CUDA 배정 밀도 및 스레드

too many resources requested for launch 

커널을 실행하는 동안 인해보다 더 레지스터의 사용으로 발생 각 다중 프로세서에 대해 GPU가 지정한 제한값. 장치 쿼리 결과를 다음과 같이

Device 0: "GeForce GTX 470" 
CUDA Driver Version/Runtime Version   5.0/5.0 
CUDA Capability Major/Minor version number: 2.0 
Total amount of global memory:     1279 MBytes (1341325312 bytes) 
(14) Multiprocessors x (32) CUDA Cores/MP: 448 CUDA Cores 
GPU Clock rate:        1215 MHz (1.22 GHz) 
Memory Clock rate:        1674 Mhz 
Memory Bus Width:        320-bit 
L2 Cache Size:         655360 bytes 
Total amount of constant memory:    65536 bytes 
Total amount of shared memory per block:  49152 bytes 
Total number of registers available per block: 32768 
Warp size:          32 
Maximum number of threads per multiprocessor: 1536 
Maximum number of threads per block:   1024 
Maximum sizes of each dimension of a block: 1024 x 1024 x 64 
Maximum sizes of each dimension of a grid:  65535 x 65535 x 65535 

업데이트 로버트 Crovella은 자신이 코드를 실행에 아무런 문제가 없다고 말했다, 그래서 여기 실행을위한 전체 코드를 붙여 넣습니다.

전체 코드는 다음과 같습니다

__global__ void calc_params(double *d_result_array, int total_threads) { 

     int thread_id    = threadIdx.x + (blockDim.x * threadIdx.y); 
     d_result_array[thread_id] = 1/d_result_array[thread_id]; 

} 

    void calculate() { 

    double *h_array; 
    double *d_array; 

    size_t array_size = pow((double)31, 2) * 2 * 10; 

    h_array = (double *)malloc(array_size * sizeof(double)); 
    cudaMalloc((void **)&d_array, array_size * sizeof(double)); 

    for (int i = 0; i < array_size; i++) { 
     h_array[i] = i; 
    } 

    cudaMemcpy(d_array, h_array, array_size * sizeof(double), cudaMemcpyHostToDevice); 

    int BLOCK_SIZE = 1024; 
    int NUM_OF_BLOCKS = (array_size/BLOCK_SIZE) + (array_size % BLOCK_SIZE)?1:0; 

    calc_params<<<NUM_OF_BLOCKS, BLOCK_SIZE>>>(d_array, array_size); 
    cudaDeviceSynchronize(); 
    checkCudaErrors(cudaGetLastError()); 

    cudaFree(d_array); 
    free(h_array); 

} 

이 코드를 실행하면, 내가 같은 오류, 출시

에 대한

를 요청 너무 많은 자원을 얻을 동안 대신 커널
에 역 문을 사용하여의 (즉 d_result_array [thread_id] = 1/d_result_array [thread_id])
EQUATE 문 완벽하게 작동
(즉 d_result_array [thread_id = d_result_array [thread_id] * 200).

왜? 작은 블록 크기를 사용하는 것 외에는 가능한 대안이 있습니까? 유일한 해결책이라면, 어떻게 작동 할 수있는 블록 크기가되어야 하는지를 알아야합니다.

안부,

P. cudaCheckErrors이

Build of configuration Debug for project TEST 

make all 
Building file: ../test_param.cu 
Invoking: NVCC Compiler 
nvcc -G -g -O0 -gencode arch=compute_20,code=sm_20 -odir "" -M -o "test_param.d" "../test_param.cu" 
nvcc --compile -G -O0 -g -gencode arch=compute_20,code=compute_20 -gencode arch=compute_20,code=sm_20 -x cu -o "test_param.o" "../test_param.cu" 
Finished building: ../test_param.cu 

Building target: TEST 
Invoking: NVCC Linker 
nvcc -link -o "TEST" ./test_param.o 
Finished building target: TEST 

운영 체제

#define checkCudaErrors(val) check((val), #val, __FILE__, __LINE__) 

template<typename T> 
void check(T err, const char* const func, const char* const file, const int line) { 
    if (err != cudaSuccess) { 
    std::cerr << "CUDA error at: " << file << ":" << line << std::endl; 
    std::cerr << cudaGetErrorString(err) << " " << func << std::endl; 
    exit(1); 
    } 
} 

빌드 및 OS 정보입니다 무슨 힘 싶어 사람들을 위해

Ubuntu Lucid (10.04.4) 64bit 
Linux paris 2.6.32-46-generiC#105-Ubuntu SMP Fri Mar 1 00:04:17 UTC 2013 x86_64 GNU/Linux 

가 오류 나는

를받을 알고
CUDA error at: ../test_param.cu:42 
too many resources requested for launch cudaGetLastError() 
+0

"커널에서 inverse 문을 사용하면 equate 문이 완벽하게 작동합니다"는 의미는 무엇입니까? – talonmies

+1

왜 블록 및 스레드의 1D 배열을 만들지 만 2D 배열을 필요로하는 커널을 사용하고 있습니까? 또한, 왜'int BLOCK_SIZE = 1024;'를 가지고 있고'(array_size/BLOCKSIZE)'를 사용하고있는 다음 줄에 BLOCK_SIZE와 BLOCKSIZE 중 하나가 다른 정의가 있습니까? –

+1

덧붙여서,'BLOCKSIZE'의 사용을'BLOCK_SIZE'으로 변경하면 CC 2.0 장치에 오류없이 게시 한 코드를 컴파일하고 실행할 수 있습니다. 그래서 당신이 기술 한 문제는 BLOCK_SIZE와 BLOCKSIZE에 대한 두 가지 정의가 없다면 게시 한 내용에 포함되어 있지 않다고 생각합니다.이 경우 BLOCKSIZE가 무엇인지 알려주지 않았습니다. –

답변

2

이것은 컴파일러의 아티팩트 인 것 같습니다. 문제는 nvcc 명령 행에 -Xptxas -v 옵션을 전달하여 관찰 할 수있는 레지스터 사용법 인 것 같습니다. 어떤 이유로 인해 -G 버전의 코드는 일반 코드보다 상당히 많은 레지스터 (스레드 당)를 사용합니다. 몇 가지 옵션이 있습니다.

  1. -G 스위치를 사용하지 마십시오. 이 스위치는 -G 스위치가없는 경우보다 느리게 실행될 수있는 코드를 생성하므로 디버그 용도로만 사용해야합니다.
  2. -G 스위치를 사용하려면 블록 당 스레드 수를 줄이십시오. 이 예제에서는 블록 당 768 개 이하의 스레드로 실행할 수있었습니다.
  3. 스레드 당 더 적은 레지스터를 사용하도록 컴파일러에 지시하십시오.

    nvcc -Xptxas -v -arch=sm_20 -G -maxrregcount=20 -o t145 t145.cu 
    
이 마지막 경우의 목적은 (블록 당 스레드 * 쓰레드 당 레지스터)가 블록 당 최대 레지스터보다이어야한다

: 당신은 그와 같이, -maxrregcount 스위치를 사용하여이 작업을 수행 할 수 사용중인 GPU 일반적인 CC 2.0 GPU는 블록 당 최대 32768 개의 레지스터를 사용할 수 있습니다 (deviceQuery sample으로 확인할 수 있음).

+0

감사합니다. @RobertCrovella에 대한 설명입니다. 확실히 통찰력과 대안을 제공합니다. 코드를 작성하고 오류 및 프로파일 링을위한 디버그 정보를 사용하고 있기 때문에 디버깅 및 나중에 릴리스 모드로 전환하는 동안 이러한 대안 중 일부를 사용할 수 있습니다. 다시 한번 감사드립니다. – fahad

+0

# 3 대신 [launch bounds] (http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#launch-bounds)를 사용하여 컴파일러 활동을보다 정확하게 제어 할 수 있습니다 커널별로. –

관련 문제