2013-05-02 5 views
0

나는 cuda에서 2 차원 어레이를 생성하고 초기화하려고 시도하지만 비참하게 실패하고 있습니다. 여기 내 초기화 커널의 :cudaMallocPitch로 할당 된 메모리에 액세스

__global__ void initMap(float* map, size_t pitch, int w, int h, int numX, int numY){ 
int idx=blockIdx.x*blockDim.x+threadIdx.x; 
int idy=blockIdx.y*blockDim.y; 
int i; 
int j; 
for (i=0; i<numX; i++){ 
    for (j=0; j<numY; j++){ 
     int idMC=idx+i; 
     int idMR=threadIdx.y+j; 
     if(idMC<w && idy+idMR<h){ 
      float* row=(float*)(map+idy+idMR*pitch); 
      row[idMC]=0.5; 
     } 
    } 
} 

__syncthreads(); 
} 

그리고 여기에 내가 배열을 할당하고 메인의 초기화 커널 호출 방법 : 기본적으로

int width=map_size; 
int height=map_size; 
float* map; 
size_t pitch; 
checkCudaErrors(cudaMallocPitch(&map, &pitch, width*sizeof(float), height)); 
int numT=32; 
int numBX=(int)ceil((float)width/numT); 
int numBY=(int)ceil((float)height/numT); 
dim3 numBlocks(numBX, numBY); 
dim3 numThr(numT, numT); 
initMap <<<numBlocks, numThr>>> (map, pitch/sizeof(float), width, height, 1, 1); 
cudaError_t err=cudaGetLastError(); 
if (err != cudaSuccess) 
    printf("Error: %s\n", cudaGetErrorString(err)); 
checkCudaErrors(cudaDeviceSynchronize()); 

을, 나는 2 차원 배열을 분할 할 일은 노력하고있어 32x32 청크로 변환하고 각각을 0.5로 채울 블록에 지정합니다. 그러나 배열을 디스크에 쓰거나 다른 커널에서 요소에 액세스하려고하면 많은 QNAN이 있다는 것을 알 수 있습니다. 그래서 전체 배열을 채우지 않고 일부 스팟이 누락 된 것 같습니다. 이 같은

+0

nevermind, 초기화 할 때 idy + idMR 주위에 대괄호를 넣는 것을 잊어 버렸습니다. – Orgrim

+0

여전히 올바르지 않습니다. 작동하는 동안 우연히 만 작동합니다. 피치가 할당 워드 크기의 라운드 배수라는 보장은 없습니다. cudaMallocPitch에 대한 문서에는 커널 코드의 정확한 피치 사용이 포함되어 있습니다. – talonmies

+0

그것은 (char *)로 캐스트 된 것입니다. 맞습니까? 나는 그곳에서 무엇이 행해졌는지에 관해서는 분명히 밝혀지지 않았기 때문에 그것을 사용하지 않았습니다. 나 한테 설명해 줄래? 감사! – Orgrim

답변

1

뭔가 작업을해야합니다 :

__global__ void initMap(float* map, size_t pitch, int w, int h, int numX, int numY){ 
    int col = threadIdx.x + (blockDim.x * blockIdx.x); 
    int row = threadIdx.y + (blockDim.y * blockIdx.y); 

    if ((row < h) && (col < w)){ 
    float *myrow = (float *)(((char *)map)+(row*pitch)); 
    myrow[col] = 0.5f; 
} 

이것은 pitch 매개 변수는 방법 cudaMallocPitch 세트 그것입니다 바이트의 번호로 전달됩니다 가정합니다. 그래서 우리가 먼저해야 할 일은 mapchar 포인터로 변환하는 것입니다. 그런 다음 선택한 행을 기반으로 올바른 피치 오프셋을 추가하고 결과 포인터를 float 포인터로 변환합니다. 그런 다음 float 포인터를 사용하여 선택한 행에 색인을 생성합니다. 행에 w보다 큰 인덱스에있는 모든 "팬텀"요소는이 초기화되지 않습니다

initMap <<<numBlocks, numThr>>> (map, pitch, width, height, 1, 1); 

참고 :

따라서 커널 호출로 조정해야한다. 그들은 쓰레기를 담을 것입니다. 하지만 어쨌든 그 요소를 사용하거나 신경 쓸 필요는 없습니다.

이 배열을 다시 호스트에 복사 할 때 cudaMemcpy2D을 사용해야합니다. 올바르게 설정하면 복사 프로세스 중에 팬텀 요소가 호스트로 다시 제거되므로 호스트 배열에 가비지 데이터가 없어야합니다. 그래서 cudaMallocPitch/cudaMemcpy2D를 올바르게 사용하는 방법을 보여주는 많은 질문이 있습니다.

관련 문제