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

时间:2017-09-26 07:10:42

标签: matlab matrix matrix-multiplication lapack blas

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

我的问题是

1-是否有任何lapack / blas函数可以在乘法中对子矩阵起作用? 2-如果不是,最好直接编写乘法代码,还是将子矩阵复制到另一个矩阵并使用dgemm更好?

1 个答案:

答案 0 :(得分:4)

实际上dgemm是为子矩阵乘法而设计的。您只需要正确使用每个矩阵的起始指针以及参数LDALDBLDC

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点开始

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);
    

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