欢迎光临散文网 会员登陆 & 注册

【TF/Guide笔记】 11. Data input pipelines

2022-03-05 17:26 作者:纪一希  | 我要投稿

    看前面的文档的时候我一直很好奇他的输入是怎么做的,因为在我的观念里,下意识的会认为要有一个专门负责数据读写的线程或进程才对,但是始终没有找到相关的描述。

    就像在distributed training里,每个worker也只是调用了一下准备输入的函数,没有说这个过程里就启动了一个独立线程。

    看到tf.data的说明才明白,人家还真就没启额外的线程,也就是对于worker来说,create_per_worker_dataset就是一个一次性调用,在你实现的函数里,你是把文件全读进了内存也好,只是打开了文件指针也好,这都是你自己选择的,后续next()的时候逻辑也由用户自己指定,框架不帮你做什么预设。当然你也可以自己启一个独立的IO线程。

    但是正常来说,异步IO是很重要的,Dataset在高级使用方法里提供了相应接口。

    首先是prefetch,按我的理解,prefetch并没有启动独立的线程做IO,它应该是变相的利用了系统读取文件的那个pipeline,让它帮你做了prefetch,这样在我真的跑到read的时候其实相关数据已经大概率在内存里了,算是一定程度上的优化。

    最正经的还是interleave,这个也是跟我以前理解的data source一样的东西,也就是单独启几个线程,预先把数据读好一部分备用,保证下游计算的吞吐始终是充足的,另外实现了cache,以便缓存中间结果。


    说实在的,在数据流的实现上着实是没啥新鲜东西,我理解,可能复杂的数据处理并不在tf的设计理念之内。对于tf来说,它优化的是基于tensor的高计算模型,而不是像lr那样高吞吐的简单模型,所以在数据流上就不用搞的太复杂。

    以前我们在做数据流的时候,必须要考虑数据处理,甚至是sortby,partitionby这样的操作,因为我经手的项目都是高吞吐的模型,特别是带时序的数据,要做各种各样的数据处理,真到训练上反而不需要太多计算,这就让我们在数据这一端弄的非常头疼。本来想看看tf是怎么处理的,结果人家根本不care这种问题。

    tf.data文档的前半部分我很快的扫了一眼,大都是讲怎么兼容各种数据格式的,但是这些数据在转换成tensor真的进入训练之后,用的逻辑都是相同的,也就是非常简单的流式数据,几乎没有任何多余的操作。

    就比如在random shuffle,这个问题上,前面有一节提过,你可以自己对文件列表shuffle,但是到了数据流上的shuffle,他只能提供一个buffer,在其内部做shuffle,不能给你保证全局打乱,除非你开个超大buffer。比如对于imbalance数据,他也只能是概率性的丢到多余的正例或负例,这个比例还得用户自己指定。

    也正是因为tf.data是个非常简单的数据流,它才能够支持迭代器的方式生成数据,支持你在上面嵌套很多map,或者原地的batch、unbatch。


    这样的设计的确让框架变得简单了,把很多问题扔给了用户,虽然用户代码写起来繁琐,但也能让人更好的控制代码逻辑和资源开销。

    我们以前的框架把data source,parameter server和training loop都揉到了一起,看似是个训练的通用框架,但很多时候遇到特殊操作,还是要部分的舍弃一些功能,结果不需要的这些功能的代码又可能触发未知的bug,在这三者交接的部分如果做的更解耦一些,整体逻辑应该能更清晰一点,尤其是在python接口的设计上(虽然现在我觉得弄python api这件事本身就很蠢)。

【TF/Guide笔记】 11. Data input pipelines的评论 (共 条)

分享到微博请遵守国家法律