在阿里云 ECS 上使用 Analytics Zoo 对人工智能应用进行 bfloat16 加速

本文将介绍在阿里云第七代高主频 ECS 实例上,利用 Analytics Zoo 和第三代智能英特尔® 至强® 可扩展处理器提供的 bfloat16 特性提高人工智能应用的性能。

author-image

作者

背景信息

● 阿里云第七代高主频 ECS 实例构建于第三代神龙平台之上,基于第三代智能英特尔® 至强® 可扩展处理器创建。相对于上一代,阿里云 ECS 云服务器第七代高主频实例计算性能最大可以提升 260%。在 ECS 上使用 Analytics Zoo,可以利用 Analytics Zoo 的高级流水线特性,比如使用英特尔优化的深度学习框架(例如 TensorFlow、PyTorch 等)开发深度学习应用。

● 第三代智能英特尔® 至强® 可扩展处理器提供了业界领先、经工作负载优化的平台,并内置了 AI 加速功能--增强型英特尔® Deep Learning Boost(英特尔® DL Boost)。增强型英特尔® DL Boost 通过业界首次对 bfloat16 的 x86 支持,增强了人工智能推理和训练性能。

● 第三代智能英特尔® 至强® 可扩展处理器可运行复杂的人工智能工作负载。增强型英特尔® DL Boost 将人工智能训练最高提升 1.93 倍,图像分类性能最高提升 1.87 倍,自然语言处理的训练性能提升 1.7 倍,推理提升 1.9 倍。新的 bfloat16 处理支持使医疗保健、金融服务和零售业的人工智能训练工作负载受益匪浅。

● Analytics Zoo 是英特尔开源的统一的大数据和 AI 平台,它可以无缝的将 TensorFlow、Keras、PyTorch 等 AI 程序扩展到分布式 Spark、Flink、Ray 等大数据平台上运行。Analytics Zoo 提供了以下特性:

         o   为基于 TensorFlow、PyTorch、OpenVINO 等的 AI 模型提供运行在大数据平台之上的端到端的流水线。例如开发者可以在 Spark 代码中嵌入 TensorFlow 或者 PyTorch 代码,进行分布式的训练和推理。开发者可以在 Spark ML 流水线中使用原生的深度学习支持如 TensorFlow、Keras、PyTorch、BigDL 等。

         o   为自动化的机器学习任务提供了高级 ML 工作流支持,例如自动的 TensorFlow、PyTorch、OpenVINO 等模型的分布式推理 Cluster Serving 以及可扩展的时序数据预测的 AutoML 功能。

         o   内置提供了 Recommendation、Time Series、CV、NLP 等应用常用的模型。

●     bfloat16 是一种业界广泛用于神经网络的数字格式。

●     Resnet50 是一个 50 层的残差网络 (Residual Network),该神经网络广泛用于目标分类等领域。

操作步骤

如果您想在 ECS 上使用 Analytics Zoo 对人工智能应用进行 bfloat16 加速,按照以下步骤在 ECS 上加速人工智能应用。下面步骤以训练 Resnet50 模型的工作负载为例进行说明。

        1.     步骤一:创建高主频 ECS 实例

        2.     步骤二:在 ECS 上准备带有 bfloat16 优化支持的 Analytics Zoo 环境

        3.     步骤三:在 ECS 实例上训练 Resnet50 模型和 bfloat16 的性能提升

步骤一:创建高主频 ECS 实例

完成以下操作,创建一台 ECS 实例。

        1.     前往实例创建页

        2.     创建一台 hfc7 实例。具体操作,请参见使用向导创建实例

        3.     在配置参数时,您需要注意当前场景支持的实例规格族包括 hfc7 和 hfg7。具体规格,请参见高主频型

        4.     在实例列表中,找到创建的实例,单击实例 ID。查看并确认实例规格。

步骤二:在 ECS 上准备带有 bfloat16 优化支持的 Analytics Zoo 环境

