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

背景信息

  • 阿里云第七代高主频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提供了以下特性:
    • 为基于TensorFlow、PyTorch、OpenVINO等的AI模型提供运行在大数据平台之上的端到端的流水线。例如开发者可以在Spark代码中嵌入TensorFlow或者PyTorch代码,进行分布式的训练和推理。开发者可以在Spark ML流水线中使用原生的深度学习支持如TensorFlow、Keras、PyTorch、BigDL等。
    • 为自动化的机器学习任务提供了高级ML工作流支持,例如自动的TensorFlow、PyTorch、OpenVINO等模型的分布式推理Cluster Serving以及可扩展的时序数据预测的AutoML功能。
    • 内置提供了Recommendation、Time Series、CV、NLP等应用常用的模型。
    ZOO
  • bfloat16是一种业界广泛用于神经网络的数字格式。
  • Resnet50是一个50层的残差网络(Residual Network),该神经网络广泛用于目标分类等领域。

操作步骤

如果您想在ECS上使用Analytics Zoo对人工智能应用进行bfloat16加速,按照以下步骤在ECS上加速人工智能应用:
  1. 步骤一:创建高主频ECS实例
  2. 步骤二:在ECS上准备带有bfloat16优化支持的Analytics Zoo环境
  3. 步骤三:在ECS实例上训练Resnet50模型和bfloat16的性能提升

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

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

  1. 前往实例创建页
  2. 创建一台hfc7实例。具体操作,请参见使用向导创建实例
    在配置参数时,您需要注意当前场景支持的实例规格族包括hfc7和hfg7。具体规格,请参见高主频型
  3. 在实例列表中,找到创建的实例,单击实例ID。查看并确认实例规格。
    确认ECS

步骤二:在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创建。
    1. 连接ECS实例。具体步骤,请参见连接ECS实例
    2. 运行以下命令安装并运行Docker。
      yum install docker-io -y
      systemctl start docker
    3. 运行以下命令获取支持bfloat16的Analytics Zoo docker image。
      docker pull intelanalytics/analytics-zoo:0.8.1-bigdl_0.10.0-spark_2.4.3-bf16
    4. 运行以下命令运行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
    5. 运行以下命令进入container。
      docker exec -it az1 bash
  • 方法二:用户使用Analytics Zoo nightly build来支持bfloat16手动创建。
    1. 连接ECS实例。具体步骤,请参见连接ECS实例
    2. 运行以下命令下载并解压最新的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
    3. 运行以下命令安装git。
      yum -y install git
    4. 运行以下命令下载TensorFlow源代码。
      git clone https://github.com/Intel-tensorflow/tensorflow.git
      git checkout v1.15.0up1
    5. 运行以下命令编译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
    6. 运行以下命令整理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/* ./
    7. 运行以下命令更新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