本文分享自華為云社區(qū)《TensorFlow模型訓(xùn)練常見(jiàn)案例》,作者: 昇騰CANN。
基于TensorFlow的Python API開(kāi)發(fā)的訓(xùn)練腳本默認(rèn)運(yùn)行在CPU/GPU/TPU上,為了使這些腳本能夠利用昇騰AI處理器的強(qiáng)大算力,需要將其遷移到昇騰平臺(tái)。
本期分享幾個(gè)TensorFlow網(wǎng)絡(luò)遷移到昇騰平臺(tái)后執(zhí)行失敗或者執(zhí)行性能差的典型案例,并給出原因分析及解決方法。
01 數(shù)據(jù)預(yù)處理中存在資源類算子,導(dǎo)致訓(xùn)練異常
問(wèn)題現(xiàn)象
TensorFlow網(wǎng)絡(luò)執(zhí)行時(shí),報(bào)如下錯(cuò)誤:
[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 ,數(shù)據(jù)預(yù)處理中存在資源類算子LookupTableFindV2,兩個(gè)算子需要配對(duì)使用。
昇騰AI處理器默認(rèn)采用計(jì)算全下沉模式,即所有的計(jì)算類算子(包括初始化圖中的資源類算子)全部在Device側(cè)執(zhí)行,數(shù)據(jù)預(yù)處理仍在Host執(zhí)行。這樣數(shù)據(jù)預(yù)處理中的LookupTableFindV2算子與初始化圖中的HaskTableV2算子未在同一設(shè)備執(zhí)行,導(dǎo)致網(wǎng)絡(luò)運(yùn)行出錯(cuò)。
解決方案
需要修改訓(xùn)練腳本,使能混合計(jì)算能力,將資源類算子的初始化圖也留在Host側(cè)執(zhí)行,訓(xùn)練腳本修改方法如下:
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(...)
其中配置參數(shù)“mix_compile_mode”是混合計(jì)算開(kāi)啟開(kāi)關(guān),當(dāng)此開(kāi)關(guān)配置為“True”后,會(huì)將需要成對(duì)使用的資源類算子留在前端框架在線執(zhí)行。
補(bǔ)充說(shuō)明:當(dāng)用戶的預(yù)處理腳本中存在需要成對(duì)使用的tf.contrib.lookup下Table類的API時(shí),需要參考此方法使能混合計(jì)算功能,將初始化圖中的對(duì)應(yīng)算子留在Host側(cè)執(zhí)行。
02 數(shù)據(jù)預(yù)處理中存在tf.Variable,導(dǎo)致訓(xùn)練異常
問(wèn)題現(xiàn)象
TensorFlow網(wǎng)絡(luò)執(zhí)行時(shí),報(bào)如下錯(cuò)誤:
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.
原因分析
此問(wèn)題是由于數(shù)據(jù)預(yù)處理腳本中存在tf.Variable變量。訓(xùn)練腳本在昇騰平臺(tái)運(yùn)行時(shí),tf.Variable變量在Host側(cè)執(zhí)行,而tf.Variable變量的初始化在Device側(cè)執(zhí)行,變量執(zhí)行和變量初始化不在同一設(shè)備執(zhí)行,導(dǎo)致訓(xùn)練異常。
使用了tf.Variable的訓(xùn)練腳本代碼示例如下:
batch_size = tf.Variable( tf.placeholder(tf.int64, [], 'batch_size'), trainable= False, collections=[] ) train_dataset = train_dataset.batch(batch_size, drop_remainder=True)
解決方案
需要修改訓(xùn)練腳本,將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 動(dòng)態(tài)shape網(wǎng)絡(luò)執(zhí)行時(shí)報(bào)v1控制流算子不支持的錯(cuò)誤
問(wèn)題現(xiàn)象
TensorFlow 1.15版本的動(dòng)態(tài)shape網(wǎng)絡(luò)執(zhí)行時(shí),報(bào)如下錯(cuò)誤:
node node_name(node_type) is v1 control operator, which is not supported, please convert to v2 control operator
原因分析
由于當(dāng)前TensorFlow網(wǎng)絡(luò)為動(dòng)態(tài)shape網(wǎng)絡(luò),且存在V1版本的控制流算子。在昇騰AI處理器執(zhí)行TensorFlow動(dòng)態(tài)shape網(wǎng)絡(luò)當(dāng)前不支持V1版本的控制流算子,所以會(huì)造成網(wǎng)絡(luò)運(yùn)行失敗。
解決方案
將網(wǎng)絡(luò)中的TensorFlow V1版本的控制流算子轉(zhuǎn)換為V2版本,即可解決此問(wèn)題。
方法一:通過(guò)設(shè)置如下環(huán)境變量將TensorFlow V1版本的控制流算子轉(zhuǎn)換為V2版本。
export ENABLE_FORCE_V2_CONTROL=1
方法二:修改網(wǎng)絡(luò)腳本,在import tensorflow as tf后增加如下兩條指令,將TensorFlow V1版本的控制流算子轉(zhuǎn)換為V2版本。
tf.enable_control_flow_v2()
tf.enable_resource_variables()
04 網(wǎng)絡(luò)調(diào)測(cè)時(shí)ReduceSum算子執(zhí)行性能差
問(wèn)題現(xiàn)象
網(wǎng)絡(luò)調(diào)測(cè)時(shí),網(wǎng)絡(luò)整體性能較慢。通過(guò)Profiling工具獲取網(wǎng)絡(luò)的Profiling數(shù)據(jù),并進(jìn)行算子的性能數(shù)據(jù)分析,發(fā)現(xiàn)ReduceSum算子的性能很差。
查看Profiling性能數(shù)據(jù)中ReduceSum算子的詳細(xì)信息,關(guān)鍵字段如下表藍(lán)色字體所示:
op_type |
block_dim |
input_shape |
input_data_type |
input_formats |
ReduceSum |
1 |
1,256,256,3 |
DT_FLOAT16 |
NHWC |
ReduceSum算子的輸入數(shù)據(jù)類型(input_data_type)為“DT_FLOAT16”,block_dim字段的值為“1”,說(shuō)明該算子未開(kāi)啟多核并行計(jì)算。
原因分析
針對(duì)昇騰AI處理器的ReduceSum算子,若輸入數(shù)據(jù)類型為float16,由于硬件限制,某些場(chǎng)景下會(huì)無(wú)法開(kāi)啟多核計(jì)算。
解決方案
ReduceSum算子輸入數(shù)據(jù)是float16的情況可能有如下兩種場(chǎng)景:
場(chǎng)景一:
網(wǎng)絡(luò)調(diào)測(cè)時(shí)未開(kāi)啟混合精度,ReduceSum算子的輸入數(shù)據(jù)本身就是float16類型,此種情況下,若ReduceSum算子的性能較差,可嘗試在ReduceSum算子前插入一個(gè)Cast算子,將算子的輸入數(shù)據(jù)類型從float16轉(zhuǎn)換為float32。
ReduceSum算子在輸入類型為float32的場(chǎng)景下,會(huì)使能多核并發(fā)計(jì)算,從而達(dá)到提升該算子性能的效果。
場(chǎng)景二:
網(wǎng)絡(luò)調(diào)測(cè)時(shí)開(kāi)啟了混合精度,將ReduceSum算子的輸入數(shù)據(jù)類型從float32轉(zhuǎn)換成了float16,此種情況下,可將ReduceSum算子加入混合精度黑名單,這樣網(wǎng)絡(luò)調(diào)測(cè)時(shí)ReduceSum算子就不會(huì)被轉(zhuǎn)換成float16類型,從而避免該算子性能的劣化。
將ReduceSum算子加入混合精度黑名單的方法如下:
1) 修改網(wǎng)絡(luò)腳本,通過(guò)modify_mixlist參數(shù)指定需要修改的混合精度算子黑名單,修改示例如下:
# 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文件中進(jìn)行算子黑名單的配置,配置示例如下:
{ "black-list": { "to-add": ["ReduceSumD"] } }
補(bǔ)充說(shuō)明:僅在ReduceSum算子性能較差時(shí),且符合本案例中的問(wèn)題現(xiàn)象時(shí),可嘗試使用此方法進(jìn)行性能提升。
05 更多介紹
[1]昇騰文檔中心:https://www.hiascend.com/zh/document
[2]昇騰社區(qū)在線課程:https://www.hiascend.com/zh/edu/courses
[3]昇騰論壇:https://www.hiascend.com/forum
?文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-745511.html
點(diǎn)擊關(guān)注,第一時(shí)間了解華為云新鮮技術(shù)~文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-745511.html
到了這里,關(guān)于昇騰遷移丨4個(gè)TensorFlow模型訓(xùn)練案例解讀的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!