Tensorflow 调试方法

Timeline

可以直观的显示一个Step内Op粒度执行之间, 包括使用的GPU stream等信息, 为性能优化提供参考

在Chrome中键入 chrome://tracing/ ,即可通过Load按钮加载time.json, 使之图形化显示

所谓的Op粒度, 就是说Timeline只表示DAG图计算的过程中,每个Op的起止时间和使用的Stream(Tensorflow使用StreamExecutor管理Stream),而Op粒度的分析有时是有误导性的,比如使用Horovod进行分布式训练时,由于多个AllreduceOp并无相关性,也分属不同的Stream,看起来并行度很高,其实在其内部实现中,一方面Horovod会做融合,另一方面只有一个后台线程真正的去做网络通信,最后,网络IO的能力上限取决于网卡,所以实际的IO路径根本不是Timeline上看到的那种并行,而是在Horovod后台,最多到网卡就已经串行了。

Continue reading

Tensorflow 设计技巧

图遍历

下述代码取自图计算逻辑的executor.cc文件.

遍历一张图有很多方法, TF中的这部分设计主要针对大量并行执行的场景: 即一个节点ready了就可以执行, 多个节点同时ready了可以同时执行, 为了达到并行的效果, 使用线程池作为后端支持. 通常来讲, 线程池内的一个线程如果执行完毕任务就会进入等待状态, 但此处的设计技巧, 减少了线程状态切换的开销

-15-26- 对于expensive的节点, 通常会丢入线程池执行, 但如果当前线程的queue是空, 就在当前线程执行,
-19-21-是这个算法的关键, 第一次遇到expensive并不会立即丢入线程池, 如果真要丢进去, 也会延迟到遇到下一个expensive节点的时候, 如此, n(直接丢入线程池的expensive节点) = n(一共遇到的expensive节点) – 1, 这样, 只要有expensive节点, 都会留一个给当前线程做最终定夺: 如果当前线程任务为空, 就不会劳烦线程池, 如果当前尚有其他工作, 还是丢给线程池执行.

python 代码片段收集

逐行处理文件

test.txt是一个有15140行的文本文件. 第一种方法在我的笔记本上需要0.02s. 而后一种需要0.04s.

读取指定行

C++ MiniTrick

时间戳打印

master-slave工作线程各自初始化

在master-worker模型中, 二者的初始化逻辑往往不同, 如果第一个执行的线程是master, 可以使用下面的代码来标识出:

Continue reading