【发布时间】:2021-11-22 07:49:06
【问题描述】:
我是 CUDA 编程的初学者,正在编写一个由单个文件 main.cu 组成的程序,如下所示。
#include <iostream>
#include <opencv2/opencv.hpp>
#define DEBUG(str) std::cerr << "\033[1;37m" << __FILE__ << ":" << __LINE__ << ": \033[1;31merror:\033[0m " << str << std::endl;
#define CUDADEBUG(cudaError) \
if (cudaError != cudaSuccess) \
DEBUG(cudaGetErrorString(cudaError));
#define ERROR(str) \
{ \
DEBUG(str); \
exit(1); \
}
__global__ void makeGrey(
unsigned char *&pimage,
const int &cn,
const size_t &total)
{
unsigned i = blockDim.x * blockIdx.x + threadIdx.x;
unsigned icn = i * cn;
printf("%u\n", i);
if (i < total)
{
float result = pimage[icn + 0] * .114 +
pimage[icn + 1] * .587 +
pimage[icn + 2] * .299;
pimage[icn + 0] = result; //B
pimage[icn + 1] = result; //G
pimage[icn + 2] = result; //R
// pimage[icn + 3] *= result; //A
}
}
int main(int argc, char **argv)
{
if (argc != 3)
ERROR("usage: executable in out");
cv::Mat image;
unsigned char *dimage;
image = cv::imread(argv[1], cv::IMREAD_UNCHANGED);
if (!image.data)
ERROR("Image null");
if (image.empty())
ERROR("Image empty");
if (!image.isContinuous())
ERROR("image is not continuous");
const size_t N = image.total();
const int cn = image.channels();
const size_t numOfElems = cn * N;
const int blockSize = 512;
const int gridSize = (N - 1) / blockSize + 1;
CUDADEBUG(cudaMalloc(&dimage, numOfElems * sizeof(unsigned char)));
CUDADEBUG(cudaMemcpy(dimage, image.data, numOfElems * sizeof(unsigned char), cudaMemcpyHostToDevice));
makeGrey<<<gridSize, blockSize>>>(dimage, cn, N);
cudaError_t errSync = cudaGetLastError();
cudaError_t errAsync = cudaDeviceSynchronize();
if (errSync != cudaSuccess)
std::cerr << "Sync kernel error: " << cudaGetErrorString(errSync) << std::endl;
if (errAsync != cudaSuccess)
std::cerr << "Async kernel error: " << cudaGetErrorString(errAsync) << std::endl;
CUDADEBUG(cudaMemcpy(image.data, dimage, numOfElems * sizeof(unsigned char), cudaMemcpyDeviceToHost)); //line 73
CUDADEBUG(cudaFree(dimage)); //line 74
cv::imwrite(argv[2], image);
return 0;
}
当我执行程序时,我得到
Async kernel error: an illegal memory access was encountered
/path-to-main.cu:73: error: an illegal memory access was encountered
/path-to-main.cu:74: error: an illegal memory access was encountered
我检查了CV_VERSION 宏,即4.5.3-dev,并安装了 Cuda Toolkit 11.4(nvcc 版本 11.4)。同样 afaik,内核根本不执行(我使用了 Nsight gdb 调试器和 printf)。我不明白为什么我要访问一个非法的内存区域。我很感激任何帮助。提前谢谢你。
【问题讨论】:
-
您的 GPU 函数
makeGrey通过引用获取其参数,这些值位于堆栈中,而不是 GPU 内存中,而是按值获取。 -
谢谢@Kaldrr。您知道有关如何调试 cuda 应用程序的任何建议或教程吗?我必须手动检查数百万个线程吗?其次,很抱歉我不知道我不应该使用引用。我认为
cudaMalloc支持引用。这是为什么?最后,我应该怎么做才能提高你的声誉?如果你写了一个答案,我会接受或不惜一切代价。 -
CUDA调试在线教程here.
-
@Kaldrr 我接受了你的回答。在您的帖子中,您告诉参数值驻留在内存中,但我使用了
cudaMalloc。难道不是在GPU(VRAM等)中分配一块内存而不是主内存吗?我认为普通的 c++ 引用风格也可以在那里工作,就像我们对主内存所做的那样。 -
@HakanDemir 您使用
cudaMalloc的方式与将参数传递给您的makeGrey函数的方式无关。每当您在 C++ 中作为函数参数引用时,您就是在告诉编译器您不是直接传递值,而是在内存中存在该值的位置。但是这个值存在于主机/CPU 内存中,这意味着设备/GPU 代码将尝试使用引用来读取值,该引用指向主机/CPU 内存中的一个值,这在您的内存中是非常未定义的行为(很可能是崩溃)案例。