Cuda 这样,每个维度中的线程总数至少等于相应的图像维度。请记住,网格大小表示每个维度中的块数。这意味着维度中的线程总数等于该维度中网格大小和块大小的乘积。对于二维网格,X维度中的线程数等于block.X*grid.X,Y维度中的线程数等于block.Y*grid.Y

Cuda 这样,每个维度中的线程总数至少等于相应的图像维度。请记住,网格大小表示每个维度中的块数。这意味着维度中的线程总数等于该维度中网格大小和块大小的乘积。对于二维网格,X维度中的线程数等于block.X*grid.X,Y维度中的线程数等于block.Y*grid.Y,cuda,Cuda,假设图像大小为400 x 900,则相应维度中的线程总数也应至少相同 假设您选择了一个大小为(32,32)的块。然后,图像的x和y维度的块数应为400/32和900/32。但两个图像维度都不是相应块维度的整数倍,因此由于整数分割,我们最终将创建大小为12 x 28的网格,这将导致线程总数等于384 x 896。(因为32 x 12=384和32 x 28=896) 正如我们可以看到的,每个维度中的线程总数小于相应的图像维度。我们需要做的是对块的数量进行取整,这样,如果图像维度不是块维度的倍数,我

假设图像大小为400 x 900,则相应维度中的线程总数也应至少相同

假设您选择了一个大小为(32,32)的块。然后,图像的x和y维度的块数应为400/32900/32。但两个图像维度都不是相应块维度的整数倍,因此由于整数分割,我们最终将创建大小为12 x 28的网格,这将导致线程总数等于384 x 896。(因为32 x 12=384和32 x 28=896)

正如我们可以看到的,每个维度中的线程总数小于相应的图像维度。我们需要做的是对块的数量进行取整,这样,如果图像维度不是块维度的倍数,我们将创建一个额外的块来覆盖剩余的像素。 以下是两种方法

我们使用浮点除法和
ceil
计算结果,而不是整数除法来计算块数

int image_width = 400;
int image_height = 900;
dim3 block(32,32);
dim3 grid;
grid.x = ceil( float(image_width)/block.x );
grid.y = ceil( float(image_height)/block.y );
另一个聪明的方法是使用以下公式

int image_width = 400;
int image_height = 900;
dim3 block(32,32);
dim3 grid;
grid.x = (image_width + block.x - 1 )/block.x;
grid.y = (image_height + block.y - 1 )/block.y;
以上述方式创建网格时,最终将创建一个大小为13 x 29的网格,这将导致线程总数等于416 x 928

现在在本例中,每个维度中的线程总数大于相应的图像维度。这将导致一些线程访问映像边界之外的内存,从而导致未定义的行为。这个问题的解决方案是,我们在内核中执行绑定检查,并且只对那些落在映像边界内的线程进行处理。当然要做到这一点,我们需要将图像维度作为参数传递给内核。下面的内核示例演示了这个过程

__global__ void kernel(unsigned char* image, int width, int height)
{
    int xIndex = blockIdx.x * blockDim.x + threadIdx.x; //image x index or column number
    int yIndex = blockIdx.y * blockDim.y + threadIdx.y; //image y index of row number

    if(xIndex < width && yIndex < height)
    {
       //Do processing only here
    }
}
__global__ void kernel(unsigned char* image, int width, int height)
{
    int xIndex = blockIdx.x * blockDim.x + threadIdx.x; //image x index or column number
    int yIndex = blockIdx.y * blockDim.y + threadIdx.y; //image y index of row number

    if(xIndex < width && yIndex < height)
    {
       //Do processing only here
    }
}
调用内核并将图像维度作为参数传递,如下所示:

dim3 block(32,32);
dim3 grid;
grid.x = (image_width + block.x - 1)/block.x;
grid.y = (image_height + block.y - 1)/block.y;
kernel<<<grid, block>>>(...., image_width, image_height);
内核(..,图像宽度,图像高度);
在内核中执行绑定检查,如下所示:

dim3 block(32,32);
dim3 grid;
grid.x = (image_width + block.x - 1)/block.x;
grid.y = (image_height + block.y - 1)/block.y;
kernel<<<grid, block>>>(...., image_width, image_height);
\uuuuu全局\uuuuuu无效内核(无符号字符*图像,整数宽度,整数高度)
{
int xIndex=blockIdx.x*blockDim.x+threadIdx.x;//图像x索引或列号
int yIndex=blockIdx.y*blockDim.y+threadIdx.y;//行号的图像y索引
if(xIndex<宽度&yIndex<高度)
{
//只在这里进行处理
}
}
__global__ void kernel(unsigned char* image, int width, int height)
{
    int xIndex = blockIdx.x * blockDim.x + threadIdx.x; //image x index or column number
    int yIndex = blockIdx.y * blockDim.y + threadIdx.y; //image y index of row number

    if(xIndex < width && yIndex < height)
    {
       //Do processing only here
    }
}