【TF/Guide笔记】 12. Performance
performance一章里详细的介绍了function,大部分跟之前推理的结果差不多,这里做一些修正:
计算图并没有延迟计算的操作,在调用function的时候,建图和跑图是同时完成的,那看来tape.gradient的确可能产生冗余计算
关于多态,文档给出了详细规则,对于primitive和nested类型,可以认为它判断值是否完全一致,但对于其他自定义类型,是怎样都会触发多态的。对于tensor,框架会判断shape是否一致,也可以手动指定None维来避免多态
autograph对于分支的包装,只会操作条件为tensor的if语句。循环也差不多,只是对for的对象为dataset的时候做了特殊判断
后面讲了一堆在使用tf.function时可能遇到的问题,其实想明白计算图的工作原理之后都不难理解。然而tf还是要做这么大篇幅的说明,说明这件事对于熟悉了eager模式的人来说的确不好懂,这也是为了向下兼容带来的问题吧。
用大厂做好的产品还有的好处就是配套工具齐全,tf提供了一套profiler,不仅各种统计数据齐全,而且可视化做的也蛮好看的。可惜文档说,这套profiler是要联网的,如果纯本地跑会有一些图表加载不出来,大概会影响美观,但我理解数据还是齐全的。
关于计算图的优化,文档里列了一页,之前提到过的有常数折叠,表达式优化,剪枝,这里还有不少其他的,很多我都不大懂,能看懂的有:
子图优化,应该跟表达式优化差不多,一些常用的连续操作它给写了更好的实现方法大概是;
内存优化,大概是排布了一下内存使用的顺序?并且让计算图使用的峰值内存最小,还可以自动把一些暂时不需要的内存挪到cpu;
类似的还有把一些很轻的操作挪到cpu,把gpu上的操作改成16位浮点数。其他的分支和循环的简化,我感觉可能类似编译上的知识,这我就不大懂了。
关于精度的优化,这里并不是简单的把float32换成float16,根据文档的描述,打开mixed开关的话,keras会帮你选合适的精度设置,保证不会让训练结果变差,目前来看,对于fullyconnected来说,大概就是dense的部分用了float16,loss用的float32,activation不好说,但是也不用了解的这么仔细。
因为如果针对每个op里的每个步骤都要定义用16还是用32,应该需要实验或者证明来做恰当的选择,同时代码上也会有很多判断的地方。目前为止,function、strategy、tape、policy,这些东西都是包在外面的设置,都会对计算图结构产生影响,keras里动辄上千行代码,这种东西真是不想自己去搞。
另外记录一下,keras还帮用户做了loss scale,先给loss乘个数,这个数还是现场算的,最后再给gradient除,以防止中间结果出0,导致gradient是0。