从设备到主机的cudaMemcpy错误
在内核上计算之后,我返回一个二维结构,从设备到主机从设备到主机的cudaMemcpy错误,cuda,Cuda,在内核上计算之后,我返回一个二维结构,从设备到主机 HANDLE_ERROR(cudaMemcpy(Pixel,Pixel_gpu,img_wd*img_ht*sizeof(pixel),cudaMemcpyDeviceToHost)); 像素在主机上声明,像素gpu在设备上分配,如下所示: **Pixel_gpu; HANDLE_ERROR(cudaMalloc(&Pixel_gpu,img_wd*img_ht*sizeof(pixel))); pixel **Pixel = (p
HANDLE_ERROR(cudaMemcpy(Pixel,Pixel_gpu,img_wd*img_ht*sizeof(pixel),cudaMemcpyDeviceToHost));
像素在主机上声明,像素gpu在设备上分配,如下所示:
**Pixel_gpu;
HANDLE_ERROR(cudaMalloc(&Pixel_gpu,img_wd*img_ht*sizeof(pixel)));
pixel **Pixel = (pixel**)malloc((img_ht)*sizeof(pixel*));
for(int i=0;i<(img_ht);i++)
Pixel[i]=(pixel*)malloc((img_wd)*sizeof(pixel));
内核启动:
cudaDeviceProp prop;
HANDLE_ERROR(cudaGetDeviceProperties(&prop, 0));
int thread_block=sqrt(prop.maxThreadsPerBlock);
dim3 DimGrid(ceil(img_wd/thread_block),ceil(img_ht/thread_block),1);
dim3 DimBlock(sqrt(prop.maxThreadsPerBlock),sqrt(prop.maxThreadsPerBlock),1);
//allocating gpu memory
pixel **Pixel_tmp_gpu, **Pixel_gpu;
HANDLE_ERROR(cudaMalloc(&Pixel_tmp_gpu,img_wd*img_ht*sizeof(pixel)));
HANDLE_ERROR(cudaMalloc(&Pixel_gpu,img_wd*img_ht*sizeof(pixel)));
float **kernel0_gpu, **kernel1_gpu;
HANDLE_ERROR(cudaMalloc(&kernel0_gpu,k*1*sizeof(float)));
HANDLE_ERROR(cudaMalloc(&kernel1_gpu,1*k*sizeof(float)));
cout<<"memory allocated"<<endl;
//copying needed data
HANDLE_ERROR(cudaMemcpy(Pixel_tmp_gpu,Pixel_tmp,img_wd*img_ht*sizeof(pixel),cudaMemcpyHostToDevice));
HANDLE_ERROR(cudaMemcpy(Pixel_gpu,Pixel,img_wd*img_ht*sizeof(pixel),cudaMemcpyHostToDevice));
HANDLE_ERROR(cudaMemcpy(kernel0_gpu,kernel0,k*1*sizeof(float),cudaMemcpyHostToDevice));
HANDLE_ERROR(cudaMemcpy(kernel1_gpu,kernel1,1*k*sizeof(float),cudaMemcpyHostToDevice));
cout<<"memory transfers done"<<endl;
vertical_conv<<<DimGrid,DimBlock>>>(Pixel_gpu, Pixel_tmp_gpu,img_wd, img_ht,kernel0_gpu,k);
time_t vertical_convolution=time(NULL);
cout<<" vertical_convolution time: "<<double(vertical_convolution - reading_file)<<"sec"<<endl;
horizontal_conv<<<DimGrid,DimBlock>>>(Pixel_tmp_gpu, Pixel_gpu, img_wd, img_ht, kernel1_gpu, k);
time_t horizontal_convolution=time(NULL);
cout<<" horizontal convolution time:" <<double(horizontal_convolution-vertical_convolution)<<" sec"<<endl;
pixel *Pixel_res = (pixel*)malloc(img_wd*img_ht*sizeof(pixel));
HANDLE_ERROR(cudaMemcpy(Pixel_res,Pixel_gpu,img_wd*img_ht*sizeof(pixel),cudaMemcpyDeviceToHost));
cudaDeviceProp道具;
句柄_错误(cudaGetDeviceProperties(&prop,0));
int thread_block=sqrt(属性maxThreadsPerBlock);
dim3 DimGrid(ceil(img\U wd/螺纹块),ceil(img\U ht/螺纹块),1);
dim3 DimBlock(sqrt(属性maxThreadsPerBlock),sqrt(属性maxThreadsPerBlock),1);
//分配gpu内存
像素**像素\u tmp\u gpu,**像素\u gpu;
句柄错误(cudamaloc(&Pixel_tmp_gpu,img_wd*img_ht*sizeof(Pixel));
句柄错误(cudaMalloc(&Pixel_gpu,img_wd*img_ht*sizeof(Pixel));
浮点**内核0\gpu,**内核1\gpu;
HANDLE_错误(cudamaloc(&kernel0_gpu,k*1*sizeof(float));
HANDLE_错误(cudamaloc(&kernel1_gpu,1*k*sizeof(float));
coutPixel\u gpu
是一个连续内存块,由w*h
类型的Pixel
元素组成。它的大小是
sizeOfDeviceMemory = img_wd * img_ht * sizeof(pixel)
sizeOfHostMemory = img_ht * sizeof(pixel*)
与此相反,CPU端的Pixel
是一个“指针数组”:Pixel
指针指向h
类型的Pixel*
元素。它的大小是
sizeOfDeviceMemory = img_wd * img_ht * sizeof(pixel)
sizeOfHostMemory = img_ht * sizeof(pixel*)
显然,这些大小是不同的,尝试将sizeOfDeviceMemory
字节写入此指针会导致非法访问
通常,您还应将主机上的内存分配为一个连续块:
pixel* Pixel = (pixel*)malloc(img_wd * img_ht * sizeof(pixel));
然后可以使用已有的cudaMemcpy
调用将内存复制到此指针
如果主机上有一个
像素*
不适合您,并且您迫切需要一个像素**
(例如,将其传递给其他函数),那么您可以像以前一样创建一个“指针数组”,但不为每一行分配新内存,而是让每个指针指向一行中的一行,连续像素块 我尝试将主机内存分配为一个块,但仍然得到相同的错误。非法内存访问错误可能发生在内核中。你还没有表现出一点,所以人们只是在猜测。Marco13指出的当然是代码中的一个缺陷,但是由于您没有展示完整的代码,没有人能告诉您所有的问题可能是什么。如果您以双指针(**
)的形式传递Pixel\gpu
,那么您的内核几乎肯定会有问题代码>看起来也有点奇怪。它应该声明为pixel*pixel\gpu
。然后,您可以使用cudamaloc(&Pixel\gpu,…)
分配它,并使用cudaMemcpy(…,Pixel\gpu,…)
。如何声明Pixel\gpu
?正如Robert指出的那样,由于异步的性质,很难猜测现在可能出现了什么错误。对于调试,您可以在cudaMemcpy
调用之前和之后添加cudaDeviceSynchronize()
,以确保此调用是问题的根源。您不能将平面、单指针(*
)分配传递给内核,并期望将其用作双指针(***
)数组。在主机和设备之间传递双指针数组需要特殊编码,而您缺少这种编码。这是一个经常被误解的话题,因此有很多问题在讨论它。您只需搜索cuda 2D array
或cuda
标记信息页面链接,即可找到讨论如何处理2D array的典型问题。我相信这仍然不是一个好消息。它应该是其他人可以编译和运行的东西,而无需大量的组装工作。如果您只需将所有内容转换为具有模拟2D访问的单指针数组(即[row*width+col]
),您的工作将大大简化。我将研究cuda上的2D数组处理,感谢您的建议。
sizeOfHostMemory = img_ht * sizeof(pixel*)
pixel* Pixel = (pixel*)malloc(img_wd * img_ht * sizeof(pixel));