首页 理论教育 GPU与MATLAB混合编程方案:线程块

GPU与MATLAB混合编程方案:线程块

时间:2023-11-24 理论教育 版权反馈
【摘要】:图4.11 大小为16×16的线程块图4.12 MATLAB中显示的输入图像出于演示的目的,首先将输入图像进行转置。图4.13 由线程块覆盖的输入图像给定输入图像和线程块的大小,可以确定在水平和垂直方向上分别有多少线程块。当调用CUDA核函数时,可以知道哪个线程块中的哪个线程正在进行处理。图4.14 分配给图像的线程块和线程对于分配了图像以外像素的线程将直接返回,不进行任何处理。图4.15 采用新线程块大小优化后的卷积

GPU与MATLAB混合编程方案:线程块

优化步骤中,我们通过调整线程网格和线程块的大小来进行优化。首先,确定一个块的大小为16×16,每个块共有256个线程,很明显,它比线程束的尺寸更大。基于线程块和图像的大小,可以确定线程网格的大小。在第一种方法中,每个线程块中只利用了其中一个线程。所以本方法通过给每个线程块分配更多的线程,利用线程块中的其他线程。

每个新的线程块中包含256个以二维方式排列的线程,如图4.11所示。线程块中的每个线程对应处理输入图像的每个像素。图4.12为MATLAB的原始输入图像。

978-7-111-52904-0-Chapter04-38.jpg

图4.11 大小为16×16的线程块

978-7-111-52904-0-Chapter04-39.jpg

图4.12 MATLAB中显示的输入图像

出于演示的目的,首先将输入图像进行转置。这是因为来自MATLAB的输入图像是按列顺序存储的,然而在C/C++和CUDA中,图像是按行顺序存储的。然后,把线程块置于输入图像的顶部,看看这个原始图像是如何分为线程块和线程的,如图4.13所示。

978-7-111-52904-0-Chapter04-40.jpg

图4.13 由线程块覆盖的输入图像

给定输入图像和线程块的大小,可以确定在水平和垂直方向上分别有多少线程块。注意到线程块覆盖的整个区域比输入图像大。这是因为所有的线程块应该是相同大小的,而图像的大小可能不是线程块大小的整数倍。因此,要使线程块覆盖的整个区域比输入图像大。

978-7-111-52904-0-Chapter04-41.jpg

这一段代码展示了如何计算线程块的最小数量,这个数量必须是16的整数倍,且大于等于图片的大小。这里介绍两个dim3类型的变量blockSize和gridSize。

现在,通过线程指针和所分配线程块大小(每个像素对应一个线程),可以访问图像中的每个像素。当调用CUDA核函数时,可以知道哪个线程块中的哪个线程正在进行处理。在核函数中,使用以下CUDA的全局变量来找到确切的像素位置。

●blockDim:线程块的大小(例子中是16×16)。

●blockIdx:线程网格中线程块的索引

●threadIdx:线程块中线程的索引。(www.xing528.com)

每个特定像素的位置可以用图4.14所示的变量计算。请再次注意,图像的行是水平表示的,而图像的列是垂直呈现的,因为在MATLAB中,图像是按列顺序存储的。

978-7-111-52904-0-Chapter04-42.jpg

图4.14 分配给图像的线程块和线程

对于分配了图像以外像素的线程将直接返回,不进行任何处理。在本例中,也忽略了卷积操作的边界区域。在核函数中,通过如下方式检查操作是否在边界内进行:

978-7-111-52904-0-Chapter04-43.jpg

现在创建一个新文件,并保存为conv2MexOptA.cu。

978-7-111-52904-0-Chapter04-44.jpg

978-7-111-52904-0-Chapter04-45.jpg

在这个范例代码中,创建了一个新的核函数并以如下方式调用它:

978-7-111-52904-0-Chapter04-46.jpg

我们向核函数传送新的线程块和线程大小。与之前每个线程块中只处理一个像素的方法不同,这里将图像重组成16×16线程块,但是,与之前方法相同,每个线程执行3×3掩膜乘法和加法。

然后,利用NVIDIA Visual Profiler分析这个新方法。时间分析结果显示,新方法有了巨大的改善,运算速度相比之前的方法提高了30多倍,如图4.15所示。

978-7-111-52904-0-Chapter04-47.jpg

图4.15 采用新线程块大小优化后的卷积

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