我想使用dgemm或任何其他lapack / blas函数将矩阵A的子集乘以另一个矩阵。我认为,由于子矩阵的元素可能不是连续的,我不能直接使用dgemm而不将子矩阵复制到另一个空间。因此,当这个子矩阵本身很大时,它可能是非常低效的,我认为我可能更好地为C中的这个特定问题编写乘法代码。因为复制然后使用lapack / blas本身,可能效率不高。我在matlab中使用lapack / blas作为mex文件。
我的问题是
1-是否有任何lapack / blas函数可以在乘法中对子矩阵起作用? 2-如果不是,最好直接编写乘法代码,还是将子矩阵复制到另一个矩阵并使用dgemm更好?
答案 0 :(得分:4)
实际上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)
从(2,1)
A
点开始
Bs(2x5)
从(3,5)
B
点开始
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
的想法是说我有一个矩阵A(LDA,*)
,但我将使用上子矩阵As(N,*)
。在示例中,您不希望使用上部子矩阵,而是使用A
内的其他一些子矩阵。在这种情况下,您将为矩阵创建一个新指针A+1
。现在As
是A+1
的上子矩阵。
同样从dgemm
调用Fortran的原始C
函数将是
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);