Falha de boot não especificada no Memcpy

Estou encontrando uma “falha de boot não especificada” ao executar meu programa no Cuda. Eu verifiquei os erros.

O programa é um solucionador de uma equação diferencial. Itera TOTAL_ITER vezes. ROOM_X e ROOM_Y são a largura e a altura das matrizes.

Aqui está o header, seu nome é “ú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  void Matrix(float* M); void SolverCPU(float* M1, float* M2); __global__ void SolverGPU(float* M1, float* M2); 

Aqui está o kernel e uma function que preenche uma matriz:

 #include "solver.h" #include 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); } 

E aqui está o 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<< > >(M1_d,M2_d); for(int i=0;i<TOTAL_ITER;i++) { if (i%2==0) SolverGPU<< > >(M1_d,M2_d); else SolverGPU<< > >(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; } 

Não há problema na compilation.

Quando eu verifico meus erros, a “falha de boot não especificada” aparece no memppy APÓS o kernel.

Ok, então eu li que geralmente é devido ao kernel que não é executado corretamente. Mas eu não consigo encontrar o (s) erro (s) no kernel … Eu acho que o erro é bem simples, mas não consigo encontrá-lo.

Quando eu compilo e executo seu código, recebo:

 an illegal memory access was encountered-3 

impresso.

Você pode, de fato, estar recebendo “falha de lançamento não especificada”. O relatório de erros exato dependerá da versão, da GPU e da plataforma CUDA. Mas podemos prosseguir, independentemente.

Qualquer mensagem indica que o kernel foi iniciado, mas encontrou um erro e, portanto, não foi bem-sucedido. Você pode depurar problemas de execução do kernel usando um depurador, como o cuda-gdb no linux, ou o Nsight VSE no Windows. Mas ainda não precisamos extrair o depurador.

Uma ferramenta útil é o cuda-memcheck . Se executarmos o programa com o cuda-memcheck , obtemos alguma saída adicional que indica que o kernel está fazendo leituras globais inválidas de tamanho 4. Isso significa que você está fazendo um access à memory fora dos limites. Podemos obter clareza adicional se recompilarmos seu código adicionando a opção -lineinfo e, em seguida, executaremos novamente seu código com cuda-memcheck . Agora temos a saída que se parece com isso:

 $ 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-- 

(e há muito mais saída de erro)

Isso significa que o primeiro erro encontrado pelo seu kernel foi uma leitura global inválida de tamanho 4 (ou seja, um access fora dos limites tentando ler uma quantidade int ou float , por exemplo). Com as informações lineinfo, podemos ver que isso ocorreu:

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

isto é, na linha 34 do arquivo. Esta linha é a linha do código do kernel:

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

poderíamos depurar ainda mais, talvez usando instruções printf no kernel para descobrir onde está o problema. Mas nós já temos um indício de que estamos indexando fora dos limites, então vamos inspecionar a indexação:

  i + ROOM_X *(j-1) 

o que isso avalia quando i = 0 e j = 0 (ou seja, para thread (0,0) em sua matriz de segmentos 2D)? Ele é avaliado como -2048 (isto é, ROOM_X ), que é um índice ilegal. Tentar ler a partir do M1[-2048] irá criar uma falha.

Você tem muita indexação complicada acontecendo em seu kernel, então tenho certeza que existem outros erros também. Você pode usar um método semelhante para rastreá-los (talvez usando printf para cuspir os índices computados, ou então testar os índices quanto à validade).