A-Tune Ubuntu适配以及对HPL调优

1,853 阅读9分钟

A-Tune

A-Tune功能介绍

A-Tune是一款基于AI开发的系统性能优化引擎,它利用人工智能技术,对业务场景建立精准的系统画像,感知并推理出业务特征,进而做出智能决策,匹配并推荐最佳的系统参数配置组合,使业务处于最佳运行状态。A-Tune核心技术架构如下图,主要包括智能决策、系统画像和交互系统三层。

image.png

智能决策层:包含感知和决策两个子系统,分别完成对应用的智能感知和对系统的调优决策。
系统画像层:主要包括自动特征工程和两层分类模型,自动特征工程用于业务特征的自动选择,两层分类模型用于业务模型的学习和分类。
交互系统层:用于各类系统资源的监控和配置,调优策略执行在本层进行。

A-Tune主要为用户提供以下功能:

  • 基于实时统计数据分析当前负载类型,支持自定义模型。
  • 针对多种应用场景设置默认调优参数和调优脚本,用户开箱即用。
  • 提供离线调优框架,免去人工反复做参数调整、性能评价的调优过程。针对自定义参数寻找的过程,A-Tune提供统一框架,用户设置参数搜索空间,A-Tune提供调优算法和调优结果的展现。

A-Tune模块解析

A-Tune整体由四部分组成:atune-adm,atune Service,atune Rest,atune AI Engine

 atune-adm是整个项目的命令行程序,是用户交互的入口,用户敲入命令后,atune-admin模块通过grpc协议与实际内容提供者atune Server交互,实现展示和处理的解耦。

atune Service是项目中的关键模块,因为它既对上层提供grpc调用服务,同时又负责调用atune Rest,atune AI Engine,处理下层模块的处理结果。

atune Rest基于python实现,通过atune_collector库实现系统数据的采集,与sqlite交互对profile实现增删改查,调用端口是8383。

atune AI Engine是A-Tune整个系统的“智能大脑”,模块已经提前预置一些应用模型,可根据采集的系统数据识别出具体的应用。而且该模块还实现自定义模型,用户自行采集数据并训练出适合用户场景的独特模型。

下面举例分析atune-adm analysis命令的执行过程。

image.png
① atune-adm解析输入参数,传递给内部变量。之后打开grpc通道,调用atune Server模块的Analysis函数,不断监听函数的返回结果,输出到控制台。
② atune Server验证传递进来的参数,接着调用atune Rest模块采集系统信息,信息存入csv文件。
③ atune Server调用atune AI Engine接口完成当前负载识别。
④ atune Server通过查询sqlite数据库,判断识别结果是否在定义中,然后找到预设的profile setting,激活对应配置,完成优化。

适配Ubuntu

A-Tune本身是基于openEuler系统开发,所以要使其也能在Ubuntu运行,需要安装代替组件,根据安装使用文档,安装并成功运行需要满足以下条件:

  • root身份安装软件包和python依赖包。
  • Golang版本 >= 1.15并加入环境变量。
  • 启用采集程序,配置日志写入规则。
  • Linux内核>5.4.0 (不是很精确,但ubuntu 18.04 server版经测试不行)

基于上述要求,实现可在Ubuntu系统一键准备安装环境的脚本,如下所示。

prepare.png

基于A-Tune实现Nginx调优

Nginx是一款轻量级的Web服务器、反向代理服务器,由于它的内存占用少,启动极快,高并发能力强,在互联网项目中广泛应用,提升Nginx处理性能,相当于提高整个处理系统的并发度,所以调优Nginx也是运维人员必备功课,实验环境如下表所示。

操作系统18.04.2
Linux内核版本5.4.0
CPUIntel(R) Xeon(R) Gold 5118 CPU @ 2.30 GHz * 2
RAM64GB DDR4
存储1 TB HDD
Benchmark软件httpress

 

A-Tune本身已经可以对Nginx实现调优,通过遍历参数空间搜索最优参数搭配,原程序主要对以下表中参数进行配置。

