2014-11-11 2 views
0

커널에 객체를 전달하려고합니다. 이 객체는 기본적으로 두 개의 변수를 가지며, 하나는 입력으로, 다른 하나는 커널의 출력으로 사용됩니다. 그러나 커널을 시작하면 출력 변수가 변경되지 않습니다. 그러나 다른 변수를 커널에 추가하고이 변수에도 출력 값을 할당하면 갑자기 두 변수 모두에서 작동합니다.CUDA 커널 함수 출력 변수가 수정되지 않았습니다.

다른 스레드 (While loop fails in CUDA kernel)에서 출력을 생성하지 않으면 컴파일러가 최적화를 위해 커널을 비어있는 것으로 평가할 수 있다고 읽었습니다.

그래서 커널 인수로 전달하는 입력/출력 객체가 컴파일러에 의해 출력으로 인식되지 않을 수 있습니까? 그리고 그것이 사실이라면. 이 문제를 방지 할 수있는 컴파일 옵션과 같은 우아한 방법이 있습니까? (다른 커널 인수를 추가하지 않으려합니다.)

이것은이 객체의 클래스입니다.

class Replica 
{ 
    public : 
     signed char gA[1024]; 
     int MA; 
    __device__ __host__ Replica(){ 
    } 
}; 

그리고 이것은 기본적으로 합계 감소입니다.

__global__ void sumKerA(Replica* Rd) 
{ 
    int t = threadIdx.x; 
    int b = blockIdx.x; 

    __shared__ signed short gAs[1024]; 
    gAs[t] = Rd[b].gA[t]; 

    for (unsigned int stride = 1024 >> 1; stride > 0; stride >>= 1){ 
     __syncthreads(); 
     if (t < stride){ 
      gAs[t] += gAs[t + stride]; 
     } 
    } 
    __syncthreads(); 

    if (t == 0){ 
     Rd[b].MA = gAs[0]; 
    } 
} 

마침내 내 호스트 코드.

int main() 
{ 
    // replicas - array of objects 
    Replica R[128]; 
    for (int i = 0; i < 128; ++i){ 
     for (int j = 0; j < 1024; ++j){ 
      R[i].gA[j] = 2*(rand() % 2) - 1; 
     } 
     R[i].MA = 0; 
    } 

    Replica* Rd; 

    cudaSetDevice(0); 

    cudaMalloc((void **)&Rd,128*sizeof(Replica)); 
    cudaMemcpy(Rd,R,128*sizeof(Replica),cudaMemcpyHostToDevice); 

    dim3 DimBlock(1024,1,1); 
    dim3 DimGridA(128,1,1); 

    sumKerA <<< DimBlock, DimGridA >>> (Rd); 
    cudaThreadSynchronize(); 

    cudaMemcpy(&R,Rd,128*sizeof(Replica),cudaMemcpyDeviceToHost); 
    // cudaMemcpy(&M,Md,128*sizeof(int),cudaMemcpyDeviceToHost); 
    for (int i = 0; i < 128; ++i){ 
     cout << R[i].MA << " "; 
    } 

    cudaFree(Rd); 

    return 0; 
} 

답변

0

축소 코드를 기반으로하면 블록 당 1024 개의 스레드를 실행하려는 것으로 보입니다. 이 경우

,이 올바르지 않습니다

dim3 DimBlock(1024,1,1); 
dim3 DimGridA(128,1,1); 

sumKerA <<< DimBlock, DimGridA >>> (Rd); 

제 커널 구성 파라미터는 상기 그리드의 치수이다. 두 번째 매개 변수는 스레드 블록의 크기입니다. 128 개 블록을 실행하는 동안, 블록 당 1024 개 스레드를 원하는 경우, 커널의 출시는 다음과 같아야합니다

sumKerA <<< DimGridA, DimBlock >>> (Rd); 

당신은 당신의 코드에 proper cuda error checking를 추가하는 경우 블록을 사용하기 때문에, 나는 당신이 커널 발사 실패를 볼 것 기대 128 요소의 Rd 배열에 색인을 붙일 변수 (blockIdx.x)는 원래의 경우 배열의 끝을 넘어 색인을 붙일 것입니다.

커널에서 Rd이 가리키는 복제본 개체를 수정하면 외부에서 볼 수있는 상태가되므로 해당 개체를 수정하는 모든 코드를 컴파일러에서 "최적화"할 수 없습니다.

또한 cudaThreadSynchronize()cudaDeviceSynchronize() 찬성 (그들은 같은 동작을합니다.)

+0

예, 당신은 로버트 맞다에서 더 이상 사용되지 않습니다 있습니다. 복잡한 시뮬레이션을위한 코드를 생성하고 있으며이 코드를 시뮬레이션에 사용할 수있는 새로운 프로그래밍 방식으로 시도했습니다. 불행히도, 나는 사소한 실수를 저질렀는데, 내 마음이 다른 곳으로 집중되었다. 나는 그것이 전에 나에게 일어나지 않았기 때문에 부끄럽다. 어쩌면 그건 나 같은 게으른 프로그래머가되는 처벌 일 것입니다. 정말로 오류 검사를 사용해야합니다. 모든 도움에 감사드립니다. –