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

15

我对于GPU和CPU在小型网络中速度相似(有时CPU更快),而在大型网络中GPU更快的原因有些困惑。下面这段代码在i7-6700k上运行需要103.7秒,但是当使用tensorflow-gpu时,这段代码只需29.5秒。

然而,当我训练一个只有100个隐藏神经元的网络时,而不是像下面例子中的1000个,使用GPU可以得到大约20秒的运行时间,而使用CPU则只需15秒。

我在另一个stack overflow的答案中读到,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])

1
你使用的是什么GPU?请注意,要完全饱和一款顶级GPU需要数万个线程。假设每个线程处理一个神经元的计算,一个拥有100个神经元的系统将无法充分利用GPU。相反,如果你将神经元数量增加到比如1万个,GPU相对于CPU的优势可能会进一步增加。 - njuffa
糟糕,完全忘记在答案中包含那个了。我有一张GTX 1070显卡。我明白了,这很有道理。 - Enrico Borba
我在我的GTX 1070 GPU上也注意到了同样的行为。我没有看到在CPU(i7-7700)和GPU上运行我的模型(其尺寸与您使用的相似)之间有任何区别。需要尝试增加网络容量以评估差异。 - mspadaccino
1个回答

14

对于小型网络,批量加载可能是问题的罪魁祸首。

Keras在每次迭代开始时从RAM到GPU加载每个小批量,因此在小型网络中会创建瓶颈(其中正向/反向计算非常快)。
您可以尝试使用model.fit_generator而不是普通的fit,以便负责加载小批量的CPU线程可以并行工作。

不幸的是,据我所知,没有办法将整个数据集预加载到Keras的GPU上(请参见我的问题

如果您正在使用Tensorflow后端,则可以使用Google时间线分析工具查看导致减速的原因。有关参考,请参见这个问题


1
谢谢,批量加载是我的问题。现在它运行得更快了。 - Jonas Sourlier
你能向我解释一下如何像你描述的那样写一个好的生成器吗? - volperossa
1
我不确定你所说的好是什么意思,但是在谷歌上可以搜索到一些例子,比如这个:https://www.kaggle.com/ezietsman/simple-keras-model-with-data-generator - Alexander Serikov
1
值得一提的是,GPU性能缓慢有时可以通过使用cudnn层来解决,参见此问题:https://dev59.com/4lgQ5IYBdhLWcg3w9Yvk - Guy s

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