Вывод линейной модели по тензорному потоку на GPU медленный
Я тренирую модель редкой логистической регрессии на тензорном потоке. Эта проблема конкретно о выводной части. Я пытаюсь сделать вывод о производительности на CPU и GPU. Я использую графический процессор Nvidia P100 (4 матрицы) на моем текущем GCE. Я новичок в GPU, так что извините за наивные вопросы.
Модель довольно большая ~54 тыс. Операций (считается ли она большой по сравнению с моделями dnn или imagenet?) . Когда я регистрирую размещение устройства, я вижу только использование gpu:0, а остальные не используются? Я не делаю никаких устройств во время обучения, но во время вывода я хочу, чтобы он оптимально размещал и использовал gpu. Несколько вещей, которые я заметил: мой входной узел placehoolder (feed_dict) помещен в процессор, поэтому я предполагаю, что мои данные копируются из процессора в gpu? как feed_dict точно работает за сценой?
1) Как я могу разместить свои данные, для которых я хочу запустить прогнозирование непосредственно в GPU? Примечание: мое обучение выполняется на распределенном процессоре с несколькими терабайтами, поэтому я не могу иметь постоянную или переменную непосредственно в моем графике во время обучения, но по моему выводу у меня, безусловно, могут быть небольшие партии данных, которые я бы хотел разместить непосредственно в gpu. Есть ли способы, которыми я могу достичь этого? 2) Поскольку я использую P100 GPU, я думаю, что он имеет объединенную память с хостом, возможно ли иметь zerocopy и напрямую загружать мои данные в GPU? Как я могу сделать это из кода Python, Java и C++. В настоящее время я использую feed_dict, который из различных источников Google, я думаю, не совсем оптимален. 3) Есть ли какой-либо инструмент или профилировщик, который я могу использовать, чтобы увидеть, когда я профиля профиля, как:
for epoch_step in epochs:
start_time = time.time()
for i in range(epoch_step):
result = session.run(output, feed_dict={input_example: records_batch})
end_time = time.time()
print("Batch {} epochs {} :time {}".format(batch_size, epoch_step, str(end_time - start_time)))
сколько времени тратится на 1) передачу данных с процессора на gpu 2) накладные расходы на запуск сеанса 3) использование gpu (в настоящее время я периодически использую nvidia-smi для мониторинга 4) накладные расходы на вызовы ядра на cpu vs gpu (я предполагаю каждый вызов sess.run вызывает 1 вызов ядра, верно?
мои текущие результаты тестирования производительности: CPU:
Batch size : 10
NumberEpochs TimeGPU TimeCPU
10 5.473 0.484
20 11.673 0.963
40 22.716 1.922
100 56.998 4.822
200 113.483 9.773
Batch size : 100
NumberEpochs TimeGPU TimeCPU
10 5.904 0.507
20 11.708 1.004
40 23.046 1.952
100 58.493 4.989
200 118.272 9.912
Batch size : 1000
NumberEpochs TimeGPU TimeCPU
10 5.986 0.653
20 12.020 1.261
40 23.887 2.530
100 59.598 6.312
200 118.561 12.518
Batch size : 10k
NumberEpochs TimeGPU TimeCPU
10 7.542 0.969
20 14.764 1.923
40 29.308 3.838
100 72.588 9.822
200 146.156 19.542
Batch size : 100k
NumberEpochs TimeGPU TimeCPU
10 11.285 9.613
20 22.680 18.652
40 44.065 35.727
100 112.604 86.960
200 225.377 174.652
Batch size : 200k
NumberEpochs TimeGPU TimeCPU
10 19.306 21.587
20 38.918 41.346
40 78.730 81.456
100 191.367 202.523
200 387.704 419.223
Некоторые заметные наблюдения: По мере увеличения размера партии я вижу увеличение использования моего процессора (до 100% для единственного используемого им процессора, есть ли способ, которым я могу сказать, чтобы tf тоже использовал другой процессор) при размере пакета 200 КБ - единственный раз, когда я вижу мой наивный бенчмаркинг показывает, что у gpu есть небольшой выигрыш по сравнению с процессором. Увеличение размера партии для данной эпохи оказывает минимальное влияние на время как процессоров, так и процессоров, пока размер партии <= 10k. Но после этого увеличения размера партии от 10k -> 100k -> 200k время также увеличивается довольно быстро, то есть для данной эпохи, скажем, 10 размер пакета 10, 100, 1k, 10k, время процессора и время процессора остаются довольно стабильными ~5-7 секунд для графического процессора и 0,48-0,96 секунд для процессора (что означает, что sess.run имеет гораздо больше служебных данных, чем вычисление самого графика?), Но при увеличении размера пакета дальнейшее время вычислений увеличивается гораздо быстрее, т.е. для эпохи 10 100k->200k gputime увеличился с 11 до 19 секунд и время процессора также удваивается, почему так? Кажется, для большего размера партии, хотя у меня есть только один sess.run, но внутренне это разделяет это на меньшую партию и вызывает sess.run дважды, потому что размер партии 20k эпохи 20k более близко соответствует эпохе 10 партии 200k ..
Как я могу улучшить мой вывод дальше, я считаю, что я не использую все процессоры оптимально. Есть ли какие-либо идеи относительно того, как я могу лучше тестировать, чтобы получить лучшие разбивки времени для передачи процессора> gpu и фактического ускорения вычислений графов от перехода от процессора к процессору? Загрузка данных лучше напрямую, если это возможно, нулевое копирование в gpu? Могу ли я разместить некоторые узлы в gpu только во время вывода, чтобы получить лучшую производительность? Идеи вокруг квантования или оптимизации графа вывода?
Есть еще идеи по улучшению вывода на основе GPU. Может быть, оптимизация на основе xla или тензор? Я хочу иметь высокопроизводительный код логического вывода для запуска этих вычислений на GPU, в то время как сервер приложений работает на CPU.
1 ответ
Одним из источников информации являются документы TensorFlow по производительности, включая Оптимизацию для графических процессоров и высокопроизводительных моделей.
Тем не менее, эти руководства, как правило, нацелены на обучение больше, чем на групповой вывод, хотя, безусловно, некоторые принципы все еще применяются.
Я отмечу, что, если вы не используете DistributionStrategy, TensorFlow не будет автоматически помещать операции на более чем один графический процессор ( источник).
В вашем конкретном случае я не верю, что графические процессоры еще хорошо настроены для выполнения разреженных операций, требуемых для вашей модели, поэтому я не ожидаю, что это будет хорошо работать на графическом процессоре (если вы регистрируете размещение устройства есть шанс, что поиск выполняется на процессоре). Модель логистической регрессии имеет только (разреженный) входной слой и выходной слой, поэтому, как правило, математических операций очень мало. Графические процессоры превосходят большинство, когда они делают много матричных умножений, сверток и т. Д.
Наконец, я бы посоветовал вам использовать TensorRT для оптимизации вашего графика, хотя для вашей конкретной модели нет никаких гарантий, что он работает намного лучше.