web-dev-qa-db-fra.com

Keras (backend Tensorflow) plus lent sur le GPU que sur le CPU lors de la formation de certains réseaux

J'ai du mal à comprendre exactement pourquoi les vitesses du GPU et du CPU sont similaires avec des réseaux de petite taille (le CPU est parfois plus rapide), et le GPU est plus rapide avec des réseaux de plus grande taille. Le code au bas de la question s'exécute en 103,7 s sur un i7-6700k, mais lors de l'utilisation de tensorflow-gpu, le code s'exécute en 29,5 secondes.

Cependant, lorsque j'entraîne un réseau qui a 100 neurones cachés, au lieu de 1000 comme dans l'exemple ci-dessous, j'obtiens ~ 20 secondes lorsque j'utilise le GPU, et ~ 15 secondes lorsque j'utilise le CPU.

J'ai lu sur une autre réponse de débordement de pile que les transferts CPU-> GPU prennent beaucoup de temps, je suppose que cela fait référence au chargement des exemples de données sur le GPU.

Quelqu'un peut-il expliquer pourquoi cela se produit et éventuellement référencer certains changements dans le code que je peux faire pour maximiser la vitesse?

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])
13
Enrico Borba

En cas de réseaux minuscules, le chargement par lots peut être le coupable ici.

Keras charge chaque mini-lot de RAM vers le GPU au début de chaque itération, créant ainsi un goulot d'étranglement dans les réseaux minuscules (où le calcul avant/arrière est très rapide).
Vous pouvez essayer d'utiliser model.fit_generator au lieu de plain fit, de sorte que le thread CPU qui charge les minibatches fonctionne en parallèle.

Malheureusement, je n'ai aucun moyen de précharger l'ensemble de données sur GPU pour Keras (voir mon problème )

Si vous utilisez le backend Tensorflow, vous pouvez utiliser l'outil de profilage Google Timeline pour voir les causes des ralentissements. Pour la référence, voir ce problème

8
Alex Serikov