调优参数名称参数空间说明
nginx.access_log/var/log/nginx/access.log offnginx访问日志路径
nginx.error_log/var/log/nginx/error.log/dev/nullnginx报错日志路径
net.core.netdev_max_backlog1000~100000当网卡接收数据包的速度大于内核处理的速度时,会有一个队列 保存这些数据包。这个参数表示该队列的最大值
net.ipv4.tcp_keepalive_time600~36000TCP发送keepalive消息的频度
net.core.rmem_max1048576~67108864内核套接字接收缓存区的最大大小
net.core.wmem_max1048576~67108864内核套接字发送缓存区的最大大小
net.ipv4.tcp_tw_reuse0 1 2是否允许将TIME-WAIT状态的socket重新用于新的 TCP连接
net.ipv4.ip_local_port_range32768 609991024 655358192 65535在UDP和TCP连接中本地端口的取值范围
net.ipv4.tcp_max_tw_buckets32768~1048576操作系统允许TIME_WAIT套接字数量的最大值
net.core.somaxconn128~65536当每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许发送到队列的数据包的最大数目
net.ipv4.tcp_max_syn_backlog1024~262144TCP三次握手建立阶段接收SYN请求队列的最大 长度
net.ipv4.tcp_fin_timeout1~120当服务器主动关闭连接时,socket保持在FIN-WAIT-2状态的最大时间

 

除了默认的调优参数,本文扩充可搜索参数列表,配置路径为/etc/atuned/tuning/nginx

调优参数名称参数空间说明
nginx.worker_processes8~32worker 进程数量
nginx.accept_mutexon off进程轮流接受新链接
nginx.multi_accepton off是否同时接受连接所有新请求
nginx.worker_connections768~65535一个 woker 进程处理的连接数
net.core.rmem_default212992~400000内核套接字接收缓存区默认的大小
net.core.wmem_default212992~400000内核套接字发送缓存区默认的大小
fs.file-max805968~1000000进程可以同时打开的最大句柄数

  实验中发现单次httpress的测试结果出现较大抖动,所以本实验对每次配置进行五次实验,去除一个最小值和一个最大值后取平均,实现结果如下图。

image.png  

上图中base表示A-Tune默认参数调优结果,pro为扩展参数空间后的调优结果,从上图可以看出以下结论:
1) A-Tune调优有效果,可以提升Nginx处理性能。
2) 在参数空间不大情况下,提高迭代数不会带来收益;添加新参数,扩展参数空间后,调高迭代数,效果明显。
3) 添加合适的新参数后,可以提高调优表现。

HPL

HPL(The High-Performance Linpack Benchmark)是测试高性能计算集群系统浮点性能的基准。HPL通过对高性能计算集群采用高斯消元法求解一元N次稠密线性代数方程组的测试,评价高性能计算集群的浮点计算能力。

理论浮点峰值是该计算机理论上每秒可以完成的浮点计算次数,主要由CPU的主频决定。
理论浮点峰值=CPU主频×CPU核数×CPU每周期执行浮点(dflop/c)运算的次数。
如何计算自己服务器的理论浮点峰值

HPL环境安装

HPL允许用户为达到最好的性能表现自定义MPI库和BLAS库。

BLAS(Basic Linear Algebra Subprograms)定义了一组应用程序接口标准,是一系列初级操作的规范,如向量之间的乘法、矩阵之间的乘法等。许多数值计算软件库都实现了这一核心,比如OpenBLAS、GotoBLAS、Atlas、再到Intel 的MKL。

MPI(message passing interface)即信息传递接口,是用于跨节点通讯的基础软件环境。它提供让相关进程之间进行通信,同步等操作的API。常用的MPI库有MPICH3、OpenMPI、以及Intel的MPI库。

安装并测试HPL命令步骤:

sudo apt-get install -y gcc g++ gfortran

cd ~
wget https://www.netlib.org/benchmark/hpl/hpl-2.3.tar.gz
mv hpl-2.3 hpl
cd hpl/setup
sh make_generic
cp Make.UNKNOWN ../Make.linux
cd ../

# 操作:修改Make文件配置后

make arch=linux -j $(nproc)
cd bin/linux

# 操作:修改HPL.data后运行

mpiexec -n 8 ./xhpl

安装BLAS、MPI库

各库资源链接,自己使用没啥问题
链接:pan.baidu.com/s/1S4KgWV44… 提取码:lcnm

gotoBLAS

# copy lapack to the project dir
mv ../lapack-3.1.1.tgz ./lapack
# 修改以下地方
vim f_check
# content:wq
# if (($linker_l ne "") || ($linker_a ne "")) {
#    print MAKEFILE "FEXTRALIB=$linker_L  -lgfortran -lm -lquadmath $linker_a\n";
# }

make CC=gcc BINARY=64 TARGET=NEHALEM

openBLAS

cd OpenBLAS-0.3.20
make

Atlas

sudo apt-get install -y libatlas-base-dev

INTEL-MKL

www.intel.com/content/www…
找到并下载oneMKL,之后执行

sh xxx.sh

安装MPI

MPICH3

sudo ./configure --prefix=/usr/local/mpich
make -j $(nproc)
make install

OpenMPI

./configure --prefix="/root/MPI/openmpi"
make -j $(nproc)
make install

Intel-MPI

www.intel.com/content/www…
找到并下载MPI Library,之后执行

