本文由 HPC AI 创新实验室的 Rakshith Vasudev 和 John Lockman 于 2019 年 10 月撰写
如前所述,CheXNet 是一种人工智能放射科医师辅助模型,可利用 DenseNet 从给定的胸部 x 射线图像中识别多达 14 类病理。我们探索了几种方法来横向扩展模型的培训,该模型与带有 ResNet-50 的原始 CheXNet-121 相比旗鼓相当或更胜一筹,彰显在可扩展性和提高培训准确性(正 AUROC)方面的承诺。作者展示了 CPU 系统的可扩展性,但我们有兴趣利用 GPU 的并行度来加快培训过程。在本文中,我们介绍了在 Dell EMC C4140 服务器中利用 Nvidia V100 SXM2 GPU 进行 CheftXNet 分布式横向扩展培训时实现最大性能的最佳实践。Dell EMC PowerEdge C4140 通过 SXM2 配置中的四个 Nvidia V100 GPU 提供密度和性能。
硬件配置: | 软件配置: |
---|---|
|
|
新的计算设备(如 GPU 和 TPU)允许以越来越快的速度培训神经网络,所以,CPU 处理很容易成为瓶颈。tf.data API 向用户提供构造块,以设计有效利用 CPU 的输入管道,从而优化 ETL 流程的每个步骤。
要执行培训步骤,您必须首先解压和转换培训数据,然后将其馈送到在加速器上运行的模型。但是,在欠佳的同步实施中,当 CPU 准备数据时,加速器处于空闲状态。相反,当加速器培训模型时,CPU 处于空闲状态。因此,培训步长时间是 CPU 预处理时间和加速器培训时间的总和
管道重叠培训步骤的预处理和模型执行。当加速器执行培训步骤 N 时,CPU 正在为步骤 N+1 准备数据。这样做可将培训的步长时间缩短到最大值(而不是总和),以及缩短提取和转换数据所需的时间。
如果没有管道连接,CPU 和 GPU/TPU 大部分时间都空闲:
图 1:有序执行经常使 GPU 空闲
通过管道连接,空闲时间会显著减少:
图 2:管道重叠 CPU 和 GPU 利用,更大限度地提高 GPU 利用率
tf.data API 通过 tf.data.Dataset.prefetch 转换提供软件管道机制,该转换可用于在使用时间中减去数据生成的时间。具体而言,转换使用后台线程和内部缓冲区在请求前先从输入数据集中预取元素。
有关详细信息,请参阅此处:https://www.tensorflow.org/guide/performance/datasets
如果遵循 tensorflow 提供的指导准则,则可以获得类似于下文(旧方法)的数据管道:
https://github.com/dellemc-hpc-ai/code-examples/blob/master/cheXNet-snippets/old_approach.py
在此方法(也称为旧方法)中,tf 数据管道执行以下操作(假定胸部 x 射线数据集是 TFRecords 序列):
但是,这不是性能最高的代码。这会导致停滞和频繁的 0% gpu 利用率。基本上,它不会有效地利用加速器。
为了正确设置 tf 数据管道,我们遵循 tensorflow 官方模型采取的方法,尤其是 ResNet 的方法。 旧方法与新方法之间的区别在于,在将数据管道送入模型之前如何设置数据管道。
新方法如下所示:
https://github.com/dellemc-hpc-ai/code-examples/blob/master/cheXNet-snippets/new_approach.py
TensorFlow 官方模型方法也称为新方法,如下所示:
下面是使用 TF 官方模型的旧方法和新方法的性能比较。
图 3:借助新方法,可以预期接近线性扩展。
可以看到,性能受到严重影响,使用旧方法完全没有扩展。GPU 通常很少或根本没有利用,导致性能陷入谷底。如果通信处理得当,在一个 GPU 上提高计算效率意味着在多个节点的多个 GPU 上提高计算效率。
让 CPU 并行进行预处理、从内存和 GPU 预取处理的数据、通过快速通信承担矩阵乘法重任则是使这种新方法对于多节点扩展更具吸引力的另一个方面。
运行作业的环境与您的作业一样重要,因为拥有合适的库/模块非常重要,因为它们会影响培训效果。此外,拥有最新的 CUDA 相关库有助于提高性能。
如果您没有设置工作环境,请按照此教程进行安装。
MPI 是一个通信库,可帮助 Horovod 分发作业。探索了不同的绑定和映射参数选项,C4140 的最佳参数是按套接字映射。建议的设置如下所示:mpirun --map-by socket -np x python pyfile.py --pyoptions
如果有多个进程处理一个 gpu,那么它们很可能会争夺 GPU 资源、消耗 GPU 内存,并且实际上在每个批次不安装更多映像,从而导致 GPU 性能受到冲击。已研究 Tensorflow 1.13.1,但当时似乎存在错误。它为每个 GPU 启动多个进程。
总而言之: