[原创] 强化学习框架 rlpyt 并行(parallelism)原理初探

转载需注明出处:https://www.codelast.com/

查看关于 rlpyt 的更多文章请点击这里

rlpyt 是BAIR(Berkeley Artificial Intelligence Research,伯克利人工智能研究所)开源的一个强化学习(RL)框架。我之前写了一篇它的简介。 

在单机上全面的并行(Parallelism)特性是 rlpyt 有别于很多其他强化学习框架的一个显著特征。在前面的简介文章中,已经介绍了 rlpyt 支持多种场景下的并行训练。而这种“武功”是怎么修炼出来的呢?它是站在了巨人的肩膀上——通过PyTorch的多进程(multiprocessing)机制来实现的。
所以你知道为什么 rlpyt 不使用TensorFlow这样的框架来作为后端了吧,因为TensorFlow根本就没有这种功能。TensorFlow只能靠类似于Ray这样的并行计算框架的帮助,才能支撑起全方位的并行特性。

▶▶ 为什么说TensorFlow自身的并行能力并不适用于强化学习场景
限于我掌握的知识,我不保证下面的结论都是正确的,请专家们不吝赐教。
相信很多刚开始学写强化学习程序的人,都是从莫凡的强化学习教程开始的,莫凡的强化学习教程使用的是TensorFlow来实现的(很久以前看到是这样,后来我没有再去关注过,不知道他有没有发布在其他ML框架下的RL教程)。
看过一部分莫凡RL代码的人都会知道,里面用TensorFlow实现的静态图多进程“并行”训练逻辑有多么晦涩(而且并行其实是伪并行,说到底还是串行)。
我个人认为,如果一个初学者从这样的程序入手,其实就相当于“劝退”,也就是说:这程序这么难写,你还是别学了吧。如果有与莫凡的RL代码逻辑对等的PyTorch代码,那绝对会是另一番景象。
文章来源:https://www.codelast.com/
有人会说,明明TensorFlow就支持并行训练的啊!现在很多模型不就是通过多机多卡分布式训练的吗?
然而到了强化学习场景下,就不是这么一回事了:强化学习和监督学习很不一样。在强化学习场景下,如果要并行训练的话,会需要多个agent,与多个environment交互,对应到程序就是多个进程/线程。与environment交互的过程,可以是纯CPU计算,也可以是CPU/GPU混合计算(例如,inference得到action的过程就可以放在GPU上加速),但这个过程不能是纯GPU计算的过程。以Atari游戏模拟器为例,调用ALE接口得到Atari环境的反馈,这个过程就是CPU计算的,不能在GPU上计算。整个强化学习的流程,数据就是这样不断地在CPU/GPU之间流转,当然你可以使用纯CPU,但假设你使用了GPU的话,也只能在一小部分工作中使用GPU,其实CPU的工作也很重。反观supervised learning,当你把数据预处理好了之后,就可以一次性地喂给GPU,GPU在单机单卡训练的时候,可以把结果全部算完了再吐回给CPU;就算是Distributed TensorFlow,也不适用于强化学习,因为Distributed TensorFlow的并行功能是为了并行地使用GPU对吧?但强化学习的采样过程是使用CPU,按我的理解这部分工作不能使用Distributed TensorFlow来并行,相反PyTorch有multiprocessing可以做到;而计算梯度之类的工作用Distributed TensorFlow就可以并行了——但别的DL框架例如PyTorch也可以啊。
所以Distributed TensorFlow在RL场景下有什么优势?没看出来。
关于TensorFlow在强化学习场景下的应用,莫凡当时也在知乎向网友提问如何能在TF下较好地实现强化学习的并行功能,结论大概就是:还是用PyTorch吧!
另外,知乎上有一个讨论,提问者对GPU并行训练DRL模型的并行过程提出了疑问。第一个回答里面说“采样过程可以并行”,但作者说的并不是指Distributed TensorFlow支持这个功能。
所以我认为,TensorFlow由于缺少了类似于PyTorch multiprocessing那样的模块,它只能借助于类似于Ray的并行计算框架,也就是在外面再“包装一层”,才能把TF对“全面的并行强化学习”的缺陷给修补上。
文章来源:https://www.codelast.com/
▶▶ PyTorch的多进程处理功能
参考这段话

由于全局解释器锁(global interpreter lock,GIL)的 Python 默认实现不允许并行线程进行并行执行,所以为了解决该问题,Python 社区已经建立了一个标准的多进程处理模块,其中包含了大量的实用程序(utility),它们可以使得用户轻易地生成子进程并能够实现基础的进程间通信原语(communication primitive)。
 
然而,原语的实现使用了与磁盘上持久性(on-disk persistence)相同格式的序列化,这在处理大规模数组时效率不高。所以,PyTorch 将Python 的 multiprocessing 模块扩展为 torch.multiprocessing,这就替代了内置包,并且自动将发送至其他进程的张量数据移动至共享内存中,而不用再通过通信渠道发送。
 
PyTorch 的这一设计极大地提升了性能,并且弱化了进程隔离(process isolation),从而产生了更类似于普通线程程序的编程模型。
看看就好,想深入了解的话请移步PyTorch文档。
文章来源:https://www.codelast.com/
▶▶ rlpyt的并行(parallelism)功能的局限
rlpyt瞄准的是单机上的RL训练效率的极致优化,它不支持多机训练。在单机硬件资源允许的范围内,rlpyt可以让RL模型训练很快,但如果你的训练数据占用的资源远远超过了单机硬件的范围,那么就只能利用支持分布式训练的框架了,例如构建在Ray之上的框架RLlib,又例如基于PaddlePaddle的PARL等。
这里值得一提的是,PARL号称它与RLlib进行了IMPALA算法下的对比测试,其数据吞吐量(同等计算资源下的数据收集速度)足以吊打RLlib,所以PARL看起来是一个有前途的框架。

发表评论

电子邮件地址不会被公开。 必填项已用*标注