sh xxx.sh

选优组件

如何确定基准HPL.data
ulhpc-tutorials.readthedocs.io/en/latest/p… help.aliyun.com/document_de…

Intel-MPI与其他BLAS不能搭配,好像需要Intel自家的编译库,还是商业版,遂放弃,只进行了Intel-MPI与Intel-MKL的测试,测试命令如下:

# Inter-MPI的安装路径
cd xx/xx/benchmark/mp_linkpack
# 切记不要手动设置
source /opt/intel/oneapi/mpi/latest/env/vars.sh
./build.sh

其他库,两两搭配,看效果

#!/usr/bin/env bash
# set -v on
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

#=================================================
#	System Required: Ubuntu 18.04
#	Description: generate Make.intel for different BLAS and MPI
#       Time: 2022_4_3
#	Version: 1.0.1
#	Author: no_one
#=================================================

Green_font_prefix="\033[32m" && Red_font_prefix="\033[31m" && Green_background_prefix="\033[42;37m" && Red_background_prefix="\033[41;37m" && Font_color_suffix="\033[0m"
Info="${Green_font_prefix}[信息]${Font_color_suffix}"
Error="${Red_font_prefix}[错误]${Font_color_suffix}"
Tip="${Green_font_prefix}[注意]${Font_color_suffix}"

MPdir=""
MPinc=""
MPlib=""
LAdir=""
LAinc=""
LAlib=""
BinDir=""
# export LD_LIBRARY_PATH

# activate BLASes
activate_gotoBlas(){
    echo -e "${Info} set gotoblas env..."
    LAdir=""
    LAinc=""
    LAlib="/root/blas/GotoBLAS2-1.13/GotoBLAS2/libgoto2.a -lpthread -lm" 
}

activate_openBlas(){
    echo -e "${Info} setopenblas env..."
    LAdir=""
    LAinc=""
    LAlib="/root/blas/OpenBLAS-0.3.20/libopenblas.a -lpthread -lm" 
}

activate_atlas(){
    echo -e "${Info} set atlas env..."
    LAdir=""
    LAinc="-I/usr/include/x86_64-linux-gnu/atlas"
    LAlib="-lblas" 
}

activate_mkl(){
    echo -e "${Info} set mkl env..."
    LAdir="/opt/intel/oneapi/mkl/latest"
    LAinc='-I$(LAdir)/include'
    LAlib='-Wl,--start-group $(LAdir)/lib/intel64/libmkl_intel_lp64.a $(LAdir)/lib/intel64/libmkl_sequential.a $(LAdir)/lib/intel64/libmkl_core.a -Wl,--end-group -ldl -lpthread -lm'
}

# active MPIs
activate_mpich3(){
    echo -e "${Info} set mpich3 env..."
    export LD_LIBRARY_PATH=/root/mpi/env/mpich/lib/
    MPdir=""
    MPinc="-I/root/mpi/env/mpich/include/"
    MPlib="/root/mpi/env/mpich/lib/libmpich.so -L/root/mpi/env/mpich/lib/"
    BinDir="/root/mpi/env/mpich/bin"
}

activate_openmpi(){
    echo -e "${Info} set openmpi env..."
    MPdir=""
    MPinc="-I/root/mpi/env/openmpi/include/"
    MPlib="/root/mpi/env/openmpi/lib/libmpi.so"
    BinDir="/root/mpi/env/openmpi/bin"   
    export OMPI_ALLOW_RUN_AS_ROOT=1
    export OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1
}

activate_oneapi(){
    echo -e "${Info} set oneapi-mpi env..."
    MPdir="/opt/intel/oneapi/mpi/latest"
    MPinc='-I$(MPdir)/include/'
    MPlib='$(MPdir)/lib/libmpicxx.a -L/opt/intel/oneapi/mpi/latest/lib/ -L/opt/intel/oneapi/mpi/latest/lib/release'
    BinDir="/opt/intel/oneapi/mpi/latest/bin"
    export LD_LIBRARY_PATH=/opt/intel/oneapi/mpi/latest/lib/release
}

generate_makefile(){
    # Make.intel需要自己移动到工作目录下,
    cp ./tempalte.intel ./Make.intel
    echo -e "${Info} ${BinDir} with ${LAinc}/${LAlib}"
    sed -i "s#^MPdir\s*=.*#MPdir = ${MPdir}#g" ./Make.intel
    sed -i "s#^MPinc\s*=.*#MPinc = ${MPinc}#g" ./Make.intel
    sed -i "s#^MPlib\s*=.*#MPlib = ${MPlib}#g" ./Make.intel

    sed -i "s#^LAdir\s*=.*#LAdir = ${LAdir}#g" ./Make.intel
    sed -i "s#^LAinc\s*=.*#LAinc = ${LAinc}#g" ./Make.intel
    sed -i "s#^LAlib\s*=.*#LAlib = ${LAlib}#g" ./Make.intel

    sed -i "s#^CC\s*=.*#CC = ${BinDir}/mpicc#g" ./Make.intel
    sed -i "s#^LINKER\s*=.*#LINKER = ${BinDir}/mpif77#g" ./Make.intel
}

