Tensorflow Keras显示GPU没有提高训练速度(部分使用GPU?!)

Tensorflow Keras显示GPU没有提高训练速度(部分使用GPU?!),tensorflow,keras,Tensorflow,Keras,我试图在GPU上训练我的模型,而不是在Jupyter笔记本的AWS p2.xlarge实例上训练CPU。我使用的是tensorflow gpu后端(仅安装了tensorflow gpu,并在requirements.txt中提及,而不是tensorflow) 与使用CPU相比,在这些实例上训练模型时,我没有看到任何速度的提高,事实上,我每个历元的训练速度几乎与我在4核笔记本电脑CPU上的训练速度相同(p2.xlarge也有4个带有特斯拉K80 GPU的VCPU)。我不确定是否需要对代码进行一些更

我试图在GPU上训练我的模型,而不是在Jupyter笔记本的AWS p2.xlarge实例上训练CPU。我使用的是tensorflow gpu后端(仅安装了
tensorflow gpu
,并在
requirements.txt
中提及,而不是
tensorflow

与使用CPU相比,在这些实例上训练模型时,我没有看到任何速度的提高,事实上,我每个历元的训练速度几乎与我在4核笔记本电脑CPU上的训练速度相同(p2.xlarge也有4个带有特斯拉K80 GPU的VCPU)。我不确定是否需要对代码进行一些更改,以适应GPU提供的更快/并行处理。我正在为我的模型粘贴以下代码:

model = Sequential()
model.add(recurrent.LSTM(64, input_shape=(X_np.shape[1], X_np.shape[2]),
                        return_sequences=True))
model.add(recurrent.LSTM(64, return_sequences = False))
model.add(core.Dropout(0.1))
model.add(core.Dense(3, activation='softmax'))
model.compile(loss = 'categorical_crossentropy', optimizer = 'rmsprop', metrics=['accuracy'])

model.fit(X_np, y_np, epochs=100, validation_split=0.25)
同样有趣的是,每次我使用nvidia smi检查GPU状态时,GPU似乎都在利用其50%-60%的处理能力和几乎所有的内存(但在不训练时,两者分别下降到0%和1MiB):

另外,如果您想查看我在Jupyter笔记本上关于使用GPU的日志:

[I 04:21:59.390 NotebookApp] Kernel started: c17bc4d1-fa15-4b0e-b5f0-87f90e56bf65
[I 04:22:02.241 NotebookApp] Adapting to protocol v5.1 for kernel c17bc4d1-fa15-4b0e-b5f0-87f90e56bf65
2017-11-30 04:22:32.403981: I tensorflow/core/platform/cpu_feature_guard.cc:137] Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.1 SSE4.2 AVX AVX2 FMA
2017-11-30 04:22:33.653681: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:892] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2017-11-30 04:22:33.654041: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1030] Found device 0 with properties:
name: Tesla K80 major: 3 minor: 7 memoryClockRate(GHz): 0.8235
pciBusID: 0000:00:1e.0
totalMemory: 11.17GiB freeMemory: 11.10GiB
2017-11-30 04:22:33.654070: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1120] Creating TensorFlow device (/device:GPU:0) -> (device: 0, name: Tesla K80, pci bus id: 0000:00:1e.0, compute capability: 3.7)
2017-11-30 04:22:34.014329: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1120] Creating TensorFlow device (/device:GPU:0) -> (device: 0, name: Tesla K80, pci bus id: 0000:00:1e.0, compute capability: 3.7)
Device mapping:
/job:localhost/replica:0/task:0/device:GPU:0 -> device: 0, name: Tesla K80, pci bus id: 0000:00:1e.0, compute capability: 3.7
2017-11-30 04:22:34.015339: I tensorflow/core/common_runtime/direct_session.cc:299] Device mapping:
/job:localhost/replica:0/task:0/device:GPU:0 -> device: 0, name: Tesla K80, pci bus id: 0000:00:1e.0, compute capability: 3.7

2017-11-30 04:23:22.426895: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1120] Creating TensorFlow device (/device:GPU:0) -> (device: 0, name: Tesla K80, pci bus id: 0000:00:1e.0, compute capability: 3.7)

请说明可能存在的问题。无论如何,非常感谢你看这个

尝试在
model.fit
中为
批量大小使用更大的值,因为默认值为
32
。增加它,直到您获得100%的CPU利用率


根据@dgumo的建议,您还可以将数据放入
/run/shm
。这是一个内存文件系统,允许以最快的方式访问数据。或者,您可以确保数据至少驻留在SSD上。例如,在
/tmp

中,由于使用的是LSTM层,所以会发生这种情况

Tensorflow对LSTM层的实现并没有那么好。原因可能是经常性计算不是并行计算,而GPU非常适合并行处理

我根据自己的经验证实:

  • 在我的模型中使用LSTM速度非常快
  • 决定测试去除所有LSTM的模型(得到一个纯卷积模型)
  • 由此产生的速度简直惊人
这篇关于使用GPU和tensorflow的文章还确认:

可能的解决方案? 您可以尝试使用新的,这似乎是专门为使用GPU准备的

我从未测试过它,但您很可能会用它获得更好的性能


另一件我还没有测试过的东西,我不确定它是出于这个原因设计的,但我怀疑它是:您可以在LSTM层中放置
unroll=True
。有了这些,我怀疑重复的计算将在并行计算中进行转换。

您案例中的瓶颈是在GPU之间传输数据。加速计算(并最大限度地提高GPU使用率)的最佳方法是一次加载内存所能容纳的数据量。由于您有足够的内存,您可以通过以下操作一次放置所有数据:

model.fit(X_np, y_np, epochs=100, validation_split=0.25, batch_size=X_np.shape[0])
(执行此操作时,您可能还应该增加纪元的数量)


但是注意到小型化的优点(例如更好地处理局部极小值),所以你应该考虑在两者之间选择一个批量大小。

你也可以发布你的CPU使用情况吗?您的瓶颈可能是将数据输入到模型中的部分。数据集的大小(X_np和y_np的形状)是多少?@AbderrahimKitouni 34000x7x5(示例X时间步X功能),输入和目标为34000x1。LSTM的训练速度很慢,但是增加批量大小应该会有很大帮助。您还可以尝试其他类型的重复层,比如GRU或新发布的我已经有一段时间没有查看keras文档了,并且在10月份添加了cudnn层。我对我的数据做了一次试驾,发现每个历元的训练量减少到了三分之一,而没有做任何其他改变。我会在一两天内进一步了解这一点。
model.fit(X_np, y_np, epochs=100, validation_split=0.25, batch_size=X_np.shape[0])