Analytics Zoo 提供了预先创建的支持 bfloat16 的 docker image,按照方法一可以轻松在阿里云 ECS 上获取 Analytics Zoo 的 docker image。您也可以按照方法二使用 Analytics Zoo nightly build 来支持 bfloat16。
相关代码说明请参见代码示例:Analytics Zoo 如何利用 bfloat16 加速深度模型训练

       方法一:在 ECS 上获取 Analytics Zoo 预先创建的 docker image 创建。

          i.     连接 ECS 实例。具体步骤,请参见连接 ECS 实例

          ii.    运行以下命令安装并运行 Docker。

                 yum install docker-io -y

                 systemctl start docker

          iii.    运行以下命令获取支持 bfloat16 的 Analytics Zoo docker image。

                 docker pull intelanalytics/analytics-zoo:0.8.1-bigdl_0.10.0-spark_2.4.3-bf16

          iv.    运行以下命令运行 docker container。

                 docker run -itd --name az1 --net=host  --privileged intelanalytics/analytics-zoo:0.8.1-bigdl_0.10.0-spark_2.4.3-bf16

          v.    运行以下命令进入 container。

                 docker exec -it az1 bash

       方法二:用户使用 Analytics Zoo nightly build 来支持 bfloat16 手动创建。

          i.    连接 ECS 实例。具体步骤,请参见连接 ECS 实例

          ii.   运行以下命令下载并解压最新的 Analytics Zoo nightly build pre-build package。

               wget https://oss.sonatype.org/content/repositories/snapshots/com/intel/analytics/zoo/analytics-zoo-bigdl_0.11.1-spark_2.4.3/0.9.0-SNAPSHOT/analytics-zoo-bigdl_0.11.1-spark_2.4.3-0.9.0-20201026.210040-51-dist-all.zip

               unzip analytics-zoo-bigdl_0.11.1-spark_2.4.3-0.9.0-{datetime}-dist-all.zip -d analytics-zoo

          iii.    运行以下命令安装 git。

                  yum -y install git

          iv.    运行以下命令下载 TensorFlow 源代码。

                  git clone https://github.com/Intel-tensorflow/tensorflow.git

                  git checkout v1.15.0up1

          v.    运行以下命令编译 TensorFlow。

                 bazel build --cxxopt=-D_GLIBCXX_USE_CXX11_ABI=0 --copt=-O3 --copt=-Wformat

                 --copt=-Wformat-security --copt=-fstack-protector --copt=-fPIC

                 --copt=-fpic --linkopt=-znoexecstack --linkopt=-zrelro

                 --linkopt=-znow --linkopt=-fstack-protector --config=mkl --define

                 build_with_mkl_dnn_v1_only=true --copt=-DENABLE_INTEL_MKL_BFLOAT16

                 --copt=-march=native

                 //tensorflow/tools/lib_package:libtensorflow_jni.tar.gz

                 //tensorflow/java:libtensorflow.jar

                 //tensorflow/java:libtensorflow-src.jar

                 //tensorflow/tools/lib_package:libtensorflow_proto.zip

          vi.    运行以下命令整理 Analytics Zoo 需要的库文件。

                cd bazel-bin/tensorflow/tools/lib_package

                mkdir linux-x86_64

                tar -xzvf libtensorflow_jni.tar.gz -C linux_x86-64

                rm libtensorflow_framework.so

                rm libtensorflow_framework.so.1

                mv libtensorflow_framework.so.1.15.0 libtensorflow_framework-zoo.so

                cp ../../../../_solib_k8/_U@mkl_Ulinux_S_S_Cmkl_Ulibs_Ulinux___Uexternal_Smkl_Ulinux_Slib/* ./

          vii.    运行以下命令更新 Analytics Zoo Jar。

                 cd ~/analytics-zoo/lib/

                 cp ~/tensorflow/bazel-bin/tensorflow/tools/lib_package/linux-x86_64 ./

                 jar -ufanalytics-zoo-bigdl_0.11.1-spark_2.4.3-0.9.0-SNAPSHOT-jar-with-dependencies.jar linux-x86_64/*

步骤三:在 ECS 实例上训练 Resnet50 模型和 bfloat16 的性能提升

1.   运行以下命令进入 Analytic Zoo docker 容器。

docker exec -it az1 bash

2.   运行以下命令配置 spark,对 /opt/work/spark-2.4.3/conf/spark-defaults.conf 进行修改。

spark.authenticate=false

spark.ui.killEnabled=true

spark.eventLog.enabled=true

spark.history.ui.port=18080

spark.eventLog.dir=file:///var/log/spark/spark-events

spark.history.fs.logDirectory=file:///var/log/spark/spark-events

spark.shuffle.service.port=7337

spark.master=spark://$(hostname):7077

3.   运行以下命令启动 spark master。

cd /opt/work/spark-2.4.3

./sbin/start-master.sh

4.   用 numactl 命令启动 8 个 spark workers,每个 worker 绑定到 12 个 vcpu。在 /opt/work/spark-2.4.3/bin 目录下创建如下脚本。

numactl -C 0-11 ./spark-class org.apache.spark.deploy.worker.Worker spark://$(hostname):7077 &

numactl -C 12-23 ./spark-class org.apache.spark.deploy.worker.Worker spark://$(hostname):7077 &

numactl -C 24-35 ./spark-class org.apache.spark.deploy.worker.Worker spark://$(hostname):7077 &

numactl -C 36-47 ./spark-class org.apache.spark.deploy.worker.Worker spark://$(hostname):7077 &

numactl -C 48-59 ./spark-class org.apache.spark.deploy.worker.Worker spark://$(hostname):7077 &

numactl -C 60-71 ./spark-class org.apache.spark.deploy.worker.Worker spark://$(hostname):7077 &

numactl -C 72-83 ./spark-class org.apache.spark.deploy.worker.Worker spark://$(hostname):7077 &

numactl -C 84-95 ./spark-class org.apache.spark.deploy.worker.Worker spark://$(hostname):7077 &

5.   运行以下命令检查,返回 8 表示已启动了 8 个 Worker。

jps | grep Worker | wc -l

6.   运行以下命令从 github 上下载 resnet50 示例代码。

git clone https://github.com/yangw1234/models-1.git

git checkout branch-1.6.1-zoo

7.   在 models-1/models/image_recognition/tensorflow/resnet50v1_5/training/mlperf_resnet 目录下运行 run.sh 脚本,用--use_bfloat16 选项来开启 bfloat16 训练,不加此选项则默认为 FP32 训练。

# Register the model as a source root

export PYTHONPATH="$(pwd):${PYTHONPATH}"

export KMP_BLOCKTIME=0

# 8 instances

export OMP_NUM_THREADS=6

export KMP_AFFINITY=granularity=fine,compact,1,0

export KMP_SETTINGS=1

export ANALYTICS_ZOO_HOME=/opt/work/analytics-zoo/dist

export SPARK_HOME=/opt/work/spark-2.4.3

bash $ANALYTICS_ZOO_HOME/bin/spark-submit-python-with-zoo.sh --master

spark://$(hostname):7077 \

--executor-cores 1 --total-executor-cores 8 --driver-memory 20g --executor-memory 18g \

--conf spark.network.timeout=10000000 --conf spark.executor.heartbeatInterval=100000 \

imagenet_main.py 1 --model_dir ./logs --batch_size 128 --version 1 \

--resnet_size 50 --train_epochs 90 --data_dir /opt/ILSVRC2012/ --use_bfloat16

本次训练测试结果如下所示。

Resnet50 模型训练

FP32

BF16

BF16 相对 FP32 的性能提升

Throughput (images/sec)

119.636

212.315

1.775

 

代码示例:Analytics Zoo 如何利用 bfloat16 加速深度模型训练

下面的代码用于说明 Analytics Zoo 如何利用 bfloat16 来加速深度学习模型的训练(例如 Resnet50 等)。在 Analytics Zoo 的 docker image 中已经包含,您不需要任何操作,仅作示例参考。

1.     通过以下代码将输入图片转换成 bfloat16 格式。

if use_bfloat16 == True:

dtype = tf.bfloat16

features = tf.cast(features, dtype)

2.     通过以下代码编写 custom_dtype_getter。

DEFAULT_DTYPE = tf.float32

CASTABLE_TYPES = (tf.float16,tf.bfloat16)

def _custom_dtype_getter(getter, name, shape=None, dtype=DEFAULT_DTYPE,    

      *args, **kwargs):

    if dtype in CASTABLE_TYPES:

      var = getter(name, shape, tf.float32, *args, **kwargs)

      return tf.cast(var, dtype=dtype, name=name + '_cast')

    else:

      return getter(name, shape, dtype, *args, **kwargs)

3.     通过以下代码创建 variable_scope,并在该 scope 下构建模型。

def _model_variable_scope():

    return tf.compat.v1.variable_scope('resnet_model',

                    custom_getter=_custom_dtype_getter)

with _model_variable_scope():

    logits = _resnet_50_model(features)

4.     通过以下代码将 logits 装换成 float32 计算 loss 以保证数值稳定性(numerical stability)。

logits = tf.cast(logits, tf.float32)

5.     使用 Analytics TFPark 进行分布式训练。具体操作,请参见 Analytics Zoo 分布式 TensorFlow