Fallo de inicio no especificado en Memcpy

Resuelto Ptit Sualty asked hace 9 años • 1 respuestas

Me encuentro con un "error de inicio no especificado" cuando ejecuto mi programa en Cuda. He comprobado los errores.

El programa es un solucionador de una ecuación diferencial. Itera TOTAL_ITER veces. ROOM_X y ROOM_Y son el ancho y el alto de las matrices.

Aquí está el encabezado, su nombre es "único:

#define ITER_BETWEEN_SAVES 10000
#define TOTAL_ITER 10000
#define ROOM_X 2048
#define ROOM_Y 2048
#define SOURCE_DIM_X 200
#define SOURCE_DIM_Y 1000
#define ALPHA 1.11e-4
#define DELTA_T 10
#define H 0.1
#include <stdio.h>

void Matrix(float* M);
void SolverCPU(float* M1, float* M2);
__global__ void SolverGPU(float* M1, float* M2);

Aquí está el núcleo y una función que llena una matriz:

#include "solver.h"
#include<cuda.h>

void Matrix(float* M)
{
  for (int j = 0; j < SOURCE_DIM_Y; ++j) {
    for (int i = 0; i <  SOURCE_DIM_X; ++i) {
    M[(i+(ROOM_X/2 - SOURCE_DIM_X/2)) + ROOM_X * (j+(ROOM_Y/2 - SOURCE_DIM_Y/2))] = 100;
    }
  }
}

    __global__ void SolverGPU(float* M1,float *M2)  {
   int i =threadIdx.x + blockIdx.x * blockDim.x;
       int j = threadIdx.y + blockIdx.y * blockDim.y;

        float M1_Index = M1[i + ROOM_X * j];
        float M1_IndexUp = M1[i+1 + ROOM_X * j];
        float M1_IndexDown =M1[i-1 + ROOM_X * j];
        float M1_IndexLeft = M1[i + ROOM_X * (j+1)];
        float M1_IndexRight = M1[i + ROOM_X *(j-1)];


        M2[i + ROOM_X * j] = M1_Index + (ALPHA * DELTA_T / (H*H)) * (M1_IndexUp + M1_IndexDown + M1_IndexLeft +M1_IndexRight - 4*M1_Index);     

}

Y aquí está lo principal.

int main(int argc, char* argv[] ){

    float *M1_h, *M1_d,*M2_h, *M2_d;
    int size = ROOM_X * ROOM_Y * sizeof(float);
    cudaError_t err = cudaSuccess;  

    //Allocating Memories on Host
    M1_h = (float *)malloc(size);
    M2_h = (float *)malloc(size);

    //Allocating Memories on Host
    err=cudaMalloc((void**)&M1_d, size);
    if (err != cudaSuccess) { 
        fprintf(stderr, "Failed to allocate array_d ... %s .\n", cudaGetErrorString(err)); 
        exit(EXIT_FAILURE); 
    }

    err=cudaMalloc((void**)&M2_d, size);    
    if (err != cudaSuccess) { 
        fprintf(stderr, "Failed to allocate array_d ... %s .\n", cudaGetErrorString(err)); 
        exit(EXIT_FAILURE); 
    }

    //Filling the Matrix
    Matrix(M1_h);


    //Copy on Device

    err = cudaMemcpy(M1_d, M1_h, size, cudaMemcpyHostToDevice);
    if(err !=0){
        printf("%s-%d\n",cudaGetErrorString(err),1);
        getchar();  
    }

    err=cudaMemcpy(M2_d, M2_h, size, cudaMemcpyHostToDevice);
    if(err !=0){
        printf("%s-%d",cudaGetErrorString(err),2);
        getchar();  
    }

    dim3 dimGrid(64,64);
    dim3 dimBlock(32,32);


    //SolverGPU<< <threadsPerBlock, numBlocks >> >(M1_d,M2_d);
    for(int i=0;i<TOTAL_ITER;i++) { 
    if (i%2==0) 
    SolverGPU<< <dimGrid,dimBlock >> >(M1_d,M2_d);
    else
    SolverGPU<< <dimGrid,dimBlock >> >(M2_d,M1_d);
    }   

    err=cudaMemcpy(M1_h, M1_d, size, cudaMemcpyDeviceToHost);
    if(err !=0){
        printf("%s-%d",cudaGetErrorString(err),3);
        getchar();  
    }   

    cudaFree(M1_d);
    cudaFree(M2_d);

    free(M1_h);
    free(M2_h);
    return 0;   

}

No hay ningún problema en la compilación.