make_file(){
    make arch=intel clean > /dev/null 2>&1
    make arch=intel -j $(nproc) -w >> make.log 2>&1
    # make arch=intel -j $(nproc)
    if [ $? -ne 0 ]; then
        exit
    fi
}

run_test(){
    cp ./bin/HPL.dat ./bin/intel/
    cd ./bin/intel || exit
    ${BinDir}/mpiexec -n 8 ./xhpl
}

run(){
    generate_makefile
    make_file
    run_test
    cd /root/hpl || exit
}

image.png

PS:改变gcc参数有奇效,比如以下参数 参数名称 | 参数说明 | | --------------------- | -------------- | | -fomit-frame-pointer | 少了栈帧的切换和栈地址的保存 | | -O3 | 提高代码的并行执行程度 | | -funroll-loops | 启发式地决定展开哪些代码循环

基于A-Tune实现HPL调优

这里主要用到了A-Tune的离线调优命令

# Start to tuning
atune-adm tuning --project hpl --detail hpl_client.yaml
# Restore the environment
atune-adm tuning --restore --project hpl

新建目录文件,充当命令行参数

$ cat hpl_client.yaml
project: "hpl"
engine : "gbrt"
iterations : 30
random_starts : 10

benchmark : "sh /root/hpl/bin/intel/run.sh"
evaluations :
  -
    name: "Gflops"
    info:
        get: "echo '$out' | grep 'WC11C2R4' | awk '{print $7}'"
        type: "negative"
        weight: 100

修改server配置,路径/etc/atuned/tuning/,新建目录hpl

$ cat tuning_params_hpl.yaml
project: hpl
maxiterations: 100
startworkload: ''
stopworkload: ''
object:
- name: problems.N
  info:
    desc: The size of problems
    get: cat /root/hpl/bin/intel/HPL.dat |awk '/Ns$/{print}'|awk '{print $1}'
    set: sed -i 's#.*Ns$#$value    Ns#g' /root/hpl/bin/intel/HPL.dat
    needrestart: 'false'
    type: discrete
    scope:
    - 64880
    - 78776
    step: 2024
    items: null
    dtype: int
- name: problems.NB
  info:
    desc: The minimum granularity of the calculation
    get: cat /root/hpl/bin/intel/HPL.dat |awk '/NBs$/{print}'|awk '{print $1}'
    set: sed -i 's#.*NBs$#$value    NBs#g' /root/hpl/bin/intel/HPL.dat
    needrestart: 'false'
    type: discrete
    scope:
    - 96
    - 256
    step: 16
    items: null
    dtype: int
- name: vm.swappiness
  info:
    desc: A larger value indicates that the swap partition is used more actively.
      A smaller value indicates that the memory is used more actively.
    get: sysctl -n vm.swappiness
    set: sysctl -w vm.swappiness=$value
    needrestart: 'false'
    type: discrete
    scope:
    - 0
    - 60
    step: 10
    items: null
    dtype: int
- name: kernel.randomize_va_space
  info:
    desc: Setting Memory Address Randomization
    get: sysctl -n kernel.randomize_va_space
    set: sysctl -w kernel.randomize_va_space=$value
    needrestart: 'false'
    type: discrete
    scope:
    - 0
    - 2
    step: 1
    items: null
    dtype: int

之后操作就是运行离线调优命令
效果提升不大,结果就不放了。。。

心得体会

  • VMWare不适合HPL测试,它是通过时间片的方式“虚拟”出一个cpu,而且还受分配cpu总数的影响。
  • A-Tune不支持变量调优,比如对调优的变量存在线性关系的情况,还不能处理
    (前前后后折腾两周,麻

参考来源:

gitee.com/openeuler/A…
blog.csdn.net/weixin_4702…
scc.ustc.edu.cn/zlsc/pxjz/2…
warmshawn.github.io/2019/02/17/…
ulhpc-tutorials.readthedocs.io/en/latest/p…
gist.github.com/Levi-Hope/2…
barry-flynn.github.io/2021/10/13/…
www.intel.com/content/www…
community.arm.com/arm-communi…
help.aliyun.com/document_de…
blog.csdn.net/greenapple_…
blog.csdn.net/sishuiliuni…