【问题标题】:PETSc - MatMultScale? Matrix X vector X scalarPETSc - MatMultScale?矩阵 X 向量 X 标量
【发布时间】:2014-11-07 01:13:59
【问题描述】:

我正在使用 PETSc,我想做类似的事情,

我知道我能做到:

Mat A
Vec x,y

MatMult(A,x,y)
VecScale(y,0.5)

我只是好奇是否有一个函数可以一次性完成所有这些操作。好像可以省一个循环。

MatMultScale(A,x,0.5,y)

有这样的功能吗?

【问题讨论】:

    标签: petsc


    【解决方案1】:

    这个函数(或任何接近的函数)似乎不在functions operating on Mat 的列表中。所以对你的问题的简短回答是......不。

    如果您经常使用 $y=\frac12 Ax$,一个解决方案是使用 MatScale(A,0.5); 一次性缩放矩阵。

    这样的功能有用吗?检查这一点的一种方法是使用 petsc 的-log_summary 选项来获取一些分析信息。如果你的矩阵是密集的,你会看到在MatMult() 中花费的时间远大于在VecScale() 中花费的时间。这个问题只有在处理一个稀疏矩阵时才有意义,每行有几个非空项。

    这是一个测试它的代码,使用 2xIdentity 作为矩阵:

    static char help[] = "Tests solving linear system on 0 by 0 matrix.\n\n";
    
    #include <petscksp.h>
    
    #undef __FUNCT__
    #define __FUNCT__ "main"
    int main(int argc,char **args)
    {
        Vec            x, y;      
        Mat            A;           
        PetscReal      alpha=0.5;  
        PetscErrorCode ierr;
        PetscInt n=42;
    
        PetscInitialize(&argc,&args,(char*)0,help);
        ierr = PetscOptionsGetInt(NULL,"-n",&n,NULL);CHKERRQ(ierr);
    
        /* Create the vector*/
        ierr = VecCreate(PETSC_COMM_WORLD,&x);CHKERRQ(ierr);
        ierr = VecSetSizes(x,PETSC_DECIDE,n);CHKERRQ(ierr);
        ierr = VecSetFromOptions(x);CHKERRQ(ierr);
        ierr = VecDuplicate(x,&y);CHKERRQ(ierr);
    
        /*
         Create matrix.  When using MatCreate(), the matrix format can
         be specified at runtime.
    
         Performance tuning note:  For problems of substantial size,
         preallocation of matrix memory is crucial for attaining good
         performance. See the matrix chapter of the users manual for details.
         */
        ierr = MatCreate(PETSC_COMM_WORLD,&A);CHKERRQ(ierr);
        ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,n,n);CHKERRQ(ierr);
        ierr = MatSetFromOptions(A);CHKERRQ(ierr);
        ierr = MatSetUp(A);CHKERRQ(ierr);
    
        /*
    This matrix is diagonal, two times identity
    should have preallocated, shame
         */
        PetscInt i,col;
        PetscScalar value=2.0;
        for (i=0; i<n; i++) {
            col=i;
            ierr   = MatSetValues(A,1,&i,1,&col,&value,INSERT_VALUES);CHKERRQ(ierr);
        }
    
        ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
        ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
    
        /*
         let's do this 42 times for nothing :
         */
        for(i=0;i<42;i++){
            ierr = MatMult(A,x,y);CHKERRQ(ierr);
            ierr = VecScale(y,alpha);CHKERRQ(ierr);
        }
    
        ierr = VecDestroy(&x);CHKERRQ(ierr);
        ierr = VecDestroy(&y);CHKERRQ(ierr); 
        ierr = MatDestroy(&A);CHKERRQ(ierr);
    
        ierr = PetscFinalize();
        return 0;
    }
    

    生成文件:

    include ${PETSC_DIR}/conf/variables
    include ${PETSC_DIR}/conf/rules
    include ${PETSC_DIR}/conf/test
    
    CLINKER=g++
    
    all : ex1
    
    ex1 : main.o chkopts
        ${CLINKER} -w -o main main.o ${PETSC_LIB}
        ${RM} main.o
    
    run :
        mpirun -np 2 main -n 10000000 -log_summary -help -mat_type mpiaij
    

    由此产生的两行 -log_summary 可以回答您的问题:

    Event                Count      Time (sec)     Flops                             --- Global ---  --- Stage ---   Total
                       Max Ratio  Max     Ratio   Max  Ratio  Mess   Avg len Reduct  %T %F %M %L %R  %T %F %M %L %R Mflop/s
    ------------------------------------------------------------------------------------------------------------------------
    
    --- Event Stage 0: Main Stage
    
    VecScale              42 1.0 1.0709e+00 1.0 2.10e+08 1.0 0.0e+00 0.0e+00 0.0e+00  4 50  0  0  0   4 50  0  0  0   392
    MatMult               42 1.0 5.7360e+00 1.1 2.10e+08 1.0 0.0e+00 0.0e+00 0.0e+00 20 50  0  0  0  20 50  0  0  0    73
    

    因此,42 个VecScale() 操作耗时 1 秒,而 42 个MatMult() 操作耗时 5.7 秒。在最好的情况下,抑制 VecScale() 操作将使代码速度提高 20%。由于 for 循环的开销甚至更低。我想这就是这个函数不存在的原因。

    对于我的计算机性能不佳(VecScale() 为 392Mflops...),我深表歉意。我很想知道你身上发生了什么!

    【讨论】:

    • 感谢您的回答!我测试了您的代码,它工作正常(除了缺少几行)。我想如果影响很小,可能不值得麻烦实施。有趣的是,我对 MatMult (5.77s 73Mflop/s) 的结果几乎完全相同,而 VecScale (2.68s 156Mflop/s) 的结果更糟。我猜我的电脑更糟糕
    猜你喜欢
    • 2017-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-14
    • 2020-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多