训练某些网络时,GPU 上的 Keras(Tensorflow 后端)比 CPU 上慢

Posted

技术标签:

【中文标题】训练某些网络时,GPU 上的 Keras(Tensorflow 后端)比 CPU 上慢【英文标题】:Keras (Tensorflow backend) slower on GPU than on CPU when training certain networks 【发布时间】:2017-06-25 03:01:34 【问题描述】:

我很难理解为什么 GPU 和 CPU 速度与小型网络相似(CPU 有时更快),而 GPU 在大型网络中更快。问题底部的代码在 i7-6700k 上运行时间为 103.7 秒,但使用 tensorflow-gpu 时,代码运行时间为 29.5 秒。

但是,当我训练一个包含 100 个隐藏神经元(而不是下面示例中的 1000 个)的网络时,使用 GPU 时大约需要 20 秒,使用 CPU 时大约需要 15 秒。

我在另一个堆栈溢出答案中读到 CPU->GPU 传输需要很长时间,我假设这是指在 GPU 上加载数据示例。

有人可以解释为什么会发生这种情况,并可能参考我可以对代码进行的一些更改以最大限度地提高速度吗?

import numpy as np
import tensorflow as tf
import keras
from keras.models import Sequential
from keras.utils import np_utils
from keras.layers.core import Dense, Activation, Flatten, Dropout
from sklearn.preprocessing import normalize

## Importing the MNIST dataset using Keras
from keras.datasets import mnist
(X_train, y_train), (X_test, y_test) = mnist.load_data()

# reshape for vector input
N, x, y = X_train.shape
X_train = normalize(np.reshape(X_train, (N, x * y)))

N, x, y = X_test.shape
X_test = normalize(np.reshape(X_test, (N, x * y)))

# one-hot encoding
y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)

model = Sequential()
model.add(Dense(output_dim=750, input_dim=784))
model.add(Activation('relu'))
model.add(Dropout(0.2))

model.add(Dense(150))
model.add(Activation('relu'))
model.add(Dropout(0.2))

model.add(Dense(50))
model.add(Activation('relu'))
model.add(Dropout(0.2))

model.add(Dense(50))
model.add(Activation('relu'))
model.add(Dropout(0.2))

model.add(Dense(10))
model.add(Activation('softmax'))

model.compile(loss='categorical_crossentropy', optimizer='Nadam', metrics=['accuracy'])

fit = model.fit(X_train, y_train, batch_size=128, nb_epoch=10, verbose=0)

## Printing the accuracy of our model, according to the loss function specified in model.compile above
score = model.evaluate(X_test, y_test, verbose=0)
print('Test score:', score[0])
print('Test accuracy:', score[1])

【问题讨论】:

您使用的是什么 GPU?请注意,要使*** GPU 完全饱和需要数万个线程。假设每个线程处理一个神经元的计算,一个有 100 个神经元的系统将没有充分利用 GPU。相反,如果您将神经元的数量增加到 10K,则 GPU 相对于 CPU 的相对优势可能会进一步增加。 哎呀,完全忘了在答案中包含它。我有一个 GTX 1070。我明白了。这是有道理的 我实际上在我的 GTX 1070 GPU 上注意到了同样的行为。我看不出在 CPU (i7-7700) 和 GPU 上运行我的模型(与您使用的模型具有相似的尺寸)之间有任何区别。需要尝试增加网络的容量来评估差异 【参考方案1】:

在小型网络的情况下,批量加载可能是这里的罪魁祸首。

Keras 在每次迭代开始时将每个 minibatch 从 RAM 加载到 GPU,从而在微型网络中造成瓶颈(前向/后向计算非常快)。 您可以尝试使用model.fit_generator 而不是普通的fit,以便加载小批量的CPU 线程并行工作。

不幸的是,我不知道要在 GPU 上为 Keras 预加载整个数据集(请参阅 my issue)

如果您使用的是 Tensorflow 后端,则可以使用 Google 时间轴分析工具来查看导致速度变慢的原因。参考见this issue

【讨论】:

谢谢,批量加载对我来说是个问题。现在它运行得更快了。 你能解释一下如何按照你的描述做一个好的生成器吗? 不确定我理解你所说的好是什么意思,有几个例子可以用谷歌搜索,比如:kaggle.com/ezietsman/simple-keras-model-with-data-generator 值得一提的是,GPU 上的性能缓慢有时可以通过使用 cudnn 层来解决,请参阅这个问题:***.com/questions/41948406/…

以上是关于训练某些网络时,GPU 上的 Keras(Tensorflow 后端)比 CPU 上慢的主要内容,如果未能解决你的问题,请参考以下文章

如何确保 Keras 使用 GPU 和 tensorflow 后端?

使用 tf.keras 模型训练时 GPU 随机冻结

keras-gpu的安装与配置

使用 GPU 在 EC2 实例上训练 Keras 模型很慢

具有Tensorflow后端的Keras - 运行在CPU上预测但适合GPU

小白学习keras教程九keras 使用GPU和Callbacks模型保存