CUDA内核中的2D图像索引错误
我正在使用CUDA对图像进行线性过滤。我使用2D线程块和2D网格使问题自然化。以下是我的索引方式:(高度和宽度是图像尺寸) 在内核中,我访问以下位置:CUDA内核中的2D图像索引错误,cuda,Cuda,我正在使用CUDA对图像进行线性过滤。我使用2D线程块和2D网格使问题自然化。以下是我的索引方式:(高度和宽度是图像尺寸) 在内核中,我访问以下位置: unsigned int xIndex = blockIdx.x*16+ threadIdx.x; unsigned int yIndex = blockIdx.y*16+ threadIdx.y; unsigned int tid = yIndex * width + xIndex; 我想返回四个边界(稍后我将满足它们)。我这样做是因为: i
unsigned int xIndex = blockIdx.x*16+ threadIdx.x;
unsigned int yIndex = blockIdx.y*16+ threadIdx.y;
unsigned int tid = yIndex * width + xIndex;
我想返回四个边界(稍后我将满足它们)。我这样做是因为:
if(yIndex>=height-N || xIndex>=width-N || yIndex<N || xIndex<N)
return;
代码保持不变,一些输入运行正常,而另一些输入运行不正常。有人能发现虫子吗?我在这里附上了输入和输出示例:谢谢
更新:
内核代码(简化为返回输入图像,但给出了相同的问题)
\uuuuu全局\uuuuu无效过滤器\u8u\uc1\u内核(无符号字符*输入,无符号字符*输出,整数宽度,整数高度,浮点*过滤器,整数fSize)
{
unsigned int xIndex=blockIdx.x*BLOCK_SIZE+threadIdx.x;
unsigned int yIndex=blockIdx.y*BLOCK_SIZE+threadIdx.y;
无符号整数tid=yIndex*width+xIndex;
无符号整数N=filterSize/2;
如果(yIndex>=height-N | | | xIndex>=width-N | | | yIndex还有很多事情您还没有很好地描述,但根据您发布的信息,我猜这是一个合理的复制案例,其参数与您所说的失败案例相匹配(450 x 364,带filterSize=5
):
#包括
#包括
模板
__全局无效过滤器内核(无符号字符*输入,无符号字符*输出,整型宽度,整型高度,浮点*过滤器,整型大小)
{
无符号int xIndex=blockIdx.x*blockDim.x+threadIdx.x;
无符号int-yIndex=blockIdx.y*blockDim.y+threadIdx.y;
无符号整数tid=yIndex*width+xIndex;
无符号整数N=filterSize/2;
如果(yIndex>=height-N | | | xIndex>=width-N | | | yIndex如果看不到代码,这将很难回答,但我会非常怀疑在内核中使用返回语句。如果代码中存在内存或指令同步障碍,那么很可能是返回语句本身造成了问题。我已经添加了更新中的e代码。这与我前面提到的几乎相同。你能将你正在使用的内核参数和启动参数添加到一个失败的案例中吗?另外,filterSize
目前还没有定义,应该是fSize
?我已经在问题中提到了启动参数。filterSize可以是任何参数,比如3,5,7,9..是他lps计算N,设置边界处的偏移像素。实际上,如果我将N硬编码为任何值,都不会产生任何差异。在这种配置中,我只复制输入图像以输出所有标准大小的工作,还有一些其他工作,但在少数图像大小(例如450x364)下,它会给出错误的输出。请参阅附件。我在ma上测试了您的代码chine和它的工作非常完美,提供了正确的输出。因此,这使我从整个框架中提取了我的代码,并专门为此内核制作了一个项目。我正在使用OpenCV(免费提供)阅读图像。当通过OpenCV读取图像时,同一个内核在450x364上给出了不正确的输出。标准图像大小工作正常,您认为这可能是OpenCV的问题吗?我在这里附上完整的项目,请看:@JawadMasood:OpenCV图像并不总是连续的,即内存中的所有字节都是连续的。它们之间可能存在间隙图像行。如何访问图像数据?如果boolmat::isContinuous()
返回false
,您应该在访问它时考虑到size\u t Mat::step
。请参阅和。@JawadMasood:抱歉,但没有。您问了一个关于内核索引方案的问题,我相信它已经得到了满意的回答。我不是在钻研一个庞大的OpenCV项目来试图找到您的bug。如果您能隔离一个与OpenCV相关的问题,然后我建议你发布一个新的、以OpenCV为中心的问题。事实上我发现了这个问题。imageStep并不总是等于width*numberOfChannel。在这种情况下,450x364的图像的步长是452!!!OpenCV也读取步长。我所要做的就是在调用函数中将宽度更改为步长。你已经解决这个问题有很多帮助。我认为你的答案是正确的!谢谢:)
if(yIndex>=height-N || xIndex>=width-N || yIndex<N || xIndex<N)
return;
if(yIndex>=height || xIndex>=width)
return;
__global__ void filter_8u_c1_kernel(unsigned char* in, unsigned char* out, int width, int height, float* filter, int fSize)
{
unsigned int xIndex = blockIdx.x*BLOCK_SIZE + threadIdx.x;
unsigned int yIndex = blockIdx.y*BLOCK_SIZE + threadIdx.y;
unsigned int tid = yIndex * width + xIndex;
unsigned int N = filterSize/2;
if(yIndex>=height-N || xIndex>=width-N || yIndex<N || xIndex<N)
return;
/*Filter code removed, still gives the same problem*/
out[tid] = in[tid];
}
if(yIndex<=height-N && xIndex<=width-N && yIndex>N && xIndex>N){
/*Kernel Code*/
}
#include <stdio.h>
#include <assert.h>
template<int filterSize>
__global__ void filter_8u_c1_kernel(unsigned char* in, unsigned char* out, int width, int height, float* filter, int fSize)
{
unsigned int xIndex = blockIdx.x*blockDim.x + threadIdx.x;
unsigned int yIndex = blockIdx.y*blockDim.y + threadIdx.y;
unsigned int tid = yIndex * width + xIndex;
unsigned int N = filterSize/2;
if(yIndex>=height-N || xIndex>=width-N || yIndex<N || xIndex<N)
return;
out[tid] = in[tid];
}
int main(void)
{
const int width = 450, height = 365, filterSize=5;
const size_t isize = sizeof(unsigned char) * size_t(width * height);
unsigned char * _in, * _out, * out;
assert( cudaMalloc((void **)&_in, isize) == cudaSuccess );
assert( cudaMalloc((void **)&_out, isize) == cudaSuccess );
assert( cudaMemset(_in, 'Z', isize) == cudaSuccess );
assert( cudaMemset(_out, 'A', isize) == cudaSuccess );
const dim3 BlockDim(16,16);
dim3 GridDim;
GridDim.x = (width + BlockDim.x - 1) / BlockDim.x;
GridDim.y = (height + BlockDim.y - 1) / BlockDim.y;
filter_8u_c1_kernel<filterSize><<<GridDim,BlockDim>>>(_in,_out,width,height,0,0);
assert( cudaPeekAtLastError() == cudaSuccess );
out = (unsigned char *)malloc(isize);
assert( cudaMemcpy(out, _out, isize, cudaMemcpyDeviceToHost) == cudaSuccess);
for(int i=0; i<width; i++) {
fprintf(stdout, "%d: ", i);
for(int j=0; j<height; j++) {
unsigned int idx = i + j*width;
fprintf(stdout, "%c", out[idx]);
}
fprintf(stdout, "\n");
}
return cudaThreadExit();
}