OpenAI研究 深度学习的基础设施
用例
典型的深度学习进步始于一个想法,您可以在一个小问题上对其进行测试。在此阶段,您希望快速运行许多临时实验。理想情况下,您可以通过 SSH 连接到一台机器,在屏幕上运行一个脚本,并在不到一个小时的时间内得到结果。
要使模型真正发挥作用,通常需要看到它以各种可能的方式失败,并找到解决这些限制的方法。(这类似于构建任何新的软件系统,您将在其中多次运行代码以建立对其行为方式的直觉。)
因此深度学习基础设施必须允许用户灵活地反思模型,而仅仅公开汇总统计是不够的。
一旦模型显示出足够的潜力,您就可以将其扩展到更大的数据集和更多的 GPU。这需要消耗许多周期并持续多天的长时间作业。您将需要仔细的实验管理,并且对您选择的超参数范围非常周到。
早期的研究过程是非结构化和快速的;后者是有条不紊的,有点痛苦,但要获得好的结果,这一切都是绝对必要的。
一个例子
论文 Improved Techniques for Training GANs 始于 Tim Salimans提出的几个改进生成对抗网络训练 的想法 。我们将描述这些想法中最简单的(碰巧产生了最好看的样本,尽管不是最好的半监督学习)。
GAN 由生成器和鉴别器网络组成。生成器试图欺骗鉴别器,而鉴别器试图区分生成的数据和真实数据。直觉上,可以欺骗所有鉴别器的生成器是相当不错的。但是有一个难以修复的故障模式:生成器可以通过始终输出完全相同(可能看起来很逼真!)的样本来“崩溃”。
Tim 的想法是为判别器提供一整批 样本 作为输入,而不仅仅是一个样本。因此,鉴别器可以判断生成器是否只是不断地生成单个图像。发现崩溃后,梯度将被发送到生成器以纠正问题。
下一步是在 MNIST 和 CIFAR-10上对想法进行原型设计。这需要尽快制作一个小模型的原型,在真实数据上运行它,并检查结果。经过一些快速迭代后,Tim 得到了非常令人鼓舞的 CIFAR-10 样本=——几乎是我们在该数据集上看到的最好的样本。
然而,深度学习(以及一般的 AI 算法)必须经过扩展才能真正令人印象深刻——小型神经网络是概念的证明,但大型神经网络实际上可以解决问题并且很有用。因此, Ian Goodfellow 致力于扩展模型以在 ImageNet上运行。

对于更大的模型和数据集,Ian 需要跨多个 GPU 并行化模型。每项工作都会将多台机器的 CPU 和 GPU 利用率推至 90%,但即便如此,该模型也需要花费很多天的时间来训练。在这样的制度下,每一次实验都变得弥足珍贵,他会一丝不苟地记录每一次实验的结果。
最终,虽然结果不错,但不如我们希望的那么好。我们已经测试了许多关于原因的假设,但仍未破解。这就是科学的本质。
基础设施
软件

我们的 TensorFlow 代码示例 我们的绝大多数研究代码都是用 Python 编写的,这反映在 我们的 开源项目 中。我们主要使用 TensorFlow (或 特殊情况下的Theano )进行 GPU 计算;对于 CPU,我们使用那些或 Numpy。 研究人员有时还会在 TensorFlow 之上使用更高级别的框架,例如 Keras 。
与许多深度学习社区一样,我们使用 Python 2.7。我们一般使用 Anaconda ,它对OpenCV等其他比较难的包有方便的打包 , 对一些科学库有性能优化。

我们的绝大多数研究代码都是用 Python 编写的,这反映在 我们的 开源项目 中。我们主要使用 TensorFlow (或 特殊情况下的Theano )进行 GPU 计算;对于 CPU,我们使用那些或 Numpy。 研究人员有时还会在 TensorFlow 之上使用更高级别的框架,例如 Keras 。
与许多深度学习社区一样,我们使用 Python 2.7。我们一般使用 Anaconda ,它对OpenCV等其他比较难的包有方便的打包 , 对一些科学库有性能优化。
硬件
置备
我们像许多公司对待产品一样对待基础设施:它必须提供一个简单的界面,可用性与功能一样重要。我们使用一套一致的工具来管理我们所有的服务器,并尽可能以相同的方式配置它们。

