Arm Performance Libraries是ARM提供的ARM架构下的性能库,提供了Fortran和c的API,子程序包括BLAS,LAPACK。

doc:https://developer.arm.com/documentation/109408/0100/Compile-and-test-the-examples?lang=en

一.安装与配置

安装与配置

Arm Performance Libraries | Arm Learning Paths

安装ARMPL前需要有environment-modules包:

1
2
sudo apt install environment-modules
source /etc/profile.d/modules.sh

如果报了bash: /usr/bin/tclsh: No such file or directory,说明缺少脚本语言tcl的包,sudo apt install tcl一下,再执行上述的source /etc/profile.d/modules.sh就可以了。

下载:https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Libraries#Software-Download (要注意gcc版本,要选和自己系统相符合或至少接近的)

Linux下安装ARMPL:(默认安装到/opt/arm下)

1
2
3
tar -xf arm-performance-libraries_23.10_Ubuntu-20.04_gcc-9.3.tar
cd arm-performance-libraries_23.10_Ubuntu-20.04/
sudo ./arm-performance-libraries_23.10_Ubuntu-20.04.sh -a

配置module files的路径:

1
export MODULEPATH=$MODULEPATH:/opt/arm/modulefiles

之后module avail应该会出现类似:armpl/23.10.0_gcc-9.3。需要编译和使用armpl程序时:

1
module load armpl/23.10.0_gcc-9.3

就可以使用armpl需要的环境了。

测试

在安装路径(默认为/opt/arm/armpl_23.10_gcc-9.3)下有一个examples文件夹,examples下有一些使用了armpl的程序和makefile,执行make会编译并运行这些程序,如果顺利完成,会提示Test passed OK,编写程序也可以从examples下的文件中寻找示例,命名是很规范的。

二.编译与使用

在examples在的makefile可以看到程序编译的命令,下面以SpMV为例。

编译相关参数为(libspmv是另一个使用到的库):

1
CXXOPTFLAGS = -mcpu=native -O3 -fopenmp -std=c++11 -I./libspmv/include -L./libspmv/build -I${ARMPL_DIR}/include -L$(ARMPL_DIR)/lib -larmpl -lamath -lm -lspmv

SpMV实现的代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
int armpl_evaluation(SparseMatrixCOO *ordered_coo, char *output_path){

armpl_spmat_t armpl_mat;
const double alpha = 1.0, beta = 0.0;
int creation_flags = 0;
double *x, *y;
SparseMatrixCSR *csr = (SparseMatrixCSR *)malloc(sizeof(SparseMatrixCSR));
COO_to_CSR(ordered_coo, csr);
y = (double *)malloc(sizeof(double)*csr->nrows);
x = (double *)malloc(sizeof(double)*csr->ncolumns);
generate_x(x, csr->ncolumns);

armpl_status_t info = armpl_spmat_create_csr_d(&armpl_mat, csr->nrows, csr->ncolumns, csr->row_pointers, csr->col_indices, csr->values, creation_flags);
if (info!=ARMPL_STATUS_SUCCESS) { armpl_spmat_print_err(armpl_mat); return (int)info;}
//不需要转置
info = armpl_spmat_hint(armpl_mat, ARMPL_SPARSE_HINT_SPMV_OPERATION, ARMPL_SPARSE_OPERATION_NOTRANS);
if (info!=ARMPL_STATUS_SUCCESS) { armpl_spmat_print_err(armpl_mat); return (int)info; }
//预计有多次调用
info = armpl_spmat_hint(armpl_mat, ARMPL_SPARSE_HINT_SPMV_INVOCATIONS, ARMPL_SPARSE_INVOCATIONS_MANY);
if (info!=ARMPL_STATUS_SUCCESS) { armpl_spmat_print_err(armpl_mat); return (int)info; }

info = armpl_spmv_optimize(armpl_mat);
if (info!=ARMPL_STATUS_SUCCESS) { armpl_spmat_print_err(armpl_mat); return (int)info; }
//SpMV
for (int i=0; i<1; i++) {
info = armpl_spmv_exec_d(ARMPL_SPARSE_OPERATION_NOTRANS, alpha, armpl_mat, x, beta, y);
}

info = armpl_spmat_destroy(armpl_mat);
free(x);
free(y);
return (int)info;
}