排除以上问题后,在训练网络精度仍未达预期时,通过采集训练过程中各算子的运算结果(即Dump数据),然后和业界标准算子(如TensorFlow)运算结果进行数据偏差对比,快速定位到具体算子的精度问题。主要过程为:
利用TensorFlow官方提供的debug工具tfdbg,在CPU/GPU训练脚本中添加tf_debug代码,并使用precision_tool中提供的辅助命令行工具生成npy文件。
以下操作在GPU/CPU训练环境执行。
pip3 install gnureadline pexpect
# 引用precision_tool/tf_config.py import precision_tool.tf_config as npu_tf_config # 如果使用的是Estimator,EstimatorSpec加入training_hooks # 等价于:estim_specs = tf_debug.DumpingDebugHook("precision_data/tf/tf_debug") estim_specs = tf.estimator.EstimatorSpec(training_hooks=[npu_tf_config.estimator_dump()]) # 如果使用的session.run,以下代码为sess加上了tf_debug的wrapper # 等价于:sess = tf_debug.DumpingDebugWrapperSession(sess, "precision_data/tf/tf_debug") sess = npu_tf_config.sess_dump(sess=sess)
根据代码中run的次数,会在precision_data/tf/tf_debug/目录生成1~N个离线tf_debug的dump目录。
python3 precision_tool/cli.py tf_dump
如果需要重新生成dump数据,可执行以下命令:
rm -rf precision_data/tf/dump/* && python3 precision_tool/cli.py tf_dump
以下操作在NPU训练环境执行。Dump数据前,需要注意的是:
一般情况下,dump首个step的数据用作后续比对分析即可,为了避免随机权重导致比对不准确的问题,可以在训练开始前保存ckpt,并在训练时加载。如果确定是某个step的精度问题,则建议加载最靠近异常步的ckpt文件。
# dump特定step的数据,一般对比分析dump首层即可,即保持默认值,如需指定特定step可以修改,例如 '0|5|10' TF_DUMP_STEP = '0'
# 引用precision_tool/tf_config.py import precision_tool.tf_config as npu_tf_config # 1. 手工迁移网络 # 1.1 Estimator方式 dump_config=npu_tf_config.estimator_dump_config(action='dump') npu_config = NPURunConfig(dump_config=dump_config) # 1.2 Session run方式 config = npu_tf_config.session_dump_config(config, action='dump') sess = tf.Session(config) # 2. 自动迁移网络 # 若脚本中未配置custom_op,则在脚本中新增如下粗体语句 session_config = npu_tf_config.session_dump_config(session_config, action='dump') # 若脚本中已配置custom_op,如下所示,则在脚本中新增下列粗体语句更新custom_op custom_op = session_config.graph_options.rewrite_options.custom_optimizers.add() custom_op.name = 'NpuOptimizer' custom_op.parameter_map["precision_mode"].s = tf.compat.as_bytes("allow_mix_precision") custom_op = npu_tf_config.update_custom_op(custom_op, action='dump') # 2.1 Estimator方式 run_config = tf.estimator.RunConfig(session_config=session_config,...) # 2.2 Session run方式 with tf.Session(config=npu_config_proto(session_config)): .... # 2.3 tf.keras方式 npu_keras_sess = set_keras_session_npu_config(config=session_config)
# 精度数据的根目录,ModelArts场景下需修改成ModelArts容器路径,训练结束后该路径下的数据会自动回传至OBS ROOT_DIR = '/home/ma-user/modelarts/outputs/train_url_0/'
精度数据分析依赖CANN Toolkit软件包中的atc工具和msaccucmp.py工具,以下操作需要在CANN开发环境,即Toolkit安装环境进行。
├── precision_tool │ ├── cli.py │ ├── ... ├── precision_data │ ├── npu │ │ ├── debug_0 // 存放npu dump数据 │ ├── tf │ │ ├── dump // 存放标杆dump数据
# graphviz为可选依赖,只有当需要绘制算子子图时才需要安装 pip3 install rich graphviz # ubuntu/Debian sudo apt-get install graphviz # fedora/CentOS sudo yum install graphviz
# 依赖Toolkit包中的atc和msaccucmp.py工具,配置为Toolkit包安装目录 # 默认Toolkit包安装在/usr/local/Ascend,可以不用修改,指定目录安装则需要修改 CMD_ROOT_PATH = '/usr/local/Ascend'
python3 ./precision_tool/cli.py
进入交互命令行界面:
PrecisionTool >
如需退出,可执行ctrl + c。
PrecisionTool > ac -c
根据数据量大小,比对过程需要时间不同。
对比结果会以csv的格式存放在precision_data/temp/vector_compare目录中:
您可以直接打开csv文件进行分析,具体请参考整网精度比对结果文件说明。
vcs命令默认筛选余弦相似度小于0.98的结果,您也可以通过-c参数自定义阈值:
从上图的比对结果可以看到,算子的输入基本一致,但第一个输出与标杆存在明显差异(余弦相似度为0.806927,小于0.98),说明该算子可能存在精度问题。
当出现多个算子精度问题时,会出现N个异常算子信息,默认按照算子执行顺序排序,由于后面算子精度问题可能是因为前一个算子精度问题导致,建议用户优先分析第一个异常算子。
ni命令可以根据传入的算子名称,得到如下关键信息:
另外,PassName表示该算子为融合算子,对应值表示融合规则名称,OriginOp为融合前的算子,表明是由于算子融合导致精度问题。正常情况下,融合问题应该在融合异常检测阶段解决。
整网数据比对提供了一个全网Dump数据与TF标杆数据的逐层累计比对报表,由于整网数据由于硬件差异本身是存在一定给误差的,且误差会随着层数增多而累计,即便精度正常的网络数值上也会存在细微误差,一般采用余弦相似度做初步的可疑算子筛选(注意:余弦相似度较高也不一定说明没有问题,但较低一般代表可能存在问题),精度对比结果可以给出一个大致的分析方向。