用于管理 Auto Scaling 组的 Terraform 配置片段。Terraform 创建、修改或销毁您正在运行的云资源以匹配您的配置文件。 我们使用 Terraform 来设置我们的 AWS 云资源(实例、网络路由、DNS 记录等)。我们的云和物理节点运行 Ubuntu 并配置了 Chef。为了加快启动时间,我们使用Packer预烘焙我们的集群 AMI 。我们所有的集群都使用不重叠的 IP 范围,并通过公共互联网与用户笔记本电脑上的OpenVPN 和 物理节点(充当 AWS 客户网关)上的strongSwan互连 。
我们像许多公司对待产品一样对待基础设施:它必须提供一个简单的界面,可用性与功能一样重要。我们使用一套一致的工具来管理我们所有的服务器,并尽可能以相同的方式配置它们。

我们使用 Terraform 来设置我们的 AWS 云资源(实例、网络路由、DNS 记录等)。我们的云和物理节点运行 Ubuntu 并配置了 Chef。为了加快启动时间,我们使用Packer预烘焙我们的集群 AMI 。我们所有的集群都使用不重叠的 IP 范围,并通过公共互联网与用户笔记本电脑上的OpenVPN 和 物理节点(充当 AWS 客户网关)上的strongSwan互连 。
编排
可扩展的基础架构通常最终会使简单的案例变得更加困难。我们为小型和大型工作的基础设施投入了同等的努力,并且我们正在积极巩固我们的工具包,以使分布式用例与本地用例一样容易访问。
我们提供了一个 SSH 节点集群(有和没有 GPU)用于临时实验,并运行 Kubernetes 作为物理节点和 AWS 节点的集群调度程序。我们的集群跨越 3 个 AWS 区域——我们的工作非常频繁,有时我们会在个别区域达到容量。
Kubernetes 要求每个作业都是一个 Docker 容器,这为我们提供了依赖隔离和代码快照。然而,构建一个新的 Docker 容器可以为研究人员的迭代周期增加宝贵的额外秒数,因此我们还提供工具以透明地将代码从研究人员的笔记本电脑发送到标准图像中。

TensorBoard 中的模型学习曲线 我们将 Kubernetes 的 flannel 网络直接暴露给研究人员的笔记本电脑,让用户可以无缝地通过网络访问他们正在运行的作业。这对于访问TensorBoard等监控服务特别有用 。 (我们最初的方法——从严格隔离的角度来看更干净——要求人们为他们想要公开的每个端口创建一个 Kubernetes 服务,但我们发现它增加了太多的摩擦。)
可扩展的基础架构通常最终会使简单的案例变得更加困难。我们为小型和大型工作的基础设施投入了同等的努力,并且我们正在积极巩固我们的工具包,以使分布式用例与本地用例一样容易访问。
我们提供了一个 SSH 节点集群(有和没有 GPU)用于临时实验,并运行 Kubernetes 作为物理节点和 AWS 节点的集群调度程序。我们的集群跨越 3 个 AWS 区域——我们的工作非常频繁,有时我们会在个别区域达到容量。
Kubernetes 要求每个作业都是一个 Docker 容器,这为我们提供了依赖隔离和代码快照。然而,构建一个新的 Docker 容器可以为研究人员的迭代周期增加宝贵的额外秒数,因此我们还提供工具以透明地将代码从研究人员的笔记本电脑发送到标准图像中。

我们将 Kubernetes 的 flannel 网络直接暴露给研究人员的笔记本电脑,让用户可以无缝地通过网络访问他们正在运行的作业。这对于访问TensorBoard等监控服务特别有用 。 (我们最初的方法——从严格隔离的角度来看更干净——要求人们为他们想要公开的每个端口创建一个 Kubernetes 服务,但我们发现它增加了太多的摩擦。)
kubernetes-ec2-autoscaler
我们的工作负载是突发的且不可预测的:一系列研究可以从单机实验快速发展到需要 1,000 个内核。例如,在几周内,一项实验从在单个 Titan X 上的交互阶段发展到在 60 个 Titan X 上的实验阶段,再到需要近 1600 个 AWS GPU。因此,我们的云基础设施需要动态配置 Kubernetes 节点。
在Auto Scaling组中运行 Kubernetes 节点很容易 ,但很难正确管理这些组的大小。提交批处理作业后,集群确切地知道它需要什么资源,并且应该直接分配这些资源。(相比之下,AWS 的 扩展策略 将逐步启动新节点,直到资源不再耗尽,这可能需要多次迭代。)此外,集群需要 在终止节点之前耗尽 节点以避免丢失运行中的作业。
将原始 EC2 用于大批量作业很诱人,这确实是我们的起点。然而,Kubernetes 生态系统增加了相当多的价值:低摩擦工具、日志记录、监控、将物理节点与正在运行的实例分开管理的能力等等。让 Kubernetes 正确地自动缩放比在原始 EC2 上重建这个生态系统更容易。
我们发布了 kubernetes-ec2-autoscaler,这是一个针对 Kubernetes 的批量优化扩展管理器。它在 Kubernetes 上作为普通 Pod运行 ,只需要您的工作节点位于 Auto Scaling 组中。

Kubernetes 集群的启动配置 自动缩放器通过轮询 Kubernetes master 的状态来工作,其中包含计算集群资源请求和容量所需的一切。如果容量过剩,它会耗尽相关节点并最终终止它们。如果需要更多资源,它会计算应该创建哪些服务器并适当增加您的 Auto Scaling 组大小(或者简单地 取消 封锁耗尽的节点,从而避免新节点启动时间)。
kubernetes-ec2-autoscaler 处理多个 Auto Scaling 组、CPU 以外的资源(内存和 GPU),以及对您的作业的细粒度约束,例如 AWS 区域和实例大小。此外,突发性工作负载可能导致 Auto Scaling 组超时和错误,因为(令人惊讶的是!)即使 AWS 也没有无限容量。在这些情况下,kubernetes-ec2-autoscaler 会检测到错误并溢出到辅助 AWS 区域。
我们的基础设施旨在最大限度地提高深度学习研究人员的生产力,使他们能够专注于科学。我们正在构建工具以进一步改进我们的基础架构和工作流程,并将在接下来的几周和几个月内分享这些工具。我们 欢迎帮助 使这一切变得更快!
我们的工作负载是突发的且不可预测的:一系列研究可以从单机实验快速发展到需要 1,000 个内核。例如,在几周内,一项实验从在单个 Titan X 上的交互阶段发展到在 60 个 Titan X 上的实验阶段,再到需要近 1600 个 AWS GPU。因此,我们的云基础设施需要动态配置 Kubernetes 节点。
在Auto Scaling组中运行 Kubernetes 节点很容易 ,但很难正确管理这些组的大小。提交批处理作业后,集群确切地知道它需要什么资源,并且应该直接分配这些资源。(相比之下,AWS 的 扩展策略 将逐步启动新节点,直到资源不再耗尽,这可能需要多次迭代。)此外,集群需要 在终止节点之前耗尽 节点以避免丢失运行中的作业。
将原始 EC2 用于大批量作业很诱人,这确实是我们的起点。然而,Kubernetes 生态系统增加了相当多的价值:低摩擦工具、日志记录、监控、将物理节点与正在运行的实例分开管理的能力等等。让 Kubernetes 正确地自动缩放比在原始 EC2 上重建这个生态系统更容易。
我们发布了 kubernetes-ec2-autoscaler,这是一个针对 Kubernetes 的批量优化扩展管理器。它在 Kubernetes 上作为普通 Pod运行 ,只需要您的工作节点位于 Auto Scaling 组中。

自动缩放器通过轮询 Kubernetes master 的状态来工作,其中包含计算集群资源请求和容量所需的一切。如果容量过剩,它会耗尽相关节点并最终终止它们。如果需要更多资源,它会计算应该创建哪些服务器并适当增加您的 Auto Scaling 组大小(或者简单地 取消 封锁耗尽的节点,从而避免新节点启动时间)。
kubernetes-ec2-autoscaler 处理多个 Auto Scaling 组、CPU 以外的资源(内存和 GPU),以及对您的作业的细粒度约束,例如 AWS 区域和实例大小。此外,突发性工作负载可能导致 Auto Scaling 组超时和错误,因为(令人惊讶的是!)即使 AWS 也没有无限容量。在这些情况下,kubernetes-ec2-autoscaler 会检测到错误并溢出到辅助 AWS 区域。
我们的基础设施旨在最大限度地提高深度学习研究人员的生产力,使他们能够专注于科学。我们正在构建工具以进一步改进我们的基础架构和工作流程,并将在接下来的几周和几个月内分享这些工具。我们 欢迎帮助 使这一切变得更快!