最大化TensorFlow多GPU性能

11

我想知道有没有人能够给出关于如何在4个GPU设置中获得tensorflow最佳性能的建议。

作为一个测试,我创建了两个相同的网络(18层残差网络,使用小型滤波器组(范围从16-128)在32x32的输入上。批量大小512,每个GPU 128)。一个在MXNet中,另一个是基于inception示例模拟的。

我的MXNet网络可以以每秒7k个样例进行训练,而tensorflow只能以虚拟数据为基础达到4.2k,真实数据只有3.7k。

(当在1个GPU上运行时,数字分别为每秒1.2k个样例与2.1k)

在我的实验中,我有一些问题希望加快速度。

  1. 训练时GPU利用率似乎很低。我注意到在tensorflow白皮书中有支持在同一GPU上运行多个流的功能。这在公共版本中是否可行?

  2. 有没有办法在一个执行session.run()期间执行多个训练操作?或者有异步执行的方法吗?这将允许权重更新与下一批次的前向传递同时进行。我尝试使用2个线程(系统和QueueRunners),但结果只会减慢速度。MXNet能够通过在CPU上运行权重更新来提高速度,以便GPU可以用于下一个批次。

  3. 新的分布式运行时是否能够解决这些问题,使我能够在一台计算机上运行多个工作进程?

  4. 还有其他方法吗?

我知道这里在stack overflow上有很多类似的问题,但是我搜索过了,没有找到我已经尝试过的问题的解决方案。

编辑:

我进行了一些CUDA分析,看看哪些内核比较耗时。根据我的运行,21.4%的时间花费在内部:

void Eigen::internal::EigenMetaKernel_NonVectorizable<Eigen::TensorEvaluator
<Eigen::TensorAssignOp<Eigen::TensorMap<Eigen::Tensor<float, int=4, int=1, long>, int=16>,
Eigen::TensorPaddingOp<Eigen::array<std::pair<int, int>,
unsigned long=4> const, Eigen::TensorMap<Eigen::Tensor<float const,
int=4, int=1, long>, int=16> const > const > const, Eigen::GpuDevice>, long>(float, int=4)

20.0%的时间花在了

void Eigen::internal::EigenMetaKernel_NonVectorizable<Eigen::TensorEvaluator
<Eigen::TensorAssignOp<Eigen::TensorMap<Eigen::Tensor<float, int=4, int=1, long>, int=16>,
Eigen::TensorBroadcastingOp<Eigen::array<int, unsigned long=4>
const, Eigen::TensorMap<Eigen::Tensor<float const, int=4, int=1, long>,
int=16> const > const > const, Eigen::GpuDevice>, long>(float, int=4)

关于签名,我不确定这些是在做什么。这些有意义吗?

此外,分析报告显示低内核并发性为0%,这是预期的。计算利用率也很低,只有34.9%(这包括启动时间和训练循环中的一点Python。总共大约32秒,共91秒。在TensorFlow内部大约使用了50%的利用率)。

编辑2:

我附上了一个精简版的源代码。但总体上,我更关心问题1-3,不想占用大家太多时间。

此外,我正在运行来自以下版本构建的TensorFlow:f07234db2f7b316b08f7df25417245274b63342a

编辑3:

已更新至最新版本的TensorFlow(63409bd23facad471973b110df998782c0e19c06),使用默认数据格式(NHWC),这似乎显著加快了速度。在4个GPU上,虚拟数据为6.7k-6.8k(我认为是热依赖关系)每秒例子。1个GPU--每秒2.0k个示例。真实数据的性能约为每秒4.9k个示例(4 GPU)。1个GPU--每秒1.7k个示例。

编辑4:

此外,我尝试切换数据格式为BCHW。我根据Soumith的基准测试的模型进行转换。卷积部分的确更快了,但批量归一化似乎搞砸了所有事情。使用naive实现(修复轴并使权重[1,C,1,1]而不是[C,]),我只能在4个GPU上获得每秒1.2k个示例(虚拟数据)。而使用批量归一化操作前后的转置,则可以获得每秒6.2k个示例(虚拟数据)。仍然比NHWC数据格式慢。

1个回答

1
很难在没有看到代码的情况下诊断程序性能问题。有没有可能让我们以某种方式阅读您的测试代码?
顶部显示TensorPadding有点奇怪。我希望cudnn调用应该在概要文件的顶部。无论如何,向我们展示测试代码将是有帮助的。

我附上了源代码的gist。感谢您的帮助。可以安全地假设TensorMap的第二个模板参数是应用的内核吗?您如何知道它是TensorPadding而不是例如TensorAssign - luke
1
几个建议:1)尝试从HEAD重新克隆 - 自三月以来,Eigen的填充有几个改进,应该有助于提高速度。2)当使用CuDNN最佳支持的布局时,卷积目前更快:NCHW目前是最佳张量布局。https://github.com/soumith/convnet-benchmarks/blob/master/tensorflow/benchmark_alexnet.py#L18 为您演示如何指定卷积、最大池化等数据格式顺序。 - vrv
@vrv 从HEAD重新克隆可以显著提高性能。谢谢!至于data_format,我已经更新了原始帖子。我正在研究减速问题。(相当确定是在不同维度上进行的reduce操作。) - luke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接