Hypre与Petsc安装文档及性能测试

1. 前言

本文介绍了并行计算库的Hypre和Petsc的安装方法以及在线性系统求解中不同算法的性能测试,用于日后在不同系统上的Hypre和Petsc的安装需要和新型算法性能测试基准。程序安装运行环境为NVIDIA-dgx1,详细参数请见dgx1参数。本文将分为Hypre和Petsc两个部分,分别以总体介绍,安装,程序运行关键代码和在IEEE不同节点数据下性能测试的顺序介绍两款软件的使用。

2. Hypre介绍,安装及使用

2.1 Hypre介绍

2.1.1 性能介绍

Hypre是运行在多核处理器上,借助目前性能较好的预处理矩阵(preconditioner)对于大型稀疏线性方程组使用迭代法求解的一个c语言库。其基本目标是让用户可以借助于多核处理器的并行性能,并行存储矩阵不同范围的信息,并行地进行迭代法求解,从而达到事半功倍的效果。Hypre具有扩展性极强的预处理矩阵算法,对于大型系统的预处理矩阵生成也有着不错的性能,并且迭代法所用算法选择空间较大,从后续的测试结果也可以看到,在选择了合适的算法的情况下,对于实际的电力系统线性方程组求解也可以有较快的计算速度。

另一方面,从用户的使用角度来讲,用户无需预先学习复杂的稀疏矩阵存储,而只需分配对应行列坐标给矩阵类,之后的空间压缩操作都可以由Hypre完成,这对于新手来说,可以在最短时间内搭好自己的第一个求解线性方程组程序,是很好的入门函数库。

2.1.2 程序框架介绍

Hypre使用了“原型”的概念,这个概念对于程序来说,是一种储存信息的统一格式,可以更为高效地分配存储空间。在编程之前,用户需要决定对于自己的问题,使用哪一种原型来存储信息。其包括:

  • Structured-Grid System Interface

    这是应用于矩阵中非零元素十分规则,可以用Stencil类型来统一表示非0元素分布的系统。其中Stencil类型使用的相对坐标位置的方法,在确定中心点的情况下(0,0),使用对应坐标来确定非零元素的位置和值,并且在矩阵的赋值过程得以使用。

  • Linear-Algebraic System Interface (IJ)

    IJ适用于一般的线性系统,这类系统非零元素的分布没有规律可循,我们可以通过按行赋值的方式存储矩阵中非零元素的信息。而在赋值完毕后,程序将使用CSR的格式存储非零元素的信息。

在线程的资源分配上,Hypre也采用了相对坐标的方式决定一个线程拥有的矩阵信息范围。使用左下角的坐标点和右上角的坐标点,Hypre可以通过他们的差值来得出其拥有的矩阵范围。另一方面,Hypre也可以通过行坐标的范围,来决定各线程所分配到矩阵范围。用户可以通过自身系统的特点,来判断到底采取哪一种分配方式。

2.1.3 用户使用的Hypre的总体步骤

综上,在使用Hypre计算线性系统方程时,需要包括以下步骤:

  • 根据系统特点,选择不同的原型结构
  • 根据该结构,对系统生成的矩阵进行赋值
  • 为系统不同的线程分配属于该线程的系统信息
  • 选用合适的方法与preconditioner进行求解
  • 获取结果

2.2 Hypre安装

2.2.1 检查openmpi安装

  • 首先检查系统中是否存在openmpi:

    $ mpirun --version
    
    • 如果存在则直接去安装Hypre,否则先安装openmpi(本文档选用的版本是openmpi v1.10)。

