函数功能:

函数示例

1
2
3
4
5
6
7
8
cublasStatus_t cublasSgemm(cublasHandle_t handle,
cublasOperation_t transa, cublasOperation_t transb,
int m, int n, int k,
const float *alpha,
const float *A, int lda,
const float *B, int ldb,
const float *beta,
float *C, int ldc)

参数解释:

参数 含义
handle cublas的上下文
transa 是否对矩阵A进行转置
transb 是否对矩阵B进行转置
m 矩阵C、A的行
n 矩阵C、B的列
k 矩阵A的列,矩阵B的行
alpha 参数 $\alpha $​
A 矩阵A
lda 用于存储矩阵A的二维数组的主导维度。
B 矩阵B
ldb 用于存储矩阵B的二维数组的主导维度。
beta 参数 $\beta$​
C 矩阵C
ldc 用于存储矩阵C的二维数组的主导维度。

所谓的主导维度就是将一维向量映射为二维矩阵时优先填充维度的长度。cuBLAS按照列主序所以主导维度就是矩阵的行高。

踩空点

由于最初的BLAS库使用FORTRAN语言编写的,因此它使用的是以列优先的数组存储。如下面的示例所示,在将一维向量映射为二维矩阵是列优先。

解决方案

我们下面的矩阵$A$举个例子.

在存储中的表现形式如下:

因为是列排布优先如果不改变矩阵的行列,则矩阵A如下所示,看上去完全无法进行合理计算。

但是如果我们颠倒一下行列,那么我们就可以获得矩阵A的转置$A^T$,同时按列存储的话在内存中的排序与矩阵A是完全一致的。

结论:对于矩阵$A$,$A$按行存取和$A^T$的案列存取在最终结果上是一致的。

所以我们从求矩阵$C$转变为求$C^T$

所以我们只需要颠倒一下A和B以及他们的行列就可以获得正确的结果。

这样只需要稍微改动一下参数,就可以获得行优先的结果:

参数 列优先取值 行优先取值
handle cublas的上下文 cublas的上下文
transa CUBLAS_OP_N CUBLAS_OP_N
transb CUBLAS_OP_N CUBLAS_OP_N
m 矩阵C、A的行 矩阵C,B的列
n 矩阵C、B的列 矩阵C,A的行
k 矩阵A的列,矩阵B的行 矩阵A的列,矩阵B的行
alpha 参数 $\alpha $ 参数 $\alpha $
A 矩阵A 矩阵B
lda 矩阵A的行 矩阵A的列
B 矩阵B 矩阵A
ldb 矩阵B的行 矩阵B的列
beta 参数 $\beta$ 参数 $\beta$
C 矩阵C 矩阵C
ldc 矩阵C的行 矩阵C的列