Я тренирую модель разреженной логистической регрессии на тензорном потоке. Эта проблема конкретно о выводной части. Я пытаюсь сделать вывод о производительности на процессорах и графических процессорах. Я использую графический процессор 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) издержки вызова ядра на процессоре vs gpu (я предполагаю, что каждый вызов sess.run вызывает 1 вызов ядра, верно?
мои текущие результаты:
Процессор:
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 только во время вывода, чтобы получить лучшую производительность?
Идеи вокруг квантования или оптимизации графа вывода?
Есть еще идеи по улучшению вывода на основе графического процессора. Может быть, оптимизация на основе xla или тензор? Я хочу иметь высокопроизводительный код логического вывода для выполнения этих вычислений на GPU, в то время как сервер приложений работает на CPU.