Fallo de inicio no especificado en Memcpy
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.
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-sanitizer
en 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 -lineinfo
modificador (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 int
o 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 printf
declaraciones 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 printf
para escupir los índices calculados o probar la validez de los índices).
Aunque la descripción anterior utiliza cuda-memcheck
, la compute-sanitizer
herramienta 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í .