2.2.2 安装openmpi

  • 进入openmpi官网(https://www.open-mpi.org/software/ompi/v1.10/),下载.tar.gz文件到本地。

  • 在下载路径下,解压该tar.gz文件

    $ tar -zxvf openmpi-1.10.7.tar.gz
    
  • 进入解压后生成的文件夹

    $ cd openmpi-1.10.7
    
  • configure路径下的文件,注意"--prefix="指定的是安装路径,用户可以自己指定,在后面找得到就行。

    $ ./configure --prefix="/usr/local/openmpi"
    
  • 编译并安装

    $ make 
    $ sudo make install
    
  • 为openmpi设置环境变量,进入~/.bashrc加入如下内容后保存并source

    $ vim ~/.bashrc
    /* 以下内容在.bashrc中更改 */
    export PATH="$PATH:/usr/local/openmpi/bin"
    export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/openmpi/lib/"
    /****************************************************************/
    $ source ~/.bashrc
    
  • 测试是否安装成功:进入openmpi解压的文件夹中有一个examples,运行如下例程将为出现两行"hello",则表示安装成功

    $ mpirun -np 2 ./hello_c
    

2.2.3 安装Hypre

  • 进入Hypre的github中clone源代码

    $ git clone https://github.com/LLNL/hypre.git
    // 进入source code文件夹
    $ cd hypre/src
    
  • 注意在configure的时候要让hypre知道Openmpi在哪

    $ ./configure -prefix=/usr/local/hypre \
        -with-MPI-include=/usr/local/openmpi/include \
        -with-MPI-libs="mpi_cxx mpi" \
        -with-MPI-lib-dirs=/usr/local/openmpi/lib
    
  • 编译安装

    $ sudo make install
    

    需要一段时间。。。

  • 在src文件夹中有一个examples文件夹,里面有测试是否安装成功的例程。在使用Makefile编译后,生成的可执行文件需要mpirun运行。

    $ make
    $ mpirun -np 2 ex1(ex2)
    

    如果正常输出,则表示安装成功。

2.3 Hypre计算代码详解

2.3.1 Hypre线程分配空间方式

在将矩阵不同行分给hypre不同线程时,需要告知该线程矩阵的起始行终止行,在已知矩阵总行数(N)和处理器个数(线程个数 num_procs)的情况下,考虑N无法被num_procs整除的情况,可以得到如下的计算公式。其中,myid表示这是第几个线程。

local_size = N / num_procs;         // size per processor
extra = N - local_size * num_procs; // consider rows cannot be fully divided by procs
ilower = local_size * myid;
ilower += hypre_min(myid, extra);
iupper = local_size * (myid + 1);
iupper += hypre_min(myid + 1, extra);
iupper = iupper - 1;
// update num of rows
local_size = iupper - ilower + 1;

2.3.2 Hypre矩阵,向量储存形式和赋值

目前Hypre支持的存储形式为HYPRE_PARCSR,矩阵类为HYPRE_IJMatrix,和HYPRE_IJVector,经过print打出之后为“行,列,值”的坐标对。矩阵赋值支持按行赋值

HYPRE_IJMatrixSetValues(ij_matrix, nrows, ncols, rows, cols, values);
// 其中,ij_matrix为矩阵地址,nrows是赋值的行数,ncols为该行非0元素个数,rows为行坐标,cols为列作标,values为所赋的非0值

Vector的赋值与上述矩阵赋值相似。

另一方面,需要注意在每次赋值前都需要initialize矩阵,赋值完毕后都需要assemble矩阵,并且获取控制该矩阵的句柄。

HYPRE_IJMatrixInitialize(A);
/* ... 赋值操作 ... */
HYPRE_IJMatrixAssemble(A);
HYPRE_IJMatrixGetObject(A, (void **)&parcsr_A);

2.4 Hypre求解线性系统性能测试







计算题目 计算方法 迭代次数 计算时间
14节点
PCG 13 0.000860s
AMG 5 0.000328s
PCG with AMG preconditioner 4 0.000310s
118节点
PCG 117 0.001329s
AMG 10 0.000752s
PCG with AMG preconditioner 6 0.000787s
10790节点
PCG 6207 0.9464s
AMG 12 0.0337s
PCG with AMG preconditioner 7 0.0284s
福建1425节点
PCG 21246 0.388728s
AMG 迭代发散 NA
PCG with AMG preconditioner 375 0.061298s
四川2433节点
PCG 16705 0.496167s
AMG 迭代发散 NA
PCG with AMG preconditioner 10000(迭代未结束但结果误差在0.01级别) 2.464774s

3. PETSC的安装及使用

3.1 PETSC安装

3.1.1 下载PETSC安装包

说明:本部分基于机器上已经安装有openmpi,如果没有,请移步“安装openmpi”部分。

  • 使用git clone下载petsc源码
$ git clone -b maint https://bitbucket.org/petsc/petsc petsc

3.1.2 安装PETSC

  • 在源代码根目录下,编译源码,假设你的openmpi装在了“/usr/local/openmpi”里面,你想把petsc装在“$HOME/petsc”下:
$ ./configure --with-mpi-dir=/usr/local/openmpi/ --download-fblaslapack --prefix=$HOME/petsc
  • 测试安装是否成功
$ make all test

3.1.3 运行PETSC程序

  • 源代码中有一些example的文件,假定你已经在petsc根目录下面,examples的文件在 “./src/snes/examples/tutorials/”中。注意在make的时候需要指定PETSC_DIR和PETSC_ARCH中的路径。PETSC_DIR就是petsc的根目录,PETSC_ARCH是名字带“ARCH”的文件夹。假设你要编译ex12.c的文件夹
# 编译
$ make PETSC_DIR=$HOME/iterative/petsc PETSC_ARCH=arch-linux2-c-debug ex12
# mpi运行, -n 为指定processor数量
$ mpiexec -n 4 ./ex12

3.2 PETSC计算代码详解

3.2.1 PETSC线程分配空间方式

与Hypre不同的是,PETSC无需显式地表达分配给该线程的矩阵/向量行坐标范围,而只需告诉PETSC矩阵的行数和列数,使用PETSC_DECIDE让PETSC自行决定分配给该线程的行坐标范围,并且可以通过内置的函数来获得属于该线程的起始坐标和结束坐标。以下为示例代码:

// A为matrix
ierr = MatSetSizes(A, PETSC_DECIDE, PETSC_DECIDE, numRow, numCol);
/*...矩阵操作...*/
ierr = MatGetOwnershipRange(A, &Istart, &Iend);

值得一提的是,PETSC中大部分的函数操作均会返回该操作的状态码,可以通过

CHKERRQ(ierr)

来检查程序是否出错。推荐每做一次操作都要检查一次状态码。

3.2.2 PETSC矩阵,向量储存形式和赋值

PETSC存储矩阵的类型为Mat,存储向量的类型为Vec,在矩阵赋值时,需要告知行坐标,赋值个数,和所赋的值。

ierr = MatSetValues(A, 1, &Ii, 1, &J, &v, INSERT_VALUES);

其中INSERT_VALUES表示赋值类型,代表将该坐标上的参数设为v。而在每次赋值完毕后,都需要Assemble矩阵来告知系统矩阵赋值已完成。

// assemble matrix A
ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);
CHKERRQ(ierr);
ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);
CHKERRQ(ierr);

3.3 PETSC求解线性系统性能测试

目前PETSC只能支持PCG的求解,如若要使用AMG的求解需要自行编写相关的代码,因此,本文只在PETSC测试中,使用了PCG的求解方法进行性能测试。

计算题目 迭代次数 计算时间
14节点 13 0.001009s
118节点 78 0.004705s
10790节点 2257 0.911253s
福建1425节点 发散 NA
四川2433节点 发散 NA

4 结论

本测试报告详细总结了并行计算库Hypre,PETSC的安装和求解线性方程组的过程,并且在不同的线性系统问题上进行了性能测试。测试结果表明,Hypre对于实际系统的适应度较高,在算法选择上多样,并且在合适的preconditioner的帮助下,对于实际系统方程的求解也会有比较好的性能。而PETSC在一些算法的开发的上仍然存在不足,如AMG的算法需要自行编写。并且在实际系统环境下的线性方程组求解上,无法获得比较好的结果。

你可能感兴趣的:(Hypre与Petsc安装文档及性能测试)