Неуказанная ошибка запуска на Memcpy

Я сталкиваюсь с "неопределенной ошибкой запуска" при запуске моей программы в Cuda . Я проверил ошибки.

Программа является решателем дифференциального уравнения. Это повторяет время TOTAL_ITER. ROOM_X и ROOM_Y - это ширина и высота матриц.

Вот заголовок, его имя "единственное":

#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);

Вот ядро ​​и функция, которые заполняют матрицу:

#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);     

}

А вот и главный

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;   

}

Там нет проблем при компиляции.

Когда я проверяю свои ошибки, в memcpy ПОСЛЕ ядра появляется "неопределенная ошибка запуска".

Итак, я прочитал, что это обычно из-за ядра, которое не работает должным образом. Но я не могу найти ошибку (и) в ядре... Я думаю, что ошибка довольно проста, но не могу ее найти.

1 ответ

Решение

Когда я компилирую и запускаю ваш код, я получаю:

an illegal memory access was encountered-3

распечатанный.

Вы действительно можете получить "неопределенную ошибку запуска". Точное сообщение об ошибке будет зависеть от версии CUDA, графического процессора и платформы. Но мы можем идти вперед независимо.

Любое сообщение указывает на то, что ядро ​​запущено, но обнаружена ошибка, и поэтому не удалось успешно завершить. Вы можете отлаживать проблемы с выполнением ядра, используя отладчик, такой как cuda-gdb в Linux или Nsight VSE в Windows. Но нам пока не нужно извлекать отладчик.

Полезный инструмент cuda-memcheck, Если мы запустим вашу программу с cuda-memcheck, мы получаем некоторые дополнительные выходные данные, которые указывают, что ядро ​​выполняет недопустимые глобальные операции чтения размера 4. Это означает, что вы делаете доступ к памяти вне пределов. Мы можем получить дополнительную ясность, если перекомпилируем ваш код, добавив -lineinfo переключиться, а затем повторно запустить свой код с cuda-memcheck, Теперь мы получаем вывод, который выглядит так:

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

(и есть намного больше вывода ошибок)

Это означает, что самой первой ошибкой, с которой столкнулось ваше ядро, было недопустимое глобальное чтение размера 4 (т. Е. Доступ за пределами границ при попытке прочитать int или же float количество, например). С информацией lineinfo мы видим, что это произошло:

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

то есть в строке 34 в файле. Эта строка оказалась строкой кода ядра:

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

мы могли бы отлаживать дальше, возможно, используя в ядре printf заявления, чтобы узнать, где проблема. Но у нас уже есть подсказка, что мы индексируем вне границ, поэтому давайте проверим индексацию:

  i + ROOM_X *(j-1)

что это оценивает, когда i=0 и j=0 (т.е. для потока (0,0) в вашем массиве 2D потоков)? Это оценивает к -2048 (то есть -ROOM_X) который является недопустимым индексом. Пытаюсь читать с M1[-2048] создаст ошибку.

В вашем ядре происходит много сложной индексации, поэтому я уверен, что есть и другие ошибки. Вы можете использовать аналогичный метод, чтобы отследить их (возможно, используя printf выплевывать вычисленные индексы или проверять индексы на достоверность).

Другие вопросы по тегам