使用lapack/blas将矩阵的一个子集乘上另一个矩阵
问题描述:
我想使用dgemm或任何其他lapack/blas函数将矩阵A的子集乘以另一个矩阵。我认为,由于子矩阵的元素可能不是连续的,我不能直接使用dgemm而不将子矩阵复制到另一个空间。所以,当这个子矩阵本身很大时,我认为在C中为这个特定问题编写乘法代码可能会更好,因此效率可能非常低。由于复制并使用lapack/blas本身,可能效率不高。我在matlab中使用lapack/blas作为mex文件。使用lapack/blas将矩阵的一个子集乘上另一个矩阵
我的问题是
1是否有可以在乘子矩阵上工作LAPACK/BLAS的任何功能?如果不是,直接编写代码是更好的办法,还是将子矩阵复制到另一个矩阵并使用dgemm更好?
答
其实dgemm
是专为子矩阵乘法。你只需要正确使用每个矩阵的起始指针和参数LDA
,LDB
,LDC
。
BLAS的C
变种是:
void cblas_dgemm (const CBLAS_LAYOUT layout, const CBLAS_TRANSPOSE TransA, const CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, const double alpha, const double *A, const int lda, const double *B, const int ldb, const double beta, double *C, const int ldc);
说,你有矩阵:
A(15x10)
B(10x20)
C(15x20)
调用dgemm
为Column Major
矩阵存储:
cblas_dgemm (CblasColMajor, CblasNoTrans, CblasNoTrans, 15, 20, 10, 1., A, 15, B, 10, 1., C, 15);
假设你需要调用dgemm
传递小矩阵:
-
As(3x2)
开始在A
-
Bs(2x5)
点(2,1)
开始在B
点(3,5)
-
Cs(3x5)
起始于点(4,2)
的C
的N
,M
,K
将改变为3,5,2,但LDXs
将保持与上面相同。然后你必须将正确的指针传递给dgemm
,以便它们指向每个子矩阵的开始。既然你有C
编号,你必须从每个坐标中减去一个。
-
As
出发点是A + (1+0*15)
-
Bs
出发点是B + (2+4*10)
-
Cs
出发点是C + (3+1*15)
cblas_dgemm (CblasColMajor, CblasNoTrans, CblasNoTrans, 3, 5, 2, 1., A+1, 15, B+42, 10, 1., C+18, 15);
的N
LDA
的想法是说,我甲肝e矩阵A(LDA,*)
,但我将使用上部子矩阵As(N,*)
。在示例中,您不想使用上部子矩阵,而是使用A
中的其他一些内部子矩阵。在这种情况下,您将创建一个新的指针A+1
到矩阵。现在As
是A+1
的上部子矩阵。
同样从C
调用Fortran语言的原始dgemm
功能将
char NoTrans = `N`;
int N = 3;
int M = 5;
int K = 2;
int LDA = 15;
int LDB = 10;
int LDC = 15;
double alpha = 1.0;
double beta = 1.0;
dgemm (&NoTrans, &NoTrans, N, M, K, alpha, A+1, LDA, B+42, LDB, beta, C+18, LDC);
非常感谢你。你能不能再解释一下这样使用它的意思? blas_dgemm如何发现子矩阵的下一个元素,因为它不知道每个列的矩阵和大小的开始?我可以在matlab的lapack/blas中使用它吗?对不起,我对此很新。 – user85361
@ user85361我刚刚提到了cblas等价物,因为您提到了'C'。您也可以在mex文件中使用原始的Fortran's'dgemm'。我会更新答案 – ztik
优秀。非常感谢你。 – user85361