昇騰遷移丨4個TensorFlow模型訓練案例解讀

華為雲開發者聯盟發表於2023-11-06

本文分享自華為雲社群《TensorFlow模型訓練常見案例》,作者: 昇騰CANN。

基於TensorFlow的Python API開發的訓練指令碼預設執行在CPU/GPU/TPU上,為了使這些指令碼能夠利用昇騰AI處理器的強大算力,需要將其遷移到昇騰平臺。

本期分享幾個TensorFlow網路遷移到昇騰平臺後執行失敗或者執行效能差的典型案例,並給出原因分析及解決方法。

01 資料預處理中存在資源類運算元,導致訓練異常

問題現象

TensorFlow網路執行時,報如下錯誤:

[2021-03-19 13:50:24.895266: W tensorflow/core/framework/op_kernel.cc:1651] OP_REQUIRES failed at lookup_table_op.cc:809 : Failed precondition: Table not initialized.

[2021-03-19 13:50:24.895283: W tensorflow/core/framework/op_kernel.cc:1651] OP_REQUIRES failed at lookup_table_op.cc:809 : Failed precondition: Table not initialized.

原因分析

初始化圖中存在資源類運算元HaskTableV2 ,資料預處理中存在資源類運算元LookupTableFindV2,兩個運算元需要配對使用。

昇騰AI處理器預設採用計算全下沉模式,即所有的計算類運算元(包括初始化圖中的資源類運算元)全部在Device側執行,資料預處理仍在Host執行。這樣資料預處理中的LookupTableFindV2運算元與初始化圖中的HaskTableV2運算元未在同一裝置執行,導致網路執行出錯。

解決方案

需要修改訓練指令碼,使能混合計算能力,將資源類運算元的初始化圖也留在Host側執行,訓練指令碼修改方法如下:

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["mix_compile_mode"].b = True

config.graph_options.rewrite_options.remapping = RewriterConfig.OFF

config.graph_options.rewrite_options.memory_optimization = RewriterConfig.OFF

with tf.Session(config=config) as sess:

sess.run(...)

其中配置引數“mix_compile_mode”是混合計算開啟開關,當此開關配置為“True”後,會將需要成對使用的資源類運算元留在前端框架線上執行。

補充說明:當使用者的預處理指令碼中存在需要成對使用的tf.contrib.lookup下Table類的API時,需要參考此方法使能混合計算功能,將初始化圖中的對應運算元留在Host側執行。

02 資料預處理中存在tf.Variable,導致訓練異常

問題現象

TensorFlow網路執行時,報如下錯誤:

tensorflow.python.framework.errors_impl.FailedPreconditionError: Error while reading resource variable inference/embed_continuous from Container: localhost. This could mean that the variable was uninitialized. Not found: Resource localhost/inference/embed_continuous/N10tensorflow3VarE does not exist.

原因分析

此問題是由於資料預處理指令碼中存在tf.Variable變數。訓練指令碼在昇騰平臺執行時,tf.Variable變數在Host側執行,而tf.Variable變數的初始化在Device側執行,變數執行和變數初始化不在同一裝置執行,導致訓練異常。

使用了tf.Variable的訓練指令碼程式碼示例如下:

batch_size = tf.Variable(

tf.placeholder(tf.int64, [], 'batch_size'),

trainable= False, collections=[]

)

train_dataset = train_dataset.batch(batch_size, drop_remainder=True)

解決方案

需要修改訓練指令碼,將tf.Variable修改成常量,修改示例如下:

batch_size = 64 train_dataset = train_dataset.batch(batch_size, drop_remainder=True)

batch_size = 64

train_dataset = train_dataset.batch(batch_size, drop_remainder=True)

03 動態shape網路執行時報v1控制流運算元不支援的錯誤

問題現象

TensorFlow 1.15版本的動態shape網路執行時,報如下錯誤:

node node_name(node_type) is v1 control operator, which is not supported, please convert to v2 control operator

原因分析

由於當前TensorFlow網路為動態shape網路,且存在V1版本的控制流運算元。在昇騰AI處理器執行TensorFlow動態shape網路當前不支援V1版本的控制流運算元,所以會造成網路執行失敗。

解決方案

將網路中的TensorFlow V1版本的控制流運算元轉換為V2版本,即可解決此問題。

方法一:透過設定如下環境變數將TensorFlow V1版本的控制流運算元轉換為V2版本。

export ENABLE_FORCE_V2_CONTROL=1

方法二:修改網路指令碼,在import tensorflow as tf後增加如下兩條指令,將TensorFlow V1版本的控制流運算元轉換為V2版本。

tf.enable_control_flow_v2()

tf.enable_resource_variables()

04 網路調測時ReduceSum運算元執行效能差

問題現象

網路調測時,網路整體效能較慢。透過Profiling工具獲取網路的Profiling資料,並進行運算元的效能資料分析,發現ReduceSum運算元的效能很差。

檢視Profiling效能資料中ReduceSum運算元的詳細資訊,關鍵欄位如下表藍色字型所示:

op_type

block_dim

input_shape

input_data_type

input_formats

ReduceSum

1

1,256,256,3

DT_FLOAT16

NHWC

ReduceSum運算元的輸入資料型別(input_data_type)為“DT_FLOAT16”,block_dim欄位的值為“1”,說明該運算元未開啟多核平行計算。

原因分析

針對昇騰AI處理器的ReduceSum運算元,若輸入資料型別為float16,由於硬體限制,某些場景下會無法開啟多核計算。

解決方案

ReduceSum運算元輸入資料是float16的情況可能有如下兩種場景:

場景一:

網路調測時未開啟混合精度,ReduceSum運算元的輸入資料本身就是float16型別,此種情況下,若ReduceSum運算元的效能較差,可嘗試在ReduceSum運算元前插入一個Cast運算元,將運算元的輸入資料型別從float16轉換為float32。

ReduceSum運算元在輸入型別為float32的場景下,會使能多核併發計算,從而達到提升該運算元效能的效果。

場景二:

網路調測時開啟了混合精度,將ReduceSum運算元的輸入資料型別從float32轉換成了float16,此種情況下,可將ReduceSum運算元加入混合精度黑名單,這樣網路調測時ReduceSum運算元就不會被轉換成float16型別,從而避免該運算元效能的劣化。

將ReduceSum運算元加入混合精度黑名單的方法如下:

1) 修改網路指令碼,透過modify_mixlist引數指定需要修改的混合精度運算元黑名單,修改示例如下:

# Estimator模式修改方法

npu_config=NPURunConfig(

...

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")

2) 在ops_info.json檔案中進行運算元黑名單的配置,配置示例如下:

{

"black-list": {

"to-add": ["ReduceSumD"]

}

}

補充說明:僅在ReduceSum運算元效能較差時,且符合本案例中的問題現象時,可嘗試使用此方法進行效能提升。

05 更多介紹

[1]昇騰檔案中心:https://www.hiascend.com/zh/document

[2]昇騰社群線上課程:https://www.hiascend.com/zh/edu/courses

[3]昇騰論壇:https://www.hiascend.com/forum

 

點選關注,第一時間瞭解華為雲新鮮技術~

相關文章