1 下载安装包
读者可以在文末的参考链接中找到 HPL[1], openMPI[2], OpenBLAS[3] 的下载页面,本文选择的版本为:
软件包 | 版本 |
---|---|
HPL | 2.3 |
openMPI | 4.0.4 |
OpenBLAS | 0.3.20 |
2 安装 OpenMPI
OpenMPI官网:https://www.open-mpi.org/
OpenMPI 需要手动编译安装,以下为本文的安装命令,读者可以根据自身情况修改路径
tar -zxvf /root/share/soft/pkgs/openmpi-4.0.4.tar.gz -C /root/share/soft/build
cd /root/share/soft/build/openmpi-4.0.4
## --prefix参数用于指定openmpi的安装路径
./configure --prefix=/root/share/soft/tool/openmpi/4.0.4
make -j
make install
单核编译 openMPI 大概需要半个小时,如果需要加速可以使用并行编译
编译完毕之后,需要声明一些环境变量
export OPENMPI_HOME=/root/share/soft/tool/openmpi/4.0.4
export PATH=$OPENMPI_HOME/bin:$PATH
export LD_LIBRARY_PATH=$OPENMPI_HOME/lib:$LD_LIBRARY_PATH
export LIBRARY_PATH=$OPENMPI_HOME/lib:$LIBRARY_PATH
export CPATH=$OPENMPI_HOME/include:$CPATH
export C_INCLUDE_PATH=$OPENMPI_HOME/include:$C_INCLUDE_PATH
这些环境变量只会存在于当前的会话窗口中,读者可以将其添加到自己的 bashrc 文件中或添加到 module 中,openmpi 的modulefile 文件见附录 2
安装完成之后,可以将 openMPI 添加到 module 中,便于管理
安装完成之后,可以用新编译得到的 mpi 编译用一下 helloworld 程序,源代码见附录 3
使用 mpicc 命令编译:mpicc -o hellowordlMPI ./helloworld.c
然后使用四个核心并行运行: mpirun -n 4 ./helloworldMPI
如果不报错说明 openMPI 安装成功
3 安装 BLAS
OpenBLAS 官网:https://www.openblas.net/
tar -zxvf /root/share/soft/pkg/OpenBLAS-0.3.20.tar.gz -C /root/share/soft/build/
cd /root/share/soft/build/openblas-0.3.20
make
make PREFIX=/root/share/soft/tool/openblas/0.3.20 install
如果要用icc 编译openblas 采用 CC=icc FC=ifort make
4 安装 HPL
之前的 openMPI 和 OpenBLAS,本文将其安装在了 tool 目录中,意为工具,但 HPL 是一种应用,所以会将HPL放置在 app 目录中以作区分
mkdir -p /root/share/soft/app/hpl
tar -zxvf /root/share/soft/pkg/hpl-2.3.tar.gz -C /root/share/soft/app/hpl
cd /root/share/soft/app/hpl-2.3
# 进入setup目录选择一个后缀名和机器环境相近的文件复制到hpl的根目录,且将后缀进行更改,这个后缀很重要!读者也可以自定义这个后缀名,本文定义为qiql
cp setup/Make.Linux_PII_FBLAS ./Make.qiql
进入Make.qiql文件ma
#
SHELL = /bin/sh
#
CD = cd
CP = cp
LN_S = ln -s
MKDIR = mkdir
RM = /bin/rm -f
TOUCH = touch
#
# ----------------------------------------------------------------------
# - Platform identifier ------------------------------------------------
# ----------------------------------------------------------------------
#
ARCH = qiql ## 这里修改成上文提到的那个后缀
#
# ----------------------------------------------------------------------
# - HPL Directory Structure / HPL library ------------------------------
# ----------------------------------------------------------------------
#
TOPdir = /root/share/soft/app/hpl-2.3 ## 这里修改为hpl的全路径
INCdir = $(TOPdir)/include
BINdir = $(TOPdir)/bin/$(ARCH)
LIBdir = $(TOPdir)/lib/$(ARCH)
#
HPLlib = $(LIBdir)/libhpl.a
#
# ----------------------------------------------------------------------
# - Message Passing library (MPI) --------------------------------------
# ----------------------------------------------------------------------
#
MPdir = mpicc ## 除非读者使用的是 intel 的编译器,那么这个地方应该填写的是 mpiicc,否则都应该填写 mpicc
# MPinc = -I$(MPdir)/include # 注释本行
# MPlib = $(MPdir)/lib/libmpich.a # 注释本行
#
# ----------------------------------------------------------------------
# - Linear Algebra library (BLAS or VSIPL) -----------------------------
# ----------------------------------------------------------------------
# LAdir = $(HOME)/netlib/ARCHIVES/Linux_PII # 注释本行
LAinc =
LAlib = -L/root/share/soft/tool/openblas/0.3.20/lib -lopenblas ## 这里将中间部分填写为 OpenBLAS 库的安装路径
#
# ----------------------------------------------------------------------
# - F77 / C interface --------------------------------------------------
F2CDEFS = -DAdd__ -DF77_INTEGER=int -DStringSunStyle
#
# ----------------------------------------------------------------------
# - HPL includes / libraries / specifics -------------------------------
# ----------------------------------------------------------------------
#
HPL_INCLUDES = -I$(INCdir) -I$(INCdir)/$(ARCH) $(LAinc) $(MPinc)
HPL_LIBS = $(HPLlib) $(LAlib) $(MPlib)
#
# - Compile time options -----------------------------------------------
#
HPL_OPTS =
#
# ----------------------------------------------------------------------
#
HPL_DEFS = $(F2CDEFS) $(HPL_OPTS) $(HPL_INCLUDES)
#
# ----------------------------------------------------------------------
# - Compilers / linkers - Optimization flags ---------------------------
# ----------------------------------------------------------------------
#
CC = mpicc # 这里可以直接填 mpicc
CCNOOPT = $(HPL_DEFS)
CCFLAGS = $(HPL_DEFS) -fomit-frame-pointer -O3 -funroll-loops -W -Wall
#
#
LINKER = mpicc # 这里也可以是mpicc
LINKFLAGS = $(CCFLAGS)
#
ARCHIVER = ar
ARFLAGS = r
RANLIB = echo
#
# ----------------------------------------------------------------------
修改完毕后,进入 Make.top 文件,将其中的 arch 字段也修改为 qiql
然后执行 make arch=qiql 以开始编译
编译完成后,会在 hpl 的根目录下生成 bin 目录,如果有 xhpl 这个可执行文件和 HPL.dat 配置文件,说明编译成功
5 调试 LInpack
调试 linpack 主要就在于修改 HPL.dat 这个输入文件,这个应用本质上就是在解一个线性方程组,所以需要对方程组的块大小,阶数,并行核数不断进行调整,使其能够充分发挥计算机的效能。目前有一些成熟的工具来生成此 HPL.dat 文件,参考:https://gitlab.fysik.su.se/hpc-support/hpl/-/tree/master
在运行之前,往往需要将 OpenBLAS 的库路径添加到环境变量 LD_LIBRARY_PATH 中去
export LD_LIBRARY_PATH=/root/share/soft/tool/openblas/0.3.20/gcc/11.2.0/lib:$LD_LIBRARY_PATH
HPL.dat 配置文件中各参数说明参考:http://muchong.com/t-2238311-1-pid-3
http://www.netlib.org/benchmark/hpl/tuning.html
一份可供参考的 HPL.dat 文件:
HPLinpack benchmark input file
Innovative Computing Laboratory, University of Tennessee
HPL.out output file name (if any)
file device out (6=stdout,7=stderr,file)
1 # of problems sizes (N)
318720 Ns
1 # of NBs
240 NBs
0 PMAP process mapping (0=Row-,1=Column-major)
1 # of process grids (P x Q)
8 Ps
16 Qs
16.0 threshold
3 # of panel fact
0 1 2 PFACTs (0=left, 1=Crout, 2=Right)
2 # of recursive stopping criterium
2 4 NBMINs (>= 1)
1 # of panels in recursion
2 NDIVs
3 # of recursive panel fact.
0 1 2 RFACTs (0=left, 1=Crout, 2=Right)
1 # of broadcast
0 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM)
1 # of lookahead depth
0 DEPTHs (>=0)
2 SWAP (0=bin-exch,1=long,2=mix)
64 swapping threshold
0 L1 in (0=transposed,1=no-transposed) form
0 U in (0=transposed,1=no-transposed) form
1 Equilibration (0=no,1=yes)
8 memory alignment in double (> 0)
运行命令为:
mpirun -n 128 --allow-run-as-root ./xhpl
6 报错集锦及解决方案
-
No rule to make target `Make.inc’. Stop.
-
详细报错信息
Makefile:47: Make.inc: No such file or director make[2]: *** No rule to make target `Make.inc'. Stop.
-
原因:这个错误主要是没有正确的修改配置文件导致的,从 Make.top 文件中可以看到这个 Make.inc 文件的来源:
leaf : - ( $(CD) $(le) ; $(MKDIR) $(arch) ) - ( $(CD) $(le)/$(arch) ; \ $(LN_S) $(TOPdir)/Make.$(arch) Make.inc )
前面的$(TOPdir) 变量是在 Make.qiql(qiql为自定义的后缀名)文件中定义的,所以如果在 Make.qiql 中没有正确的配置 $(TOPdir) ,就会出现这个错误
注意:$(TOPdir) 是 hpl 的解压目录,该软件的解压与安装在同一目录,读者可以找到Make.top 这个文件所在的位置,然后执行pwd获取当前目录并填入
-
解决办法:该错误发生后,无法先执行 make arch=qiql clean 进行清理然后再执行 make arch=qiql 重新编译,清理时会报错,此时建议将整个hpl文件夹删除,重新开始配置和编译
-
-
gcc: error: mpicc/lib/libmpich.a: No such file or directory
-
详细报错信息
mpicc -DAdd__ -DF77_INTEGER=int -DStringSunStyle -I/home/wxsc/zhangw/GPFS/qiql/app/hpl-2.3/include -I/home/wxsc/zhangw/GPFS/qiql/app/hpl-2.3/include/qiql -Impicc/include -fomit-frame-pointer -O3 -funroll-loops -W -Wall -o /home/wxsc/zhangw/GPFS/qiql/app/hpl-2.3/bin/qiql/xhpl HPL_pddriver.o HPL_pdinfo.o HPL_pdtest.o /home/wxsc/zhangw/GPFS/qiql/app/hpl-2.3/lib/qiql/libhpl.a -L/home/wxsc/zhangw/GPFS/qiql/tool/openblas/0.3.20 -lopenblas mpicc/lib/libmpich.a gcc: error: mpicc/lib/libmpich.a: No such file or directory make[2]: *** [dexe.grd] Error 1
-
原因:这个错误是因为读者没有正确的理解安装 linpack 的过程,本文所安装的 openmpi,只是 mpi 接口的其中一种实现,除此以外,还有 mpich,intel-mpi等多种实现库,hpl-2.3 中的默认配置文件中使用的是 mpich。所以默认链接的是 libmpich.a 这个文件
在前文的表述中,要求读者直接注释掉 Make 文件中的 MPinc 和 MPlib 变量,因为此时 MPdir 配置的已经是 mpicc,而 mpicc 已经存在于环境变量中PATH中了,mpicc 的库路径也都声明到了其他的环境变量中去了,程序在编译过程中,如果在 Make 文件中找不到,那么程序会自己在环境变量中去寻找,所以可以直接注释掉这两个变量,当然,读者也可以把这个地方写为实际安装的 openMPI 的 bin 目录,lib 目录,include 目录。
-
解决办法:见原因。修改完之后,无需删除整个 hpl 文件夹,执行 make arch=qiql clean 进行清理,然后编译( qiql 为自定义的后缀名)
-
-
/bin/ld: cannot find -lopenblas
-
详细报错信息
mpicc -DAdd__ -DF77_INTEGER=int -DStringSunStyle -I/home/wxsc/zhangw/GPFS/qiql/app/hpl-2.3/include -I/home/wxsc/zhangw/GPFS/qiql/app/hpl-2.3/include/qiql -fomit-frame-pointer -O3 -funroll-loops -W -Wall -o /home/wxsc/zhangw/GPFS/qiql/app/hpl-2.3/bin/qiql/xhpl HPL_pddriver.o HPL_pdinfo.o HPL_pdtest.o /home/wxsc/zhangw/GPFS/qiql/app/hpl-2.3/lib/qiql/libhpl.a -L/home/wxsc/zhangw/GPFS/qiql/tool/openblas/0.3.20 -lopenblas /bin/ld: cannot find -lopenblas collect2: error: ld returned 1 exit status make[2]: *** [dexe.grd] Error 1
-
原因:编译 Linpack 需要一个数学库,这个库可以是 OpenBLAS,也可以是GotoBLAS,也可以是 intel 的 MKL,本文选择的是OpenBLAS,在编译时,linpack 需要能够链接到库的库文件( .so 或 .a 文件),所以需要在 Make.qiql 文件中声明 OpenBLAS 库的位置,为了简便起见,本文要求读者直接注释掉了LAdir, LAinc 变量,因为这两个变量实际上并未参与到 linpack 的编译链接过程。
仔细观察这句命令: LAlib = -L/root/share/soft/tool/openblas/0.3.20/lib -lopenblas 其中的 -L 表示编译器会在/root/share/soft/tool/openblas/0.3.20/lib 路径下寻找需要的库文件, -lopenblas 表示编译器会在 -L 所指定的路径下搜索名为 openblas.so 或 openblas.a 的库文件,**而不会在所指定的路径的子目录下递归的寻找!**所以如果这里的配置出现问题,那么 linpack 在编译时就会报错说找不到 -lopenblas。
-
解决方案:仔细核对 openblas 是否安装成功,到 openblas 的安装目录下寻找是否有lib目录,看看lib目录下是否有相应的库文件,然后在配置 LAdir 时,仔细核对所填写的路径是否精确到了 openblas 的 lib 目录。另:在 -L 和其后所指定的路径之间,可以存在空格。修改完之后,无需删除整个 hpl 文件夹,执行 make arch=qiql clean 进行清理,然后编译(qiql为自定义的后缀名)
-
附录1 安装脚本
#!/usr/bin/bash
set -e
### 本文件为 linpack 的安装脚本,在执行本脚本之前,需要先指定一些配置
### 当前时间:2022年6月27日16:16:56
## 指定 OpenMPI 的安装包路径【可选】(默认与本脚本位于同一路径)
openmpi_pkg_dir=$(dirname $(readlink -f "$0"))
## 指定 OpenMPI 的 build 路径【可选】(默认与本脚本位于同一路径)
openmpi_build_dir=$(dirname $(readlink -f "$0"))/build
## 指定 OpenMPI 的版本号
openmpi_version=4.0.4
## 指定 OpenMPI 的安装路径
openmpi_install_dir=/to/your/path/openmpi/${openmpi_version}
# /home/wxsc/zhangw/GPFS/qiql/tool/openmpi/${openmpi_version}
## 指定 OpenBLAS 的安装包路径【可选】(默认与本脚本位于同一路径)
openblas_pkg_dir=$(dirname $(readlink -f "$0"))
## 指定 OpenBLAS 的 build 路径【可选】(默认与本脚本位于同一路径)
openblas_build_dir=$(dirname $(readlink -f "$0"))/build
## 指定 OpenBLAS 的版本号
openblas_version=0.3.20
## 指定 OpenBLAS 的安装路径
openblas_install_dir=/to/your/path/openblas/${openblas_version}
# /home/wxsc/zhangw/GPFS/qiql/tool/openblas/${openblas_version}
## 指定 HPL 的安装包路径【可选】(默认与本脚本位于同一路径)
hpl_pkg_dir=$(dirname $(readlink -f "$0"))
## 指定 HPL 的版本号
hpl_version=2.3
## 指定 HPL 的安装路径
hpl_install_dir=/to/your/path
# /home/wxsc/zhangw/GPFS/qiql/app
## 指定 hpl 的后缀,可以设置成任意名称
hpl_arch=qiql
### 指定完毕
## 开始安装 OpenMPI
echo "============================================================================="
echo "============================================================================="
echo "=================== start install openmpi-$openmpi_version} ================="
mkdir -p ${openmpi_build_dir}
tar -zxvf ${openmpi_pkg_dir}/openmpi-${openmpi_version}.tar.gz -C ${openmpi_build_dir}
cd ${openmpi_build_dir}/openmpi-${openmpi_version}
./configure --prefix=${openmpi_install_dir}
make -j
make install
## 安装 OpenMPI 完毕
echo "=================== openmpi has been install to ${openmpi_install_dir} ======"
echo "=================== install openmpi-${openmpi_version} finish ==============="
echo "============================================================================="
echo "============================================================================="
## 开始安装 OpenBLAS
echo "============================================================================="
echo "============================================================================="
echo "=================== start install OpenBLAS-$openblas_version} ==============="
mkdir -p ${openblas_build_dir}
tar -zxvf ${openblas_pkg_dir}/OpenBLAS-${openblas_version}.tar.gz -C ${openblas_build_dir}
cd ${openblas_build_dir}/OpenBLAS-${openblas_version}
make -j
make PREFIX=${openblas_install_dir} install
## 安装 OpenBLAS 完毕
echo "=================== OpenBLAS has been install to ${openblas_install_dir} ===="
echo "=================== install OpenBLAS-${openblas_version} finish ============="
echo "============================================================================="
echo "============================================================================="
## 开始安装 hpl
mkdir -p ${hpl_install_dir}
tar -zxvf ${hpl_pkg_dir}/hpl-${hpl_version}.tar.gz -C ${hpl_install_dir}
cd ${hpl_install_dir}/hpl-${hpl_version}
## 新建一个环境变量脚本,后面如果要使用hpl,需要 source 该脚本,脚本放置在hpl的根目录下
touch env.hpl.sh
## 将 OpenMPI 添加到环境变量中去
echo export OPENMPI_HOME=${openmpi_install_dir} > env.hpl.sh
echo export PATH=\$OPENMPI_HOME/bin:\$PATH >> env.hpl.sh
echo export LD_LIBRARY_PATH=\$OPENMPI_HOME/lib:\$LD_LIBRARY_PATH >> env.hpl.sh
echo export LIBRARY_PATH=\$OPENMPI_HOME/lib:\$LIBRARY_PATH >> env.hpl.sh
echo export CPATH=\$OPENMPI_HOME/include:\$CPATH >> env.hpl.sh
echo export C_INCLUDE_PATH=\$OPENMPI_HOME/include:\$C_INCLUDE_PATH >> env.hpl.sh
## OpenMPI 添加环境变量完毕
## 将编译得到的 OpenBLAS 库路径添加到环境变量中去
echo export LD_LIBRARY_PATH=${openblas_install_dir}/lib:\$LD_LIBRARY_PATH >> env.hpl.sh
## 添加完毕
cd ${hpl_install_dir}/hpl-${hpl_version}
source ./env.hpl.sh
# 进入setup目录选择一个后缀名和机器环境相近的文件复制到hpl的根目录,且将后缀进行更改,这个后缀很重要!
cp setup/Make.Linux_PII_FBLAS Make.${hpl_arch}
## 修改ARCH字段
sed -i "s/ARCH = Linux_PII_FBLAS/ARCH = ${hpl_arch}/g" ./Make.${hpl_arch}
## 修改TOPdir 为 hpl 的实际安装路径
# sed -i "s/TOPdir = \$(HOME)\/hpl/TOPdir = ${hpl_install_dir}\/hpl-${hpl_version}/g" ./Make.${hpl_arch}
sed -i "/TOPdir = \$(HOME)\/hpl/a\\TOPdir = ${hpl_install_dir}\/hpl-${hpl_version}" ./Make.${hpl_arch}
## 修改MPdir 为mpicc
sed -i "s/MPdir = \/usr\/local\/mpi/MPdir = mpicc/g" ./Make.${hpl_arch}
## 在MPinc字段前加注释#
sed -i 's/MPinc */#&/g' ./Make.${hpl_arch}
## 在MPlib字段前加注释
sed -i 's/MPlib */#&/g' ./Make.${hpl_arch}
## 在LAdir字段前加注释
sed -i 's/LAdir */#&/g' ./Make.${hpl_arch}
## 在LAinc字段前加注释
sed -i 's/LAinc */#&/g' ./Make.${hpl_arch}
## 在LAlib字段后添加 OpenBLAS 正确的路径
sed -i "/LAlib =/a\\LAlib = -L${openblas_install_dir}\/lib -lopenblas" ./Make.${hpl_arch}
## 将 CC 字段修改为 mpicc
sed -i 's/CC = \/usr\/bin\/gcc/CC = mpicc/g' ./Make.${hpl_arch}
## 将 LINKER 字段修改为mpicc
sed -i 's/LINKER = \/usr\/bin\/g77/LINKER = mpicc/g' ./Make.${hpl_arch}
## Make.${hpl_arch} 文件修改完毕
## 修改 Make.top 文件中的 arch 字段
sed -i "s/arch = UNKNOWN/arch = ${hpl_arch}/g" ./Make.top
## Make.top 文件修改完毕
## 编译 hpl
make arch=${hpl_arch}
## 编译完毕
echo "============================================================================="
echo "============================================================================="
echo "============================================================================="
echo "============================================================================="
echo "============================================================================="
echo "hpl has been install to ${hpl_install_dir}/hpl-${hpl_version}/bin/${hpl_arch}"
echo "openmpi-${openmpi_version} has been install to ${openmpi_install_dir}, openblas-${openblas_version} has been install to ${openblas_install_dir}"
echo "Before using hpl, please source the env.hpl.sh script in the ${hpl_install_dir}/hpl-${hpl_version} to add environment variables to the session"
echo "============================================================================="
echo "============================================================================="
echo "============================================================================="
set +e
### END
附录 2 openMPI 的 modulefile
#%Module
proc ModulesHelp { } {
puts stderr "\tThis module adds openmpi compiled with default intel compiler."
}
module load gcc/11.2.0
set OPENMPI_HOME /root/share/soft/tool/openmpi/4.0.4
set MPI_ROOT $OPENMPI_HOME
prepend-path PATH $OPENMPI_HOME/bin
prepend-path LD_LIBRARY_PATH $OPENMPI_HOME/lib
prepend-path LIBRARY_PATH $OPENMPI_HOME/lib
prepend-path CPATH $OPENMPI_HOME/include
prepend-path C_INCLUDE_PATH $OPENMPI_HOME/include
# installed by qiql, 2022-06-24.
附录 3 MPI 测试并行程序
#include <mpi.h>
#include <stdio.h>
int main(int argc, char** argv) {
// Initialize the MPI environment
MPI_Init(NULL, NULL);
// Get the number of processes
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
// Get the rank of the process
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
// Get the name of the processor
char processor_name[MPI_MAX_PROCESSOR_NAME];
int name_len;
MPI_Get_processor_name(processor_name, &name_len);
// Print off a hello world message
printf("Hello world from processor %s, rank %d out of %d processors\n",
processor_name, world_rank, world_size);
// Finalize the MPI environment.
MPI_Finalize();
}
评论区