TensorFlow GPU 利用率仅为 60% (GTX 1070)

Posted

技术标签:

【中文标题】TensorFlow GPU 利用率仅为 60% (GTX 1070)【英文标题】:Tensorflow GPU utilization only 60% (GTX 1070) 【发布时间】:2017-03-05 05:42:17 【问题描述】:

我正在使用 TensorFlow 训练 CNN 模型。我只实现了 60% (+- 2-3%) 的 GPU 利用率,而没有大幅下降。

Sun Oct 23 11:34:26 2016       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 367.57                 Driver Version: 367.57                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 1070    Off  | 0000:01:00.0     Off |                  N/A |
|  1%   53C    P2    90W / 170W |   7823MiB /  8113MiB |     60%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID  Type  Process name                               Usage      |
|=============================================================================|
|    0      3644    C   /usr/bin/python2.7                            7821MiB |
+-----------------------------------------------------------------------------+

因为它是 Pascal 卡,所以我使用 CUDA 8 和 cudnn 5.1.5 CPU使用率在50%左右(均匀分布在8个线程上。i7 4770k),所以CPU性能应该不是瓶颈。

我正在使用 Tensorflow 的二进制文件格式并使用 tf.TFRecordReader() 读取

我正在创建这样的批量图像:

#Uses tf.TFRecordReader() to read single Example
label, image = read_and_decode_single_example(filename_queue=filename_queue) 
image = tf.image.decode_jpeg(image.values[0], channels=3)
jpeg = tf.cast(image, tf.float32) / 255.
jpeg.set_shape([66,200,3])
images_batch, labels_batch = tf.train.shuffle_batch(
    [jpeg, label], batch_size= FLAGS.batch_size,
    num_threads=8,
    capacity=2000, #tried bigger values here, does not change the performance
    min_after_dequeue=1000) #here too

这是我的训练循环:

sess = tf.Session()

sess.run(init)
tf.train.start_queue_runners(sess=sess)
for step in xrange(FLAGS.max_steps):
    labels, images = sess.run([labels_batch, images_batch])
    feed_dict = images_placeholder: images, labels_placeholder: labels
    _, loss_value = sess.run([train_op, loss],
                                 feed_dict=feed_dict)

我对 tensorflow 没有太多经验,而且我现在不知道瓶颈可能在哪里。如果您需要更多代码 sn-ps 来帮助识别问题,我会提供。

更新:带宽测试结果

==5172== NVPROF is profiling process 5172, command: ./bandwidthtest

Device: GeForce GTX 1070
Transfer size (MB): 3960

Pageable transfers
  Host to Device bandwidth (GB/s): 7.066359
  Device to Host bandwidth (GB/s): 6.850315

Pinned transfers
  Host to Device bandwidth (GB/s): 12.038037
  Device to Host bandwidth (GB/s): 12.683915

==5172== Profiling application: ./bandwidthtest
==5172== Profiling result:
Time(%)      Time     Calls       Avg       Min       Max  Name
 50.03%  933.34ms         2  466.67ms  327.33ms  606.01ms  [CUDA memcpy DtoH]
 49.97%  932.32ms         2  466.16ms  344.89ms  587.42ms  [CUDA memcpy HtoD]

==5172== API calls:
Time(%)      Time     Calls       Avg       Min       Max  Name
 46.60%  1.86597s         4  466.49ms  327.36ms  606.15ms  cudaMemcpy
 35.43%  1.41863s         2  709.31ms  632.94ms  785.69ms  cudaMallocHost
 17.89%  716.33ms         2  358.17ms  346.14ms  370.19ms  cudaFreeHost
  0.04%  1.5572ms         1  1.5572ms  1.5572ms  1.5572ms  cudaMalloc
  0.02%  708.41us         1  708.41us  708.41us  708.41us  cudaFree
  0.01%  203.58us         1  203.58us  203.58us  203.58us  cudaGetDeviceProperties
  0.00%  187.55us         1  187.55us  187.55us  187.55us  cuDeviceTotalMem
  0.00%  162.41us        91  1.7840us     105ns  61.874us  cuDeviceGetAttribute
  0.00%  79.979us         4  19.994us  1.9580us  73.537us  cudaEventSynchronize
  0.00%  77.074us         8  9.6340us  1.5860us  28.925us  cudaEventRecord
  0.00%  19.282us         1  19.282us  19.282us  19.282us  cuDeviceGetName
  0.00%  17.891us         4  4.4720us     629ns  8.6080us  cudaEventDestroy
  0.00%  16.348us         4  4.0870us     818ns  8.8600us  cudaEventCreate
  0.00%  7.3070us         4  1.8260us  1.7040us  2.0680us  cudaEventElapsedTime
  0.00%  1.6670us         3     555ns     128ns  1.2720us  cuDeviceGetCount
  0.00%     813ns         3     271ns     142ns     439ns  cuDeviceGet

【问题讨论】:

首先 - 你的 batch 有多大?你的模型有多大?您能否尝试构建更大的 CNN(并在单个批次中推送更多数据)以查看问题是否出在 CPU 和 GPU 之间的同步上? @lejlot 他已经把 GPU 内存用完了 @FranckDernoncourt 如果您不进行配置,Tensorflow 总是会尽可能多地获取 GPU 内存。 @lejlot 我的批次是 32,图像为 200x66x3 如果我没有搞砸计算,那就是 5 Mb!但是我也尝试了 128 批,但这并没有改变任何东西!!模型大小有点难以计算……我有 5 个卷积层和 3 个全连接层…… @andre_bauer 谢谢,我不知道。 【参考方案1】:

在获得更多 tensorflow 经验后,我意识到 GPU 的使用在很大程度上取决于网络大小、批处理大小和预处理。使用具有更多卷积层的更大网络(例如 Resnet 样式)会增加 GPU 使用率,因为涉及更多计算并且通过传输数据等产生的开销(相对于计算)更少。

【讨论】:

这是正确的。尝试使用网络层、类型、批量大小,甚至浮点精度都会导致不同的 GPU 使用历史。【参考方案2】:

一个潜在的瓶颈是在将图像加载到 GPU 时 CPU 和 GPU 之间的 PCI Express 总线使用情况。你可以使用一些tools to measure it。

另一个潜在的瓶颈是磁盘 IO,我在您的代码中看不到任何会导致它的东西,但密切关注它总是一个好主意。

【讨论】:

检查磁盘 IO 瓶颈的最佳方法是什么?我使用的是 SSD,数据是二进制文件。如果这就是瓶颈,我认为没有办法改进:/ @andre_bauer 我在 Linux 上使用 iotop 我获得了 1.7 GB(目前)的训练数据,磁盘完全空闲,因为我认为everythink 都在 RAM 中(32Gb,因此还有空间容纳更多训练数据!) 我更新了我的问题并添加了带宽测试结果。我觉得他们看起来很正常,对吧? @andre_bauer 是的。可惜我们没有一个程序来监控 Linux 上的 PCI Express 总线使用情况。

以上是关于TensorFlow GPU 利用率仅为 60% (GTX 1070)的主要内容,如果未能解决你的问题,请参考以下文章

为啥tensorflow训练用GPU比CPU更慢了

在 TensorFlow 中打印 GPU 和 CPU 使用率

Tensorflow不使用nvidia gpu,而是CPU利用率为100%

tensorflow版本的bert模型 GPU的占用率为100%而其利用率为0%

TensorFlow如何提高GPU训练效率和利用率

使用 Keras 和 Tensorflow 降低 NVIDIA GPU 使用率