这个例子的问题在于,它只适用于方阵。如果矩阵不是方阵,由于维度不匹配(假设维度对于
A*B
是正确的),你就无法计算出
A^t*B^t
。
我手头没有可用的 cuBLAS 安装程序,所以这有点像一次尝试,但我会非常惊讶如果 cuBLAS 的工作方式与通常的 BLAS 不同。BLAS 期望矩阵按列主序(即 Fortran 主序)排列,但也可以用于按行主序(即 C 主序)排列的矩阵。
在我看来(这可能完全错误),
gemm_v2
不是处理两个 C 主序矩阵乘法的通常/最佳方法,例如因为如果一个人将两个 C 主序矩阵相乘,答案也将是一个 C 主序矩阵。
使用
gemm
计算两个 C 主序矩阵的积的技巧如下:
即使这可能已经为你所知,我还是想首先详细说明一下行主序(c-memory-layout)和列主序(fortran-memory-layout),以便充分解释我的答案。
因此,如果我们有一个
2x3
(即 2 行 3 列)矩阵
A
,并将其存储在一些连续的内存中,我们得到:
row-major-order(A) = A11, A12, A13, A21, A22, A23
col-major-order(A) = A11, A21, A12, A22, A13, A33
这意味着,如果我们得到一个连续的内存块,它按行主序表示矩阵,我们将其解释为按列主序表示矩阵,那么我们将得到完全不同的矩阵!
然而,如果我们看一下转置矩阵A^t
,我们可以很容易地看出:
row-major-order(A) = col-major-order(A^t)
col-major-order(A) = row-major-order(A^t)
这意味着,如果我们想要以行主序(row-major-order)的方式得到矩阵
C
作为结果,blas例程应该将转置后的矩阵
C
以列主序(column-major-order)的方式(毕竟我们无法改变)写入这个内存。然而,
C^t=(AB)^t=B^t*A^t
且
B^t
和
A^t
是在列主序中重新解释的原始矩阵。
现在,设
A
是一个
n x k
的矩阵,
B
是一个
k x m
的矩阵,则调用
gemm例程应该按如下方式进行:
gemm('N', 'N', m, n, k, 1.0, B, m, A, k, 0.0, C, m)
请注意:
- 我们不必转置矩阵
A
和 B
,因为通过将 C-order 重新解释为 Fortran-order 可以处理它。
- 我们必须交换矩阵
A
和 B
的位置,以便得到以 Fortran-order 形式表示的 C^t
作为结果。
- 由于重新解释为 C-order,所以得到的矩阵
C
是按 C-order 排列的(从 Fortran-order 转换)并且没有 ^t
。