为什么Apple的Metal Matrix乘法示例需要填充C

ZH *_*LIU 5 objective-c gpu-programming ios metal

我正在学习Apple的Metal,试图进行一些GPU计算。

我检查了Apple给出的矩阵乘法示例。有一点我不明白。

在文件MetalMatrixMult.h中

// Number of rows in matrices A and C.
@property (nonatomic) uint16_t m;

// Number of columns in matrix A; number of rows in matrix B.
@property (nonatomic) uint16_t n;

// Number of columns in matrices B and C.
@property (nonatomic) uint16_t k;

// Output matrix (padded) C row count
@property (nonatomic, readonly) uint16_t M;

// Output matrix (padded) C column count
@property (nonatomic, readonly) uint16_t K;

// Output matrix C = A x B
@property (nonatomic, readonly) float* output;
Run Code Online (Sandbox Code Playgroud)

它说矩阵C已填充。我不清楚这pad是什么意思。是某种对齐方式吗?原因我知道Metal的着色器语言规范中有类型对齐方式,但是我不知道为什么我们需要填充缓冲继承者。

谢谢。

hun*_*ley 5

它与优化内存访问有关。您的 GPU 有许多线程组,每个线程组都包含相对少量的专用内存(几 KB),可以非常快速地访问。这与 GPU 的主内存分开,后者可能是几 GB 的相对较慢的内存。

由于所有 3 个矩阵 ( A,BC)不太可能适合单个线程组的内存,并且在循环内回退到主内存会非常慢,因此我们将计算划分为“块”或扇区。想象一下将结果矩阵C划分为一个网格,其中每个扇区是 8 x 8 元素的集合:然后我们可以指示线程组 1 计算左上扇区的结果,而其他线程组同时计算其他扇区。在这种情况下,线程组 1 只需要 的前 8 行A和前 8 列B来计算其部分C。这意味着我们可以向线程组 1 发送更少的数据,使其保持在缓存限制范围内。

Metal 要求我们填充矩阵的原因是它可以划分C为一个完美的网格。如果您的真实结果矩阵为 12 x 18,扇区大小为 8 x 8,则表示C为 1.5 x 2.25 个扇区。GPU 无法在部分扇区上高效运行,因此您必须用零填充矩阵以达到整数 - 在这种情况下为 2 x 3 扇区或 16 x 24 个元素。为了高度优化的并行处理,您牺牲了一点存储空间和更多的时钟周期。