如何构建自己的深度学习基础设施
nakn6373
8年前
<p>深度学习是一门经验科学,许多基础设施的质量也在倍增。幸运的是,现在的开源生态系统可以使任何人建立不错的深度学习基础设施。</p> <p>在这篇文章中,我们将讲述深度学习研究通常如何进行,介绍可选的对应基础设施以及开源的kubernetes-ec2-autoscaler,用于Kubernetes的批次优化扩展管理。希望这篇文章对你构建自己的深度学习基础设施有所帮助。</p> <h2><strong>用例</strong></h2> <p>深度学习典型的进步是从一个想法开始的,你在一个小问题上进行测试。在这个阶段,你想要快速的进行许多临时实验。理想情况下,你可以通过SSH连上一台机器,然后运行脚本,并在一小时以内得到结果。</p> <p>要使模型真正工作,通常需要预见所有可能出错的情况,并且设法解决这些限制。(这类似于构建新的软件系统,你多次运行代码来了解它的运行情况。)</p> <p>视频</p> <p>你需要从多个角度来考察你的模型,以了解它们的实际学习情况。上面这个来自于Dario Amodei的强化学习Agent(控制右边的球拍)取得了高比分,但当你看着它玩时,你会发现它只是呆在一个地方。因此,深度学习基础设施必须能够让用户灵活观察模型,仅仅给出汇总统计是不够的。</p> <p>一旦模型表现不错,你可以将它使用在更大的数据集和更多的GPU上。这是需要进行长期任务时才这么做,它们会消耗很多周期,并持续数天。你需要对实验小心管理,对所选择的超参数范围要考虑非常周到。</p> <p>前期的研究过程都是非结构化的、敏捷的;后期研究则是有条不紊的,并在一定程度上让人感到痛苦,但这都是得到良好结果所必须的。</p> <h2><strong>例子</strong></h2> <p>论文Improved Techniques for Training GANs 开头讲述了Tim Salimans设计了几种改善生成对抗性网络训 练的思想。我们将介绍最简单的思想(产生最好的样本,但不是最好的半监督学习)。GAN包含一个生成器和一个鉴别器网络。生成器尝试愚弄鉴别器,而鉴别器 则尝试区分生成数据和真实数据。直观地说,可以愚弄所有鉴别器的生成器是一个好的生成器。但是有一个难以修复的错误:生成器可能会“崩溃”,总是会输出完 全一样(可能是逼真的!)的样本。</p> <p>Tim提出这样的想法,给鉴别器输入样本的一个 小批次 ,而不是将整个样本作为输入。因此鉴别器就可以区分生成器是不是不断产生一张图像。当发现崩溃,生成器将会进行梯度调整来纠正这一问题。</p> <p>下一步就是将这个想法在MNIST和CIFAR10上构建原型。这需要尽快原型化一个小模型,使用真实数据,并检查结果。经过一番快速迭代,TIm得到了非常令人振奋的CIFAR-10样本——这个数据集上我们见过最好的样本。</p> <p>然而,深度学习(和一般的AI算法)必须进行扩展——小的神经网络可以证明一个概念,但是大的神经网络才能真正解决问题,才能为人所用。所以 Ian Goodfellow 将这个模型扩展到 ImageNet 上进行使用。</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/2af0a11584a357e518a972de09f174bc.jpg"></p> <p>我们的模型学会了生成ImageNet的图画</p> <p>对于更大的模型和数据集,Ian需要将模型并行部署在多个GPU上。每个Job将会占用90%的CPU和GPU,但即便如此,该模型还是需要经过多天的训练。在这种情况下,每个实验显得弥足珍贵,他会一丝不苟地记录每个实验结果。</p> <p>最终,虽然结果还不错,但并没有我们期望的那么好。虽然已经测试过很多假设,但仍然没有解决。这就是科学的本质。</p> <h2><strong>基础设施</strong></h2> <p>软件</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/249576cb3de6f62f4e8ad9d2292ea505.jpg"></p> <p>我们Tensorflow代码的一个</p> <p>我们绝大多数的研究代码是使用Python所写的,可以在 我们 的 开 源 项目 中看到。我们主要使用 Tensorflow (或者在特殊情况下使用 Theano )进行GPU计算;对于CPU计算我们还会使用 Numpy 。研究人员有时还会使用高层框架,例如基于Tensorflow的 Keras 。</p> <p>与多数深度学习社区一样,使用Python 2.7。我们通常使用 Anaconda ,它能很方便的打包,如 OpenCV ,和对一些科学计算库文件进行 性能优化 。</p> <h2><strong>硬件</strong></h2> <p>对于理想的批处理作业,加倍集群中的节点可以减半作业运行时间。不幸的是,在深度学习方面,增加GPU个数会 次线性 加快速度。因此,要达到顶级性能需要超顶级的GPU。我们还在 模拟器 、 强化学习环境 、或小规模模型上使用了许多CPU(这不比在GPU上运行的快)。</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/33fdb165a50eafd4361fe9fb61c2dee8.jpg"></p> <p>下满载的Titan Xs</p> <p>AWS 慷慨地给我们提供了大量的计算机。使用它们进行CPU实例以及水平扩展GPU作业。我们同样会运行自己的物理机,主要使用的是 Titan X GPU。我们希望有混合云:它可以使用不同GPU、互联以及将来可能成为重要深度学习的技术进行实验。</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/c69485b377c9069c90d7125caa4d3596.jpg"></p> <p>在 htop 上同样的物理单元显示有许多空闲的CPU。我们通常将CPU密集型工作与GPU密集型分开运行。</p> <p><strong>配置</strong></p> <p>我们使用基础设施与其他公司对待产品一样:它必须有简洁的界面,可用性与功能同等重要。我们使用一套统一的工具来管理所有的服务器并尽可能对它们进行同样的配置。</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/a610e3e7ab6bfc4a34b3f13cf000e0db.jpg"></p> <p>Terraform配置管理自动扩展组片段。Terraform创建,修改,或销毁运行的云资源来匹配你的配置文件。</p> <p>我们使用 Terraform 来建立AWS云资源(实例,网络路由,DNS记录等)。云和物理节点运行的是 Ubuntu ,使用 Chef 进行配置。为了加速处理,我们使用 Packer 来对集群AMI进行预处理。我们所有的集群使用非重叠的IP范围,通过用户笔记本上 OpenV*N 在共用网络上互联, strongSwan 部署在物理节点上(作为AWS 客户端网关 )。</p> <p>我们将用户的主目录,数据集以及结果存储在 NFS (物理硬件)和 EFS / S3 (AWS)上。</p> <p><strong>编制</strong></p> <p>可扩展的基础设施通常会导致简单用例变复杂。我们在基础设施的小型和大型作业上投入了同等精力,并且正在积极固化我们的工具包,使分布式用例与本地用例一样可用。</p> <p>我们提供了SSH节点(有的有GPU,有的没有)的集群用于临时实验,并在物理节点和AWS节点上使用 Kubernetes 作为集群调度器。集群跨越3个AWS regions——我们的作业比较耗费资源,有时候会占满单个regions所有资源。</p> <p>Kubernetes要求每个作业都是一个Docker容器,这样可以提供依赖隔离和代码快照。然而,构建一个新的Docker容器会给研究人员迭代周期增加少量额外的时间,所以我们也提供工具将研究人员笔记本上的代码转换成标准镜像。</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/4ae2c0a409231ed0ac748074c915b822.jpg"></p> <p><strong>TensorBoard中模型的</strong></p> <p>我们将Kubernetes的 flannel 网络直接暴露给研究人员的笔记本电脑,允许用户无缝网络访问他们运行的作业。这在访问监控服务时非常有用,比如 TensorBoard 。(最初的做法——从严格隔离的角度来看更明确——需要用户为他们想要暴露的端口创建一个Kubernetes 服务 ,但发现这会带来很大阻力。)</p> <p><strong>kubernetes-ec2-autoscaler</strong></p> <p>我 们的工作量会爆发性激增,并且不可预知:一项研究可能从单台机器可以进行的实验迅速地发展到需要1000个核心才能进行。比如,过了几个星期,一项实验交 互阶段只需一个Titan X,到了实验阶段需要60块Titan X,再到需要将近1600块 AWS GPU。因此,我们的云基础设施需要动态的配置Kubernetes节点。</p> <p>在 自动扩展 组中很容易运行Kubernetes节点,但是要正确管理这些组的大小就很难。在批处理作业提交后,集群知道它需要多少资源,然后直接分配。(相反,AWS的 扩展策略 将会产生新的节点碎片,直到有剩余资源,这可能会多次进行。)此外,在集群终止节点前,需要 洩流 节点,避免丢失正在执行的作业。</p> <p>只使用原始的EC2进行大批量作业很诱人,而我们开始也是这么做的。然而,Kubernetes 生态系统带来了很多价值:低阻力工具,日志,监控,能够从运行实例中分别管理物理节点等。正确配置Kubernetes自动扩展比在原始EC2上重新构建这个生态系统更简单。</p> <p>我们即将推出 kubernetes-ec2-autoscaler ,面向Kubernetes的批处理优化的扩展管理。它在Kubernetes上作为普通的 Pod 运行,只需你的工作节点在自动扩展组内。</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/6999c51a118d6a41b8a5e8ac6ff4ea82.jpg"></p> <p><strong>Kubernetes集群的启动配置</strong></p> <p>自动扩展器获取Kubernetes 主节点的状态,包括计算集群资源需求和容量所需的一切信息。如果资源不足,它将会洩流节点,然后终止它们。如果需要更多的资源,它会计算应该创建什么服务并适当增大自动扩展组的大小(或是简单的 取消已洩流节点警告 ,从而避免了新节点起转的时间)。</p> <p>kubernetes-ec2-autoscaler 负责处理多个自动扩展组,超过CPU(内存和GPU)的资源,限制你作业的细粒度因素,比如AWS region和实例大小。此外,突发性工作负载可能导致自动扩展组超时和错误,因为(令人惊讶!)AWS不具有无限容量。在这种情况 下,kubernetes-ec2-autoscaler 检测到错误并把作业发配到第二个AWS region。</p> <p> </p> <p>来自:https://mp.weixin.qq.com/s?__biz=MjM5NzQ3ODAwMQ==&mid=2686978257&idx=1&sn=8783c46c72b12183906c15f106253e77&scene=0&key=&ascene=7&uin=&devicetype=android-23&version=26031933&nettype=WIFI</p> <p> </p>