【发布时间】:2016-03-22 13:10:52
【问题描述】:
我正在开发一个程序来转换灰度图像。我正在使用 CImg 库。我必须为每个像素读取 3 个值 R-G-B,计算相应的灰度值并将灰度像素存储在输出图像上。我正在使用 NVIDIA GTX 480。关于卡的一些细节:
- 微架构:费米
- 计算能力(版本):2.0
- 每个 SM 的核心数(经线大小):32
- 流式多处理器:15
- 每个多处理器的最大驻留扭曲数:48
- 每个多处理器的最大共享内存量:48KB
- 每个多处理器的最大驻留线程数:1536
- 每个多处理器的 32 位寄存器数:32K
我正在使用具有 256 个线程块的方形网格。 该程序可以有不同尺寸的输入图像(例如 512x512 像素、10000x10000 像素)。我观察到增加分配给每个线程的像素数会提高性能,因此它比每个线程计算一个像素要好。问题是,如何确定静态分配给每个线程的像素数?用所有可能的数字计算测试?我知道在 GTX 480 上,1536 是每个多处理器的最大驻留线程数。我需要考虑这个数字吗?以下,是内核执行的代码。
for(i = ((gridDim.x + blockIdx.x) * blockDim.x) + threadIdx.x; i < width * height; i += (gridDim.x * blockDim.x)) {
float grayPix = 0.0f;
float r = static_cast< float >(inputImage[i]);
float g = static_cast< float >(inputImage[(width * height) + i]);
float b = static_cast< float >(inputImage[(2 * width * height) + i]);
grayPix = ((0.3f * r) + (0.59f * g) + (0.11f * b));
grayPix = (grayPix * 0.6f) + 0.5f;
darkGrayImage[i] = static_cast< unsigned char >(grayPix);
}
【问题讨论】:
-
性能取决于许多因素:寄存器使用、内存合并,当然还有块和网格大小。您可以通过在“NVIDIA CUDA 占用计算器”中输入您的数字来获得一些信息 - 这是一个 XLS (Excel) 文件,可在 developer.download.nvidia.com/compute/cuda/… 找到
-
@Marco:甚至不再需要使用占用电子表格。运行时 API 功能
cudaOccupancyMaxActiveBlocksPerMultiprocessor将为您完成所有艰苦的工作 -
@talonmies 对,那是在... CUDA 6 左右添加的?但是,我认为电子表格仍然比编写自定义代码、查阅 API 文档和在一些修改-编译-运行-重复循环中尝试不同的参数化更方便。我只是想提一下(虽然我自己并没有广泛使用它,也不能说它对有针对性的优化有多大帮助)
-
@Marco:我已经尝试过“NVIDIA CUDA 占用计算器”。但我唯一能看到的是变化 1)每个线程的寄存器计数,2)每个块的共享内存和 3)块大小的影响。没有关于用于获得性能的最佳块数量的建议。我错了吗?
-
我对它也不是很熟悉,所以我认为@talonmies 可能会在这里给出更集中的建议。但是例如,当您使用默认设置打开 XLS,然后将“每个块的线程数”更改为 128,您会看到占用率(在上图中,在“每个多处理器的占用率”字段中)减少。最大值似乎已达到,例如用于 512 或 672 个线程(100% 或 98% 占用率)
标签: image-processing cuda nvidia