Tensorflow 调试方式主要有以下几种
- Timeline初步分析性能瓶颈
- Tensorboard,Graphviz等对图信息进行可视化
- 环境变量配置导出图信息
- 使用bazel编译选项输出内部信息
- 使用GDB进行细节问题定位
Timeline
可以直观的显示一个Step内Op粒度的执行时间, 为性能优化提供参考。Chrome中键入 chrome://tracing/ ,即可通过Load按钮加载time.json, 使之图形化显示
python tf_cnn_benchmarks.py --trace_file="time.json" --save_summaries_steps=10 --summary_verbosity=1 --train_dir "./tmp" --num_gpus=1 --batch_size=1 --model=alexnet
mpirun --allow-run-as-root -np 4 -H 10.54.32.198:4 python tf_cnn_benchmarks.py --xla="True" --trace_file="time.json" --num_gpus=1 --batch_size=32 --model=alexnet --variable_update=horovod
Timeline看起来很美好,但有几个问题一定要注意:
- 基本单位是Op。 Op内逻辑再简单,也一定会体现,Op内逻辑再复杂,也不会对其拆分。
- 是谁的执行流。Timeline体现的是CPU端启动Op的执行流,,上图中的GPU端的执行流看起来有多条,实际上到底有没有并行呢?这不一定,这张Timeline图本质只是对time.json进行了可视化,这里看到的GPU任务就对应time.json的
"name": "/job:localhost/replica:0/task:0/device:GPU:0 Compute"
而GPU的执行流编号就对应"tid": 14,
所以,问题就变成了:这里的“tid”能否表示实际在GPU中的执行流?我理解是不能的,在使用GPU做backend的场景,HorovodAllreduce底层调用NcclAllReduce,而NcclAllReduce本质是DMA引擎在做实际工作,而以DMA的工作方式,怎么会占用GPU的Compute流呢,所以,这里应该比较准确的理解应该是,TODO:在某一时刻,不断开启新的执行流去执行一个GPU Op,至于这些执行流是否真的在GPU内并行,这里并不能表达,需要使用GPU专属的工具。 - 并行的欺骗性,本质上,这种误导是由于1和2导致的Timeline局限性,倒也称不上是错误。上图中使用Horovod进行分布式训练时,由于多个AllreduceOp并无相关性,也分属不同的执行流,看起来并行度很高,其实在其内部实现中,一方面Horovod会做融合,另一方面每个HorovodAllreduceOp只有一个后台线程真正的去做网络通信,最后,网络IO的能力上限取决于网卡,当网卡达到瓶颈时,更多的并行HorovodAllreduceOp是没有意义的。
- 和Step强相关,取一个Timeline的时候,通常会指定运行到某个Step来保存,这里的问题是,不同的Step可能执行的Timeline差异巨大,典型的问题就是开启XLA时,部分子图只会在Step1执行,同时,Step1进行的XlaCompile也会大大延长单Step时间,所以在测试的时候,使用的Step也是要小心设置的。
Tensorboard
Tensorboard用于传统TF Graph调试是比较容易理解的,这里讨论如何使用Tensorboard进行XLA的可视化。XLA可以将优化的各个阶段的子图导出为pbtxt或pb|dot,html等格式,如果是pbtxt,可以直接点击Tensorboard左侧Choose File 按钮上传。
python tf_cnn_benchmarks.py --trace_file="time.json" --xla="True" --save_summaries_steps=10 --summary_verbosity=1 --train_dir "./tmp" --num_gpus=1 --batch_size=1 --model=alexnet
执行”./bazel-bin/tensorboard/tensorboard –logdir=”./logs” –port=9000″,浏览器输入”http://localhost:9000/“,点击上传mark_for_compilation_annotated_1.pbtxt即可看到子图:
Dot + Graphvis
XLA的HLO PASS可以生成pb, html,dot等格式,这里的pb用import_pb_to_tensorboard或者自己写的脚本都没能成功转化成pbtxt,还没办法使用的Tensorboard查看,但相应的dot格式,显然可以使用Graphviz进行可视化。但鉴于graphviz的全量计算的方式,对于特别大神经网络,dot工具本身就会成为瓶颈。
foo $ dot -Tsvg -o module_0002.after_optimizations.svg module_0002.after_optimizations.dot