使用 CUDA 进行矩阵乘法:2D 块与 1D 块
Posted
技术标签:
【中文标题】使用 CUDA 进行矩阵乘法:2D 块与 1D 块【英文标题】:Matrix multiplication with CUDA: 2D blocks vs 1D blocks 【发布时间】:2015-03-09 18:15:25 【问题描述】:我目前正在做一个家庭作业,我必须实现几个矩阵乘法内核,尝试几个网格和块维度并对结果进行基准测试。
我的第一个内核使用 1D 线程块(其中每个线程块负责计算一个 1×n 子矩阵,每个线程负责计算该子矩阵中的一个元素),我的第二个内核是 2D 块(其中每个线程块负责计算一个方形子矩阵,每个线程负责计算该子矩阵中的一个元素)。他们都在使用全局内存。
我使用大小为 4096*4096 的矩阵启动了几项测试,对于 1D 内核,每个块的线程范围从 64 到 1024,对于 2D 内核,从 8*8 到 32*32。我希望两个内核都能获得相同的性能,但不知何故,2D 内核似乎总是稍微快一些。
这是否可以通过使用 2D 线程块在同一个“区域”中发生更多内存访问以及利用某种缓存机制这一事实来解释?
【问题讨论】:
是的,如果您使用的是缓存内存访问。 【参考方案1】:是的,使用 2D 块可以减少每个块访问的不同矩阵元素的数量。这个简单的计算应该很清楚:
Calculation of A*B=C
Matrix size: 4096*4096
Block size: 1024x1
Number of different elements read from Matrix A: 1 row = 4096 elements
Number of different elements read from Matrix B: 1024 columnes = 4096*1024
Sum: 4193280
Block size: 32x32
Number of different elements read from Matrix A: 32 rows = 32*1024
Number of different elements read from Matrix B: 32 columnes = 32*1024
Sum: 65536
要在结果矩阵中计算 C(i,j),您必须从矩阵 A 中读取第 i 行,从矩阵 B 中读取第 j 列。
因此,如果要计算结果矩阵的第一行,则必须读取第一行的 N 次(假设矩阵为 NxN),并且矩阵 B 中的每一列都读取一次。
4x1 Block
v v v v
>0 1 2 3 0 1 2 3 x x x x
4 5 6 7 4 5 6 7 - - - -
8 9 A B 8 9 A B - - - -
C D E F C D E F - - - -
2x2 Block
v v
>0 1 2 3 0 1 2 3 x x - -
>4 5 6 7 4 5 6 7 x x - -
8 9 A B 8 9 A B - - - -
C D E F C D E F - - - -
箭头指向计算x
指示的元素所需的行和列。
【讨论】:
或许您可以进一步解释一下您的“简单计算”? @op,但请注意,在您描述的实现中,您并没有直接重用值。如果您使用缓存方法(fermi 默认使用只读缓存或在开普勒中启用缓存),则好处是值在缓存中的概率更高,因为您在更高的位置重用值。以上是关于使用 CUDA 进行矩阵乘法:2D 块与 1D 块的主要内容,如果未能解决你的问题,请参考以下文章
使用 Numba 进行矩阵乘法时出现 CUDA 内存不足错误