C++ LAPACK zgemm op(A)尺寸

C++ LAPACK zgemm op(A)尺寸,c++,matrix,lapack,lapacke,C++,Matrix,Lapack,Lapacke,在netlib的链接中,它将M指定为: 输入时,M指定矩阵的行数 矩阵C.M的op(A)和必须至少为零。 退出时保持不变 所以如果我想用一个3x10矩阵作为a,但我想用它的共轭来表示zgemm(TRANSA='C'),我应该输入什么作为M?3还是10 另外,当我使用其他LAPACK例程时,我将2D矩阵输入为1D,如[3*3],而不是[3][3],调用例程时,我仅将A用于矩阵,我可以对非平方矩阵执行相同的操作吗?[3*10]而不是[3][10] C++中的代码。 < P> A/命名约定/澄清

在netlib的链接中,它将M指定为:

输入时,M指定矩阵的行数 矩阵C.M的op(A)和必须至少为零。 退出时保持不变

所以如果我想用一个3x10矩阵作为a,但我想用它的共轭来表示zgemm(TRANSA='C'),我应该输入什么作为M?3还是10

另外,当我使用其他LAPACK例程时,我将2D矩阵输入为1D,如[3*3],而不是[3][3],调用例程时,我仅将A用于矩阵,我可以对非平方矩阵执行相同的操作吗?[3*10]而不是[3][10]


C++中的代码。

< P> <强> A/命名约定/澄清<强> < /P> 在给出答案之前,为了更清晰,重要的是要记住以下事实:

  • 在美国,M表示行大小,N表示列大小
鉴于

  • 在其他一些地方,如欧洲,N表示行大小,M表示列大小
评论:

  • 您将在netlib.org中找到的所有Blas/Lapack文档都使用美国惯例

  • 我(作为一个欧洲人)必须承认,美国公约更符合逻辑,就像索引(I,j)和(m,n)遵循相同的字母顺序一样

为了避免这种歧义,我通常使用:

  • 行大小的I_大小和列大小的J_大小
B/答案

B.1/gemm

void cblas_zgemm(CBLAS_LAYOUT layout,
                 CBLAS_TRANSPOSE opA,
                 CBLAS_TRANSPOSE opB,
                 const int M, <-------------- I_Size of op(A) 
                 const int N, <-------------- J_Size of op(B)
                 const int K, <-------------- J_Size of op(A)
                 const void* alpha,
                 const void* A,
                 const int lda,
                 const void* B,
                 const int ldb,
                 const void* beta,
                 void* C,
                 const int ldc);
B.2/内存布局

对于Blas/Lapack兼容性和更一般的数字处理

永远不要使用[I_size][J_size],而是始终使用[I_size*J_size]

(原因是:在一种情况下,您有一个指针数组,在另一种情况下,您有一个连续的内存块,它更便于矢量化、缓存友好性等。)

更准确地说

  • 列主修(Fortran风格):A[ld*J_size]

  • 行大调(C风格):A[I_size*ld]

(其中,ld是主要维度)

更新:

    < > >即使你在C++中编码<强>我建议使用FORTRAN约定(列主要)。假装也支持行主模式,但在引擎盖下,它只是在调用请求的子例程之前将矩阵复制到列主布局中。因此,这个额外的功能只是一个幻觉(关于性能)。更准确地说,这是最重要的。只要
    Layout=RowMajor
    ,您就可以检查Lapacke代码,以查看此函数几乎在任何地方都可以使用(例如,请参见代码)

  • 还要注意的是,如果您想要通用步幅(“任意前导尺寸”在I和J方向),您可以使用类库而不是Blas。真正的优势是能够创建任意的张量二维视图。这个选择取决于你的应用,我不知道你是否考虑过张量操作

B.3/矩阵尺寸


如果你的矩阵总是小到3x10,blas/lapack不是一个好的选择(对于性能)。考虑使用类似或的库。

精彩的解释。非常感谢。我的矩阵相当大,我只是用3和10作为例子。@Alireza我刚刚添加了一些关于内存布局/Lapacke的“更新”(见B.2的结尾)这是一个很好的解释。值得注意的是,通过观察M和N始终是C的行数和列数,K始终是被乘以的维度,可以大大简化您的思维。我发现这比试图根据A和B的维度来推理M和N要简单得多,因为它不受转置的影响。@StephenCanon我同意,你是绝对正确的。我明天一有时间就去清理我的帖子(我现在有点赶时间)。感谢您的积极和建设性反馈。
const Size_t opA_I_size = (opA == CblasNoTrans) ? A.I_size() : A.J_size();
const Size_t opA_J_size = (opA == CblasNoTrans) ? A.J_size() : A.I_size();

const Size_t opB_I_size = (opB == CblasNoTrans) ? B.I_size() : B.J_size();
const Size_t opB_J_size = (opB == CblasNoTrans) ? B.J_size() : B.I_size();

cblas_zgemm(CblasColMajor,
            opA,
            opB,
            opA_I_size,
            opB_J_size,
            opA_J_size,
            alpha,
            A.data(),
            A.ld(),
            B.data(),
            B.ld(),
            beta,
            C.data(),
            C.ld());