使用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)

调用dgemmColumn 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

NMK将改变为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); 
    

NLDA的想法是说,我甲肝e矩阵A(LDA,*),但我将使用上部子矩阵As(N,*)。在示例中,您不想使用上部子矩阵,而是使用A中的其他一些内部子矩阵。在这种情况下,您将创建一个新的指针A+1到矩阵。现在AsA+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); 
+0

非常感谢你。你能不能再解释一下这样使用它的意思? blas_dgemm如何发现子矩阵的下一个元素,因为它不知道每个列的矩阵和大小的开始?我可以在matlab的lapack/blas中使用它吗?对不起,我对此很新。 – user85361

+0

@ user85361我刚刚提到了cblas等价物,因为您提到了'C'。您也可以在mex文件中使用原始的Fortran's'dgemm'。我会更新答案 – ztik

+0

优秀。非常感谢你。 – user85361