Почему время прогнозирования для выборки в Tensorflow (и Keras) меньше при прогнозировании в пакетах, чем в отдельных выборках? - PullRequest
0 голосов
/ 11 октября 2018

Я использую свою обученную модель для прогнозирования (только для процессора).Я наблюдаю, что как на Tensorflow, так и на Keras с бэкэндом Tensorflow время прогнозирования для выборки намного меньше при использовании серии выборок по сравнению с отдельной выборкой.Более того, время на выборку уменьшается с увеличением размера пакета до пределов, налагаемых памятью.Например, на чистом Tensorflow прогнозирование отдельной выборки занимает ~ 1,5 секунды, на 100 выборках это ~ 17 секунд (на время выборки ~ 0,17 с), на 1000 выборок это ~ 93 секунды (на время выборки ~ 0,093 с)).

Это нормальное поведение?Если так, есть ли интуитивное объяснение этому?Я думаю, это может быть связано с инициализацией графика, но мне нужно кое-что прояснить.Кроме того, почему время выборки уменьшается, когда мы увеличиваем количество выборок для прогноза?В моем случае использования я должен предсказать по отдельным образцам, когда они станут доступны.Так что, очевидно, я бы совсем немного потерял бы в скорости, если бы это так работало.

Заранее спасибо за вашу помощь.

Редактировать: я добавляю минимальный рабочий пример.У меня есть один вход изображения и 4 векторных входа для моей модели, которая производит 4 выхода.Я инициализирую все входы в 0 для проверки скорости (я думаю, что фактические значения не имеют большого значения для скорости?).Время инициализации и время вывода рассчитываются отдельно.Я обнаружил, что время инициализации является частью времени вывода (~ 0,1 с для 100 выборок).

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import time
import numpy as np
import tensorflow as tf

t00=time.time()
graph = tf.Graph()
graph_def = tf.GraphDef()

with open("output_graph.pb", "rb") as f:
    graph_def.ParseFromString(f.read())
with graph.as_default():
    tf.import_graph_def(graph_def)

# One image and 4 auxiliary scalar inputs
img_input_layer ="input"
qp4_input_layer ="qp4"
qp3_input_layer ="qp3"
qp2_input_layer ="qp2"
qp1_input_layer ="qp1"
input_name = "import/" + img_input_layer
qp4_input_name = "import/" + qp4_input_layer
qp3_input_name = "import/" + qp3_input_layer
qp2_input_name = "import/" + qp2_input_layer
qp1_input_name = "import/" + qp1_input_layer



input_operation_img = graph.get_operation_by_name(input_name)
input_operation_qp4 = graph.get_operation_by_name(qp4_input_name)
input_operation_qp3 = graph.get_operation_by_name(qp3_input_name)
input_operation_qp2 = graph.get_operation_by_name(qp2_input_name)
input_operation_qp1 = graph.get_operation_by_name(qp1_input_name)

output_operation=[]

for i in range(4):
    output_operation.append(graph.get_operation_by_name("import/" + "output_"+str(i)).outputs)

#Initializing dummy inputs
n=100 # Number of samples for inference
img=np.zeros([n,64, 64,1])
qp4=np.zeros([n,1, 1,1])
qp3=np.zeros([n,2, 2,1])
qp2=np.zeros([n,4, 4,1])
qp1=np.zeros([n,8, 8,1])
t01=time.time()
print("Iniialization time",t01-t00)

t0=time.time()
with tf.Session(graph=graph) as sess:
    results = sess.run(output_operation,
                       {input_operation_img.outputs[0]: img, input_operation_qp4.outputs[0]: qp4, input_operation_qp3.outputs[0]: qp3,  input_operation_qp2.outputs[0]: qp2,  input_operation_qp1.outputs[0]: qp1})

    # print(results)
t1 = time.time()
print("Inference time", t1-t0)

Ответы [ 2 ]

0 голосов
/ 11 октября 2018

Это очень сильно зависит от инструментария модели, метода развертывания и интерфейса - ничего из того, что вы предоставили или даже не описали.В моей практике общие причины включают в себя:

  • Время инициализации модели: вы как-то "пробуждаете" модель для каждой партии?Если, как вы предложили, вы повторно инициализируете модель для каждого запроса, то я несколько удивлен, что накладные расходы не составляют большую часть вашего времени.
  • Затраты интерфейса: как добраться до образцов/ из модели?Это в HTTP-запросе, где вы испытываете затраты на коммуникацию за запрос, а не за образец?
  • Простое время ввода-вывода модели: если ваша модель считывает весь пакет за раз, тогда время задержки для открытия иДоступ к входному каналу может быть основным фактором задержки.

У вас есть работа, чтобы диагностировать первопричины.Пока у вас есть только три точки данных;Я рекомендую собрать еще несколько.Что вы можете вписать в график времени?Есть ли какие-то скачки, которые предполагают системное ограничение, например размер входного буфера?Можете ли вы оснастить свою модель каким-либо профилирующим кодом, чтобы выяснить, какие лаги в вашей модели, а какие - в издержках системы?

Попробуйте развернуть вашу модель как сервис;что происходит со временем, когда оно уже загружено в память, инициализировано и просто ожидает следующего ввода?Какое время задержки у вас в интерфейсе запроса?

Результаты этих исследований покажут вам, где вы можете получить выгоду от изменения дизайна в вашей модели использования.

0 голосов
/ 11 октября 2018

Да, это совершенно нормально.Это происходит потому, что, как вы делаете вывод на GPU (или даже на многоядерные процессоры), увеличение размера пакета позволяет лучше использовать ресурсы параллельных вычислений на GPU, уменьшая время на выборку в пакете.Если вы используете небольшой размер пакета, то вы тратите впустую вычислительные ресурсы, доступные в графическом процессоре.

В этом документе описан тот же эффект, а на одной из рисунков представлен график, на котором показановремя вывода на изображение в зависимости от размера пакета.Он показывает тот же эффект, что и вы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...