使用 lapack/blas 将矩阵的子集乘以另一个矩阵
Multiplying a subset of matrix to another matrix using lapack/blas
我想使用 dgemm 或任何其他 lapack/blas 函数将矩阵 A 的子集乘以另一个矩阵。我认为由于子矩阵的元素可能不连续,所以我不能在不将子矩阵复制到另一个 space 的情况下直接使用 dgemm。所以,当这个子矩阵本身很大时,它可能非常低效,我认为用 C 编写这个特定问题的乘法代码可能更好。因为复制然后使用 lapack/blas本身,可能根本没有效率。我在 matlab 中使用 lapack/blas 作为 mex 文件。
我的问题是
1- lapack/blas 中是否有任何函数可以在乘法中对子矩阵起作用?
2- 如果不是,是直接编写乘法代码更好还是将子矩阵复制到另一个矩阵并使用 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)
为 Column Major
矩阵存储调用 dgemm
:
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
.
的上子矩阵
类似地,从 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);
我想使用 dgemm 或任何其他 lapack/blas 函数将矩阵 A 的子集乘以另一个矩阵。我认为由于子矩阵的元素可能不连续,所以我不能在不将子矩阵复制到另一个 space 的情况下直接使用 dgemm。所以,当这个子矩阵本身很大时,它可能非常低效,我认为用 C 编写这个特定问题的乘法代码可能更好。因为复制然后使用 lapack/blas本身,可能根本没有效率。我在 matlab 中使用 lapack/blas 作为 mex 文件。
我的问题是
1- lapack/blas 中是否有任何函数可以在乘法中对子矩阵起作用? 2- 如果不是,是直接编写乘法代码更好还是将子矩阵复制到另一个矩阵并使用 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)
为 Column Major
矩阵存储调用 dgemm
:
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
.
类似地,从 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);