gpt4 book ai didi

cuda - Memcpy 上未指定的启动失败

转载 作者:行者123 更新时间:2023-11-28 08:34:49 25 4
gpt4 key购买 nike

我在 Cuda 中运行我的程序时遇到“未指定的启动失败”。我检查了错误。

该程序是微分方程的求解器。它迭代 TOTAL_ITER 次。ROOM_X 和 ROOM_Y 是矩阵的宽度和高度。

这是标题,它的名字是“sole :

#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 上。

好的,所以我读到这通常是由于内核运行不正常造成的。但是我在内核中找不到错误...我想错误很简单,但无法找到它。

最佳答案

当我编译并运行您的代码时,我得到:

an illegal memory access was encountered-3

打印出来。

您可能确实遇到了“未指定的启动失败”。确切的错误报告将取决于 CUDA 版本、GPU 和平台。但无论如何我们都可以继续前进。

任何一条消息都表明内核启动但遇到错误,因此未能成功完成。您可以使用调试器调试内核执行问题,例如 Linux 上的 cuda-gdb 或 Windows 上的 Nsight VSE。但我们还不需要取出调试器。

一个有用的工具是 cuda-memcheck。 (在较新的 GPU 上,例如 cc7.0 或更新版本,您应该使用 compute-sanitizer 而不是 cuda-memcheck,但这里的过程是相同的。)如果我们运行你的程序使用 cuda-memcheck,我们得到一些额外的输出,表明内核正在进行大小为 4 的无效全局读取。这意味着你正在进行越界内存访问。如果我们重新编译您的代码并添加 -lineinfo 开关(或者使用 -G),然后使用 cuda- 重新运行您的代码,我们可以获得额外的清晰度内存检查。现在我们得到如下所示的输出:

$ 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 的无效全局读取(即尝试读取 intfloat 的越界访问数量,例如)。通过 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 时(即,对于 2D 线程数组中的线程 (0,0)),它的计算结果是什么?它的计算结果为 -2048(即 -ROOM_X),这是一个非法索引。尝试从 M1[-2048] 读取会产生错误。

您的内核中正在进行大量复杂的索引编制,所以我很确定还有其他错误。您可以使用类似的方法来追踪这些(也许使用 printf 吐出计算出的索引,或者测试索引的有效性)。

虽然上面的描述使用了cuda-memcheck,但是compute-sanitizer工具的工作原理类似,并且是在编辑时推荐的工具。

有关如何使用此方法缩小问题根源的另一个示例,请参阅 here .

关于cuda - Memcpy 上未指定的启动失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59415370/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com