tensorflow - tensorflow 宽线性模型推断 gpu 慢
问题描述
我正在训练一个关于 tensorflow 的稀疏逻辑回归模型。这个问题专门针对推理部分。我正在尝试对 cpu 和 gpu 的推理进行基准测试。我在我当前的 GCE 盒子上使用 Nvidia P100 gpu(4 个芯片)。我是 gpu 的新手,很抱歉提出一些幼稚的问题。
该模型相当大~54k 操作(与 dnn 或 imagenet 模型相比,它被认为是大吗?)。当我记录设备放置时,我只看到 gpu:0 正在使用,其余的未使用?我在训练期间不做任何设备放置,但在推理期间我希望它以最佳方式放置和使用 gpu。我观察到的几件事:我的输入节点占位符(feed_dict)放在 cpu 上,所以我假设我的数据正在从 cpu 复制到 gpu?feed_dict 在幕后究竟是如何工作的?
1)如何将我想直接在 GPU 上运行预测的数据放置?注意:我的训练在具有多个 TB 的分布式 cpu 上运行,因此在训练期间我不能直接在我的图表中使用常量或变量,但我的推断我肯定可以有我想直接放在 gpu 上的小批量数据。我有办法做到这一点吗?2)由于我使用的是P100 gpu,我认为它与主机具有统一的内存,是否可以进行零拷贝并直接将我的数据加载到gpu中?我如何从 python、java 和 c++ 代码中做到这一点。目前我使用来自各种谷歌资源的 feed_dict,我认为这根本不是最佳的。3)是否有一些工具或分析器可以用来查看我何时分析代码,例如:
for epoch_step in epochs:
start_time = time.time()
for i in range(epoch_step):
result = session.run(output, feed_dict={input_example: records_batch})
end_time = time.time()
print("Batch {} epochs {} :time {}".format(batch_size, epoch_step, str(end_time - start_time)))
在 1)cpu 到 gpu 数据传输 2)会话运行开销 3)gpu 利用率(目前我定期使用 nvidia-smi 来监控 4)cpu 与 gpu 上的内核调用开销(我假设每次调用 sess.运行调用 1 个内核调用对吗?
我目前的基准测试结果:CPU:
Batch size : 10
NumberEpochs TimeGPU TimeCPU
10 5.473 0.484
20 11.673 0.963
40 22.716 1.922
100 56.998 4.822
200 113.483 9.773
Batch size : 100
NumberEpochs TimeGPU TimeCPU
10 5.904 0.507
20 11.708 1.004
40 23.046 1.952
100 58.493 4.989
200 118.272 9.912
Batch size : 1000
NumberEpochs TimeGPU TimeCPU
10 5.986 0.653
20 12.020 1.261
40 23.887 2.530
100 59.598 6.312
200 118.561 12.518
Batch size : 10k
NumberEpochs TimeGPU TimeCPU
10 7.542 0.969
20 14.764 1.923
40 29.308 3.838
100 72.588 9.822
200 146.156 19.542
Batch size : 100k
NumberEpochs TimeGPU TimeCPU
10 11.285 9.613
20 22.680 18.652
40 44.065 35.727
100 112.604 86.960
200 225.377 174.652
Batch size : 200k
NumberEpochs TimeGPU TimeCPU
10 19.306 21.587
20 38.918 41.346
40 78.730 81.456
100 191.367 202.523
200 387.704 419.223
一些值得注意的观察:随着批量大小的增加,我看到我的 gpu 利用率增加(它使用的唯一 gpu 达到 100%,有没有办法我可以告诉 tf 也使用其他 gpu)批量大小 200k 是我唯一看到的时间我幼稚的基准测试表明,与 cpu 相比,gpu 的增益很小。增加给定 epoch 的批大小对 cpu 和 gpu 的时间影响最小,直到批大小 <= 10k。但是在从 10k -> 100k -> 200k 增加批量大小之后,时间也增加得非常快,即对于给定的时期,让我们说 10 个批量大小为 10、100、1k、10k,cpu 时间和 gpu 时间保持相当稳定~5- gpu 为 7 秒,cpu 为 0.48-0.96 秒(这意味着 sess.run 的开销比计算图形本身的开销要高得多?),但是随着批量大小的进一步增加,计算时间会以更快的速度增加,即对于 epoch 10 100k-> 200k gputime 从 11 -> 19 秒增加,cpu 时间也翻倍,为什么会这样?即使我只有一个 sess.run 似乎更大的批量大小,但在内部它将它分成更小的批量并调用 sess.run 两次,因为 epoch 20 batch size 100k 与 epoch 10 batch 200k 更匹配。
我怎样才能进一步改进我的推理,我相信我没有以最佳方式使用所有 gpus。关于如何更好地进行基准测试以获得更好的 cpu-> gpu 传输时间和图形计算从 cpu 移动到 gpu 的实际加速,有什么想法吗?如果可能的话,直接将数据更好地加载到 gpu 中?我可以仅在推理期间将一些节点放置到 gpu 以获得更好的性能吗?关于量化或优化推理图的想法?
改进基于 gpu 的推理的更多想法。可能是基于 xla 的优化或 tensrort ?我希望有高性能的推理代码在 gpu 上运行这些计算,而应用程序服务器在 cpu 上运行。
解决方案
信息来源之一是关于性能的 TensorFlow 文档,包括Optimizing for GPU and High Performance Models。
也就是说,这些指南倾向于针对训练而不是批量推理,尽管某些原则肯定仍然适用。
我会注意到,除非您使用 DistributionStrategy,否则 TensorFlow 不会自动将操作放在多个 GPU(来源)上。
在您的特殊情况下,我认为 GPU 还没有经过很好的调整来执行您的模型所需的稀疏操作类型,所以我实际上并不希望它在 GPU 上做得那么好(如果您记录设备放置有可能在 CPU 上完成查找)。逻辑回归模型只有一个(稀疏)输入层和一个输出层,因此通常很少有数学运算。GPU 在进行大量矩阵乘法、卷积等时表现最为出色。
最后,我鼓励您使用 TensorRT 来优化您的图表,尽管对于您的特定模型,不能保证它会做得更好。
推荐阅读
- ruby-on-rails - devise-async 不使用 sidekiq 执行入队作业
- python-3.x - 使用 Python 按字母顺序对 MS Word 段落进行排序
- java - JPA 实体类中@ManyToOne 的可选属性的目的是什么?
- unreal-engine4 - 为什么在发布中未启用 InsertChildAt
- svn - TortoiseSVN - 恢复搁置文件的内容
- python - 如何仅对分组的列进行分组和添加
- javascript - LocomotiveScroll 在我检查元素之前无法工作
- reactjs - 使用反应钩子访问循环中的 id
- javascript - 单击此按钮时如何运行此 node.js
- python - 有没有办法以特定格式将存储在 Python 列表中的所有对象的所有属性写入 .txt?