2017-02-07 31 views
6

У меня возникли трудности с пониманием того, почему скорости GPU и CPU аналогичны сетям небольшого размера (иногда процессор быстрее), а GPU работает быстрее с сетей большего размера. Код в нижней части вопроса запускается в 103,7 с на i7-6700k, но при использовании функции tensorflow-gpu код запускается через 29,5 секунд.Keras (бэкэнд Tensorflow) медленнее на GPU, чем на CPU при обучении определенным сетям

Однако, когда я тренирую сеть с 100 скрытыми нейронами, вместо 1000, как в примере ниже, я получаю ~ 20 секунд при использовании графического процессора и ~ 15 секунд при использовании CPU.

Я прочитал в другом переполнении стека ответ, что передача 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

Какой графический процессор вы используете? Обратите внимание, что для полного насыщения графического процессора с верхней строкой требуется десятки тысяч потоков. Предполагая, что каждый поток обрабатывает вычисление одного нейрона, система с 100 нейронами будет недоиспользовать GPU. И наоборот, если бы вы увеличили количество нейронов до, скажем, 10K, то относительное преимущество GPU и процессора, скорее всего, увеличится. – njuffa

+0

Упс, полностью забыл включить это в ответ. У меня GTX 1070. И я вижу. Это имеет смысл –

+0

Я действительно заметил такое же поведение на своем GPU GTX 1070. Я не вижу разницы между запуском моей модели (которая имеет аналогичные размеры с той, которую вы используете) на CPU (i7-7700) и графическом процессоре. Необходимо попытаться увеличить пропускную способность сети, чтобы оценить разницу – mspadaccino

ответ

1

В случае крошечных сетевых сборов загрузка может быть преступником здесь.

Keras загружает каждую микросхему с RAM на GPU в начале каждой итерации, тем самым создавая узкое место в крошечных сетях (где вычисления вперед/назад очень быстрые).
Вы можете попробовать использовать model.fit_generator вместо обычного fit, так что процессорный поток, который загружает мини-отсеки, работает параллельно.

К сожалению, нет никакого способа, я знаю, чтобы поджать весь набор данных на GPU для Keras (см my issue)

Если вы используете Tensorflow бэкенд, вы можете использовать Google Timeline средства профилирования, чтобы увидеть, что вызывает замедления. Для справки см. this issue