昇腾社区首页
中文
注册

混合精度训练

概述

混合精度训练方法是通过混合使用float16和float32数据类型来加速深度神经网络训练的过程,并减少内存使用和存取,从而可以训练更大的神经网络。同时又能基本保持使用float32训练所能达到的网络精度。当前昇腾AI处理器支持如下几种训练精度模式,用户可以在训练脚本中设置。

  • allow_fp32_to_fp16:优先保持原图精度,当算子不支持float32数据类型时,直接降低精度到float16。当前不支持float32类型的算子都是卷积类和矩阵类算子,例如Conv2D、DepthwiseConv2D等。
  • force_fp16:当算子既支持float16又支持float32数据类型时,强制选择float16。
  • force_fp32:算子既支持float16又支持float32数据类型时,强制选择float32。
  • must_keep_origin_dtype:保持原图精度。此种方式下,如果整网中有Conv2D算子,由于该算子仅支持float16类型,在原图输入是float32类型的情况下,训练会报错中止。
  • allow_mix_precision:自动混合精度。可以针对全网中float32数据类型的算子,按照内置的优化策略,自动将部分float32的算子降低精度到float16,从而在精度损失很小的情况下提升系统性能并减少内存使用。但需要注意的是:当前昇腾AI处理器仅支持float32到float16的精度调整。如果用户原始脚本中已经实现了手动混合精度功能,比如显式调用cast算子转换计算精度,则无需开启昇腾AI处理器的自动混合精度功能。

昇腾AI处理器进行混合精度训练时,推荐Loss Scale,从而补偿降低精度带来的精度损失。

Estimator模式下设置精度模式

Estimator模式下,通过NPURunConfig中的precision_mode参数设置精度模式:
from npu_bridge.npu_init import *

npu_config=NPURunConfig(
  model_dir=FLAGS.model_dir,
  save_checkpoints_steps=FLAGS.save_checkpoints_steps,
  session_config=tf.ConfigProto(allow_soft_placement=True,log_device_placement=False),
  precision_mode="allow_mix_precision"
  )

sess.run模式下设置精度模式

sess.run模式下,通过session配置项precision_mode参数设置精度模式:
import tensorflow as tf
from npu_bridge.npu_init import *

config = tf.ConfigProto()

custom_op =  config.graph_options.rewrite_options.custom_optimizers.add()
custom_op.name =  "NpuOptimizer" 
custom_op.parameter_map["use_off_line"].b = True
custom_op.parameter_map["precision_mode"].s = tf.compat.as_bytes("allow_mix_precision")
config.graph_options.rewrite_options.remapping = RewriterConfig.OFF
config.graph_options.rewrite_options.memory_optimization = RewriterConfig.OFF

with tf.Session(config=config) as sess:
  print(sess.run(cost))

修改混合精度黑白灰名单

allow_mix_precision混合精度模式下,针对全网中float32数据类型的算子,按照内置的优化策略,自动将部分float32的算子降低精度到float16,从而在精度损失很小的情况下提升系统性能并减少内存使用。

内置优化策略在“OPP安装目录/opp/op_impl/built-in/ai_core/tbe/config/ascend910/aic-ascend910-ops-info.json”,例如:

"Conv2D":{
    "precision_reduce":{
        "flag":"true"
},
  • true:(白名单)允许将当前float32类型的算子,降低精度到float16。
  • false:(黑名单)不允许将当前float32类型的算子,降低精度到float16。
  • 不配置:(灰名单)当前算子的混合精度处理机制和前一个算子保持一致,即如果前一个算子支持降精度处理,当前算子也支持降精度;如果前一个算子不允许降精度,当前算子也不支持降精度。

用户可以在内置优化策略基础上进行调整,自行指定哪些算子允许降精度,哪些算子不允许降精度。下面介绍两种方法:

  • (推荐)方法一,通过modify_mixlist指定需要修改的混合精度黑白灰算子名单。
    from npu_bridge.npu_init import *
    # Estimator模式修改方法
    npu_config=NPURunConfig(
      model_dir=FLAGS.model_dir,
      save_checkpoints_steps=FLAGS.save_checkpoints_steps,
      session_config=tf.ConfigProto(allow_soft_placement=True,log_device_placement=False),
      precision_mode="allow_mix_precision",
      modify_mixlist="/home/test/ops_info.json"
      )
    # sess.run模式修改方法
    config = tf.ConfigProto()
    custom_op =  config.graph_options.rewrite_options.custom_optimizers.add()
    custom_op.name =  "NpuOptimizer" 
    custom_op.parameter_map["use_off_line"].b = True
    custom_op.parameter_map["precision_mode"].s = tf.compat.as_bytes("allow_mix_precision")
    custom_op.parameter_map["modify_mixlist"].s = tf.compat.as_bytes("/home/test/ops_info.json")
    config.graph_options.rewrite_options.remapping = RewriterConfig.OFF
    config.graph_options.rewrite_options.memory_optimization = RewriterConfig.OFF
    with tf.Session(config=config) as sess:
      print(sess.run(cost))

    ops_info.json中可以指定算子类型,多个算子使用英文逗号分隔,样例如下:

    {
      "black-list": {                  // 黑名单
         "to-remove": [                // 黑名单算子转换为灰名单算子
         "Yolo"
         ],
         "to-add": [                   // 白名单或灰名单算子转换为黑名单算子
         "Matmul",
         "Cast"
         ]
      },
      "white-list": {                  // 白名单
         "to-remove": [                // 白名单算子转换为灰名单算子 
         "Conv2D"
         ],
         "to-add": [                   // 黑名单或灰名单算子转换为白名单算子
         "Bias"
         ]
      }
    }

    假设算子A默认在白名单中,如果您希望将该算子配置为黑名单算子,可以参考如下方法:

    1. (正确示例)用户将该算子添加到黑名单中:
      {
        "black-list": { 
           "to-add": ["A"]
        }
      }

      则系统会将该算子从白名单中删除,并添加到黑名单中,最终该算子在黑名单中。

    2. (正确示例)用户将该算子从白名单中删除,同时添加到黑名单中:
      {
        "black-list": {
           "to-add": ["A"]
        },
        "white-list": {
           "to-remove": ["A"]
        }
      }

      则系统会将该该算子从白名单中删除,并添加到黑名单中,最终该算子在黑名单中。

    3. (错误示例)用户将该算子从白名单中删除,此时算子最终是在灰名单中,而不是黑名单。
      {
        "white-list": {
           "to-remove": ["A"]
        }
      }

      此时,系统会将该算子从白名单中删除,然后添加到灰名单中,最终该算子在灰名单中。

      对于只从黑/白名单中删除,而不添加到白/黑名单的情况,系统会将该算子添加到灰名单中。

  • 方法二,直接修改算子信息库。

    对内置算子信息库进行修改,可能会对其他网络造成影响,请谨慎修改。

    1. 切换到“OPP安装目录/opp/op_impl/built-in/ai_core/tbe/config/ascend910”目录下。
    2. 对aic-ascend910-ops-info.json文件增加写权限。
      chmod u+w aic-ascend910-ops-info.json

      当前目录下的所有json文件都会被加载到算子信息库中,如果您需要备份原来的json文件,建议备份到其他目录下。

    3. 修改或增加算子信息库aic-ascend910-ops-info.json文件中对应算子的precision_reduce字段。