Понимание, почему EagerTensor. numpy () работает медленно - PullRequest
1 голос
/ 24 января 2020

Я пытаюсь делать прогнозы, используя предварительно обученную пользовательскую модель сегментации изображений для некоторых данных изображений, но у меня возникают проблемы с слишком медленными прогнозами. После некоторого профилирования с использованием Pyinstrument я обнаружил, что вызов numpy() - это то, что занимает большую часть времени выполнения. Это удивило меня, так как, насколько я понимаю, все функции, которые нужно сделать, это скопировать прогнозные данные из графического процессора обратно на хост и, возможно, сделать некоторые другие вещи, чтобы преобразовать данные в numpy -матрицу.

Я создал минимальный рабочий пример, который показывает эффект:

import numpy as np
import tensorflow as tf
from pyinstrument import Profiler

model = tf.keras.applications.resnet50.ResNet50(include_top=False, input_shape=(672, 2048, 3))
data = np.zeros((1, 672, 2048, 3))

profiler = Profiler()
profiler.start()

for _ in range(1000):
    prediction = model.predict_on_batch(data)
    output = prediction.numpy()

profiler.stop()
print(profiler.output_text())

Код производит следующий вывод Pyinstrument:

  _     ._   __/__   _ _  _  _ _/_   Recorded: 15:50:54  Samples:  6759
 /_//_/// /_\ / //_// / //_'/ //     Duration: 56.536    CPU time: 56.406
/   _/                      v3.1.0

Program: test.py

56.536 <module>  test.py:1
|- 42.315 numpy  tensorflow_core\python\framework\ops.py:918
|     [4 frames hidden]  tensorflow_core
|        39.179 _numpy  tensorflow_core\python\framework\ops.py:905
|- 12.667 predict_on_batch  tensorflow_core\python\keras\engine\training.py:1220
|     [7705 frames hidden]  tensorflow_core, ast, _weakrefset, we...
`- 1.553 [self]

Я использую Tensorflow 2.1.0 на RTX 2080 Ti , Эффект еще более выражен при использовании моей собственной модели, и в этом случае вызов numpy() занимает более 90% времени работы.

Я также пытался использовать output = np.array(memoryview(prediction)), как упоминалось в этот комментарий но без существенной разницы в производительности.

Может кто-нибудь объяснить, почему это происходит? Это ожидаемое поведение? Является ли вывод не полностью готовым сразу после вызова predict_on_batch(), поэтому numpy() должен ждать готовности вывода, прежде чем создавать массив из него?

Обновление: By добавив time.sleep(0.1) между вызовами к predict_on_batch() и numpy() в примере кода, я получаю вместо этого вывод:

  _     ._   __/__   _ _  _  _ _/_   Recorded: 12:03:52  Samples:  7821
 /_//_/// /_\ / //_// / //_'/ //     Duration: 135.388   CPU time: 25.641
/   _/                      v3.1.0

Program: test.py

135.388 <module>  test.py:1
|- 105.639 [self]
|- 16.191 numpy  tensorflow_core\python\framework\ops.py:918
|     [4 frames hidden]  tensorflow_core
`- 13.558 predict_on_batch  tensorflow_core\python\keras\engine\training.py:1220
      [7839 frames hidden]  tensorflow_core, ast, _weakrefset, we...

Как вы можете видеть, время для predict_on_batch() все еще приблизительно то же самое, но, немного подождав, время, потраченное на numpy(), значительно сокращается. Мне кажется, это указывает на мою теорию о том, что при достижении numpy() вывод не полностью готов, поэтому ему нужно немного подождать, прежде чем он сможет создать массив. Я все еще не совсем удовлетворен, может ли кто-то пролить свет на ситуацию? Что-нибудь можно сделать, чтобы улучшить производительность?

...