代码之家  ›  专栏  ›  技术社区  ›  user85361

使用lapack/blas将矩阵子集乘以另一个矩阵

  •  4
  • user85361  · 技术社区  · 7 年前

    我想使用dgemm或任何其他lapack/blas函数将矩阵a的子集乘以另一个矩阵。我认为,由于子矩阵的元素可能不连续,我无法在不将子矩阵复制到另一个空间的情况下直接使用dgemm。因此,当这个子矩阵本身很大时,它可能非常低效,以至于我认为最好用C编写这个特定问题的乘法代码。因为复制然后使用lapack/blas本身,可能根本没有效率。我使用matlab中的lapack/blas作为mex文件。

    我的问题是

    1-lapack/blas是否有任何函数可以处理乘法中的子矩阵?

    1 回复  |  直到 7 年前
        1
  •  6
  •   ztik    7 年前

    事实上 dgemm 设计用于子矩阵乘法。您只需要正确使用每个矩阵和参数的起始指针 LDA , LDB , LDC .

    这个 C BLAS的变体是:

    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 矩阵存储:

    cblas_dgemm (CblasColMajor, CblasNoTrans, CblasNoTrans, 15, 20, 10, 1., A, 15, B, 10, 1., C, 15);
    

    假设你需要打电话 矩阵乘法

    • As(3x2) 从点开始 (2,1) 属于 A
    • Bs(2x5) 从点开始 (3,5) 属于 B
    • Cs(3x5) 从点开始 (4,2) 属于 C

    这个 N , M , K 将更改为3、5、2,但 LDXs 矩阵乘法 因此它们将指向每个子矩阵的开始。既然你有 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 到矩阵。现在 是的上子矩阵 A+1 .

    类似地调用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);