Вывод линейной модели по тензорному потоку на 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 для оптимизации вашего графика, хотя для вашей конкретной модели нет никаких гарантий, что он работает намного лучше.

Другие вопросы по тегам