>

일정한 메모리를 사용할 때 문제가 발생합니다. 오류가 발생합니다 :

ERROR: an illegal memory access was encountered

커널 기능이 실행되지 않는 것 같습니다. 그러나 일정한 메모리를 선택하지 않으면 모든 것이 정상입니다. 그래서 그것은 나를 혼란스럽게 만듭니다. 나는 아주 오래 생각했다. 그러나 나는 여전히 이유가 없습니다. 문제 해결을 도와 줄 수 있습니까? 대단히 감사합니다.

변수 s가 상수 메모리를 사용하지 않으면 모든 것이 정상입니다. 그러나 s가 상수 메모리를 사용하면 프로그램이 중단됩니다.

정수 메모리를 사용한 변수는 다음과 같이 정의됩니다 :

#ifdef USE_CONST_MEM
__constant__ Sphere s[SPHERES];
#else
Sphere          *s;
#endif

커널 함수는 다음과 같이 정의됩니다 :

#ifdef USE_CONST_MEM
__global__ void kernel(unsigned char *ptr) {
    printf("ok2");
#else
__global__ void kernel(Sphere *s, unsigned char *ptr) {
#endif
    // map from threadIdx/BlockIdx to pixel position
    printf("ok2");
    int x = threadIdx.x + blockIdx.x * blockDim.x;
    int y = threadIdx.y + blockIdx.y * blockDim.y;
    int offset = x + y * blockDim.x * gridDim.x;
    REAL   ox = (x - DIM / 2);
    REAL   oy = (y - DIM / 2);
    REAL   r = 0, g = 0, b = 0;
    REAL   maxz = -INF;
    __syncthreads();
    for (int i = 0; i<SPHERES; i++) {
        REAL   n;
        REAL   t = s[i].hit(ox, oy, &n);
        if (t > maxz) {
            REAL fscale = n;
            r = s[i].r * fscale;
            g = s[i].g * fscale;
            b = s[i].b * fscale;
            maxz = t;
            printf("r: %.2f g: %.2f, b %.2f\n", r, g, b);
        }
    }
    __syncthreads();
    ptr[offset * 4 + 0] = (int)(r * 255);
    ptr[offset * 4 + 1] = (int)(g * 255);
    ptr[offset * 4 + 2] = (int)(b * 255);
    ptr[offset * 4 + 3] = 255;
}
// globals needed by the update routine
struct DataBlock {
    unsigned char   *dev_bitmap;
    CPUAnimBitmap  *bitmap;
};

커널 함수를 호출하는 함수가 있습니다.

void generate_frame(DataBlock *d, int ticks) {
    //START_GPU
    //movin the spheres
    kernelMoving << <128, 32 >> >(s, SPHERES);
    printf("ok0\n");
    // generate a bitmap from our sphere data
    dim3    grids(DIM / 16, DIM / 16);
    dim3    threads(16, 16);
#ifdef USE_CONST_MEM
    Sphere *d_s;
    cudaGetSymbolAddress((void **)&d_s, s);
    printf("ok0-1\n");
    kernel << <grids, threads >> >(s, d->dev_bitmap);
    cudaDeviceSynchronize();
    cudaError_t error = cudaGetLastError();
    if(error!=cudaSuccess)
    {
       fprintf(stderr,"ERROR: %s\n", cudaGetErrorString(error) );
       exit(-1);
    }
    printf("ok0-1-1\n");
#else
    printf("ok0-2\n");
    kernel << <grids, threads >> >(s, d->dev_bitmap);
#endif
    printf("ok1\n");
    //END_GPU
    HANDLE_ERROR(cudaMemcpy(d->bitmap->get_ptr(),
        d->dev_bitmap,
        d->bitmap->image_size(),
        cudaMemcpyDeviceToHost));
}

다음과 같은 초기화 코드 :

#ifdef USE_CONST_MEM
#else
    HANDLE_ERROR(cudaMalloc((void**)&s,
        sizeof(Sphere) * SPHERES));
#endif
    // allocate temp memory, initialize it, copy to constant
    // memory on the GPU, then free our temp memory
    Sphere *temp_s = (Sphere*)malloc(sizeof(Sphere) * SPHERES);
    for (int i = 0; i<SPHERES; i++) {
        temp_s[i].r = rnd(1.0f);
        temp_s[i].g = rnd(1.0f);
        temp_s[i].b = rnd(1.0f);
        temp_s[i].x = rnd(1000.0f) - 500;
        temp_s[i].y = rnd(1000.0f) - 500;
        temp_s[i].z = rnd(1000.0f) - 500;
        temp_s[i].radius = rnd(10.0f) + 5;
        temp_s[i].dx = STEP_SIZE * ((rand() / (float)RAND_MAX) * 2 - 1);
        temp_s[i].dy = STEP_SIZE * ((rand() / (float)RAND_MAX) * 2 - 1);
        temp_s[i].dz = STEP_SIZE * ((rand() / (float)RAND_MAX) * 2 - 1);
    }
#ifdef USE_CONST_MEM
    HANDLE_ERROR(cudaMemcpyToSymbol(s, temp_s,
        sizeof(Sphere) * SPHERES));
#else
    HANDLE_ERROR(cudaMemcpy(s, temp_s, sizeof(Sphere)*SPHERES, cudaMemcpyHostToDevice));
#endif
    free(temp_s);

cuda의 버전은 8.0입니다. 시스템은 우분투 16.04입니다.

  • 답변 # 1

    예, 어디가 잘못되었는지 알고 있습니다. 상수 메모리를 사용할 때 상수 값을 수정하려고하는 kernel_moving 함수에서 값을 변경하려고합니다. 따라서 프로그램이 중단됩니다. 이제 이것으로 변경하면 작동합니다.

       #ifdef USE_CONST_MEM
        //printf("the number of SPHERES is %d\n", SPHERES);
        Sphere *temp_s = (Sphere*)malloc(sizeof(Sphere) * SPHERES);
        HANDLE_ERROR(cudaMemcpyFromSymbol(temp_s, s, sizeof(Sphere) * SPHERES,0, cudaMemcpyDeviceToHost));
        Sphere* dev_temp_s;
        cudaMalloc((void**)&dev_temp_s, sizeof(Sphere) * SPHERES);
        cudaMemcpy(dev_temp_s, temp_s, sizeof(Sphere) * SPHERES, cudaMemcpyHostToDevice);
        kernelMoving << <128, 32 >> >(dev_temp_s, SPHERES);
        cudaMemcpy(temp_s, dev_temp_s, sizeof(Sphere) * SPHERES, cudaMemcpyDeviceToHost);
        HANDLE_ERROR(cudaMemcpyToSymbol(s, temp_s, sizeof(Sphere) * SPHERES));
        free(temp_s);
        cudaFree(dev_temp_s);
        #else
        kernelMoving << <128, 32 >> >(s, SPHERES);
        #endif
    
    

관련 자료

  • 이전 스칼라에서 팩토리 패턴/메소드를 구현하는 가장 좋은 방법은 무엇입니까?
  • 다음 패키지 Java 데스크탑 앱 (그라 데)