Cuando reviso mis errores, aparece el "error de inicio no especificado" en la memoria MEMCPY DESPUÉS del kernel.

Ok, he leído que generalmente se debe a que el kernel no se ejecuta correctamente. Pero no puedo encontrar los errores en el kernel... Supongo que el error es bastante simple, pero no puedo encontrarlo.

Ptit Sualty avatar Dec 03 '14 23:12 Ptit Sualty
Aceptado

Cuando compilo y ejecuto tu código, obtengo:

an illegal memory access was encountered-3

impreso.

Es posible que en su lugar reciba un "error de inicio no especificado". El informe de error exacto dependerá de la versión de CUDA, la GPU y la plataforma. Pero podemos seguir adelante independientemente.

Cualquiera de los mensajes indica que el kernel se inició pero encontró un error y, por lo tanto, no pudo completarse exitosamente. Puede depurar problemas de ejecución del kernel utilizando un depurador, como cuda-gdb en Linux o Nsight VSE en Windows. Pero no necesitamos sacar el depurador todavía.

Una herramienta útil es cuda-memcheck. (En GPU más nuevas, por ejemplo, cc7.0 o más nuevas, debe usar compute-sanitizeren lugar de cuda-memcheck, pero por lo demás el proceso aquí es idéntico). Si ejecutamos su programa con cuda-memcheck, obtenemos un resultado adicional que indica que el kernel está realizando lecturas globales no válidas de tamaño 4. Esto significa que está realizando un acceso a la memoria fuera de los límites. Podemos obtener claridad adicional si volvemos a compilar su código agregando el -lineinfomodificador (o alternativamente con -G) y luego volvemos a ejecutar su código con cuda-memcheck. Ahora obtenemos un resultado similar a este:

$ nvcc -arch=sm_20 -lineinfo -o t615 t615.cu
$ cuda-memcheck ./t615 |more
========= CUDA-MEMCHECK
========= Invalid __global__ read of size 4
=========     at 0x00000070 in /home/bob/misc/t615.cu:34:SolverGPU(float*, float*)
=========     by thread (31,0,0) in block (3,0,0)
=========     Address 0x4024fe1fc is out of bounds
=========     Saved host backtrace up to driver entry point at kernel launch time
=========     Host Frame:/usr/lib64/libcuda.so.1 (cuLaunchKernel + 0x2cd) [0x150a7d]
=========     Host Frame:./t615 [0x11ef8]
=========     Host Frame:./t615 [0x3b143]
=========     Host Frame:./t615 [0x297d]
=========     Host Frame:./t615 (__gxx_personality_v0 + 0x378) [0x26a0]
=========     Host Frame:./t615 (__gxx_personality_v0 + 0x397) [0x26bf]
=========     Host Frame:./t615 [0x2889]
=========     Host Frame:/lib64/libc.so.6 (__libc_start_main + 0xf4) [0x1d994]
=========     Host Frame:./t615 (__gxx_personality_v0 + 0x111) [0x2439]
=========
--More--

(y hay muchos más resultados de error)

Esto significa que el primer error encontrado por su kernel fue una lectura global no válida de tamaño 4 (es decir, un acceso fuera de límites al intentar leer una cantidad into float, por ejemplo). Con la información de lineinfo, podemos ver que esto ocurrió:

=========     at 0x00000070 in /home/bob/misc/t615.cu:34:SolverGPU(float*, float*)

es decir, en la línea 34 del archivo. Esta línea resulta ser esta línea de código del kernel:

    float M1_IndexRight = M1[i + ROOM_X *(j-1)];

Podríamos depurar más, quizás usando printfdeclaraciones internas del kernel para descubrir dónde está el problema. Pero ya tenemos una pista de que estamos indexando fuera de límites, así que inspeccionemos la indexación:

  i + ROOM_X *(j-1)

¿A qué se evalúa esto cuando i=0 y j=0 (es decir, para el hilo (0,0) en su matriz de hilos 2D)? Se evalúa como -2048 (es decir, - ROOM_X), que es un índice ilegal. Intentar leer M1[-2048]creará una falla.

Tienes mucha indexación complicada en tu kernel, así que estoy bastante seguro de que también hay otros errores. Puede usar un método similar para rastrearlos (quizás usando printfpara escupir los índices calculados o probar la validez de los índices).

Aunque la descripción anterior utiliza cuda-memcheck, la compute-sanitizerherramienta funciona de manera similar y es la recomendada en el momento de esta edición.

Para ver otro ejemplo de cómo utilizar este método para delimitar el origen de un problema, consulte aquí .

Robert Crovella avatar Dec 03 '2014 17:12 Robert Crovella