TensorFlow Profiler: wydajność modelu profilu

Zobacz na TensorFlow.org Uruchom w Google Colab Wyświetl źródło na GitHub Pobierz notatnik

Przegląd

Algorytmy uczenia maszynowego są zazwyczaj drogie obliczeniowo. Dlatego ważne jest, aby określić ilościowo wydajność aplikacji uczenia maszynowego, aby upewnić się, że korzystasz z najbardziej zoptymalizowanej wersji swojego modelu. Użyj TensorFlow Profiler, aby sprofilować wykonanie kodu TensorFlow.

Ustawiać

from datetime import datetime
from packaging import version

import os

TensorFlow Profiler wymaga najnowsze wersje TensorFlow i TensorBoard ( >=2.2 ).

pip install -U tensorboard_plugin_profile
import tensorflow as tf

print("TensorFlow version: ", tf.__version__)
TensorFlow version:  2.2.0-dev20200405

Upewnij się, że TensorFlow może uzyskać dostęp do GPU.

device_name = tf.test.gpu_device_name()
if not device_name:
  raise SystemError('GPU device not found')
print('Found GPU at: {}'.format(device_name))
Found GPU at: /device:GPU:0

Trenuj model klasyfikacji obrazów za pomocą wywołań zwrotnych TensorBoard

W tym samouczku zbadać możliwości w TensorFlow Profiler przez uchwycenie profil wydajności uzyskany poprzez szkolenie model do klasyfikacji obrazów w zbiorze MNIST .

Użyj zestawów danych TensorFlow, aby zaimportować dane uczące i podzielić je na zestawy uczące i testowe.

import tensorflow_datasets as tfds
tfds.disable_progress_bar()
(ds_train, ds_test), ds_info = tfds.load(
    'mnist',
    split=['train', 'test'],
    shuffle_files=True,
    as_supervised=True,
    with_info=True,
)
WARNING:absl:Dataset mnist is hosted on GCS. It will automatically be downloaded to your
local data directory. If you'd instead prefer to read directly from our public
GCS bucket (recommended if you're running on GCP), you can instead set
data_dir=gs://tfds-data/datasets.
Downloading and preparing dataset mnist/3.0.0 (download: 11.06 MiB, generated: Unknown size, total: 11.06 MiB) to /root/tensorflow_datasets/mnist/3.0.0...
Dataset mnist downloaded and prepared to /root/tensorflow_datasets/mnist/3.0.0. Subsequent calls will reuse this data.

Wstępnie przetwórz dane treningowe i testowe, normalizując wartości pikseli w zakresie od 0 do 1.

def normalize_img(image, label):
  """Normalizes images: `uint8` -> `float32`."""
  return tf.cast(image, tf.float32) / 255., label

ds_train = ds_train.map(normalize_img)
ds_train = ds_train.batch(128)
ds_test = ds_test.map(normalize_img)
ds_test = ds_test.batch(128)

Utwórz model klasyfikacji obrazów za pomocą Keras.

model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28, 1)),
  tf.keras.layers.Dense(128,activation='relu'),
  tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(
    loss='sparse_categorical_crossentropy',
    optimizer=tf.keras.optimizers.Adam(0.001),
    metrics=['accuracy']
)

Utwórz wywołanie zwrotne TensorBoard, aby przechwycić profile wydajności i wywołaj je podczas trenowania modelu.

# Create a TensorBoard callback
logs = "logs/" + datetime.now().strftime("%Y%m%d-%H%M%S")

tboard_callback = tf.keras.callbacks.TensorBoard(log_dir = logs,
                                                 histogram_freq = 1,
                                                 profile_batch = '500,520')

model.fit(ds_train,
          epochs=2,
          validation_data=ds_test,
          callbacks = [tboard_callback])
Epoch 1/2
469/469 [==============================] - 11s 22ms/step - loss: 0.3684 - accuracy: 0.8981 - val_loss: 0.1971 - val_accuracy: 0.9436
Epoch 2/2
 50/469 [==>...........................] - ETA: 9s - loss: 0.2014 - accuracy: 0.9439WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/summary_ops_v2.py:1271: stop (from tensorflow.python.eager.profiler) is deprecated and will be removed after 2020-07-01.
Instructions for updating:
use `tf.profiler.experimental.stop` instead.
WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/summary_ops_v2.py:1271: stop (from tensorflow.python.eager.profiler) is deprecated and will be removed after 2020-07-01.
Instructions for updating:
use `tf.profiler.experimental.stop` instead.
469/469 [==============================] - 11s 24ms/step - loss: 0.1685 - accuracy: 0.9525 - val_loss: 0.1376 - val_accuracy: 0.9595
<tensorflow.python.keras.callbacks.History at 0x7f23919a6a58>

Użyj narzędzia TensorFlow Profiler do profilowania wydajności uczenia modelu

TensorFlow Profiler jest wbudowany w TensorBoard. Załaduj TensorBoard za pomocą magii Colab i uruchom go. Przeglądać profile wydajności przechodząc do zakładki Profil.

# Load the TensorBoard notebook extension.
%load_ext tensorboard

Profil wydajności tego modelu jest podobny do poniższego obrazu.

# Launch TensorBoard and navigate to the Profile tab to view performance profile
%tensorboard --logdir=logs
<IPython.core.display.Javascript object>

Zakładka Profile otwiera stronę, która pokazuje podsumowanie wysokiego poziomu skuteczności modelu przeglądania. Patrząc na wykres krokowy po prawej stronie, można zauważyć, że model jest silnie powiązany z danymi wejściowymi (tj. spędza dużo czasu w linii wprowadzania danych). Strona Przegląd zawiera również zalecenia dotyczące potencjalnych dalszych kroków, które można wykonać, aby zoptymalizować wydajność modelu.

Aby zrozumieć, gdzie pojawia się wąskim gardłem wydajności w rurociągu wejściowym wybierz Trace Viewer z Narzędzi rozwijanej po lewej stronie. Przeglądarka śledzenia pokazuje oś czasu różnych zdarzeń, które wystąpiły na procesorze i procesorze graficznym w okresie profilowania.

Przeglądarka śledzenia pokazuje wiele grup zdarzeń na osi pionowej. Każda grupa zdarzeń ma wiele ścieżek poziomych wypełnionych zdarzeniami śledzenia. Ścieżka to oś czasu zdarzenia dla zdarzeń wykonywanych w wątku lub strumieniu GPU. Poszczególne wydarzenia to kolorowe, prostokątne bloki na ścieżkach osi czasu. Czas płynie od lewej do prawej. Nawigacja zdarzeń śledzenia za pomocą skrótów klawiaturowych W (zoom in), S (pomniejszyć), (przewijania z lewej) i A D (przewijania w prawo).

Pojedynczy prostokąt reprezentuje zdarzenie śledzenia. Wybierz ikonę kursorem myszy na pływającym pasku narzędzi (lub użyj skrótu klawiaturowego 1 ) i kliknij zdarzenie śledzenia, aby je analizować. Spowoduje to wyświetlenie informacji o zdarzeniu, takich jak czas jego rozpoczęcia i czas trwania.

Oprócz kliknięcia możesz przeciągnąć myszą, aby wybrać grupę zdarzeń śledzenia. Spowoduje to wyświetlenie listy wszystkich wydarzeń w tym obszarze wraz z podsumowaniem wydarzenia. Użyj M klawisz, aby zmierzyć czas trwania wybranych wydarzeń.

Zdarzenia śledzenia są zbierane z:

  • CPU: CPU zdarzenia są wyświetlane w ramach grupy zdarzenie o nazwie /host:CPU . Każda ścieżka reprezentuje wątek na procesorze. Zdarzenia procesora obejmują zdarzenia potoku wejściowego, zdarzenia planowania operacji GPU (op), zdarzenia wykonania operacji procesora itp.
  • GPU: GPU zdarzenia są wyświetlane w ramach grup zdarzeń przez prefiksem /device:GPU: . Każda grupa zdarzeń reprezentuje jeden strumień na GPU.

Debugowanie wąskich gardeł wydajności

Użyj przeglądarki śledzenia, aby zlokalizować wąskie gardła wydajności w potoku wejściowym. Poniższy obraz to migawka profilu wydajności.

profiler_trace_viewer_bad_ip

Patrząc na ślady zdarzeń, można zobaczyć, że GPU jest nieaktywna, podczas gdy tf_data_iterator_get_next op działa na CPU. Ta operacja odpowiada za przetwarzanie danych wejściowych i wysyłanie ich do GPU w celu przeszkolenia. Zgodnie z ogólną zasadą, dobrym pomysłem jest utrzymywanie zawsze aktywnego urządzenia (GPU/TPU).

Użyj tf.data API w celu optymalizacji rurociągu wejściowego. W takim przypadku zbuforujmy treningowy zestaw danych i pobierzmy dane z wyprzedzeniem, aby upewnić się, że zawsze są dostępne dane do przetworzenia przez procesor GPU. Zobacz tutaj po więcej informacji na temat korzystania tf.data zoptymalizować rurociągi wejściowych.

(ds_train, ds_test), ds_info = tfds.load(
    'mnist',
    split=['train', 'test'],
    shuffle_files=True,
    as_supervised=True,
    with_info=True,
)
ds_train = ds_train.map(normalize_img)
ds_train = ds_train.batch(128)
ds_train = ds_train.cache()
ds_train = ds_train.prefetch(tf.data.experimental.AUTOTUNE)
ds_test = ds_test.map(normalize_img)
ds_test = ds_test.batch(128)
ds_test = ds_test.cache()
ds_test = ds_test.prefetch(tf.data.experimental.AUTOTUNE)

Ponownie przeszkol model i przechwyć profil wydajności, ponownie wykorzystując wywołanie zwrotne z poprzedniego.

model.fit(ds_train,
          epochs=2,
          validation_data=ds_test,
          callbacks = [tboard_callback])
Epoch 1/2
469/469 [==============================] - 10s 22ms/step - loss: 0.1194 - accuracy: 0.9658 - val_loss: 0.1116 - val_accuracy: 0.9680
Epoch 2/2
469/469 [==============================] - 1s 3ms/step - loss: 0.0918 - accuracy: 0.9740 - val_loss: 0.0979 - val_accuracy: 0.9712
<tensorflow.python.keras.callbacks.History at 0x7f23908762b0>

Re-launch TensorBoard i otworzyć zakładkę Profil obserwować profil wydajności dla zaktualizowanego rurociągu wejściowym.

Profil wydajności modelu ze zoptymalizowanym potokiem wejściowym jest podobny do poniższego obrazu.

%tensorboard --logdir=logs
Reusing TensorBoard on port 6006 (pid 750), started 0:00:12 ago. (Use '!kill 750' to kill it.)
<IPython.core.display.Javascript object>

Na stronie Przegląd można zobaczyć, że średni czas kroku uległ skróceniu, podobnie jak czas kroku wejściowego. Wykres krokowy wskazuje również, że model nie jest już silnie związany z danymi wejściowymi. Otwórz przeglądarkę śledzenia, aby zbadać zdarzenia śledzenia za pomocą zoptymalizowanego potoku wejściowego.

profiler_trace_viewer_good_ip

Trace Viewer pokazuje, że tf_data_iterator_get_next op wykonuje operację znacznie szybciej. W związku z tym procesor GPU otrzymuje stały strumień danych w celu przeprowadzenia szkolenia i osiąga znacznie lepsze wykorzystanie dzięki szkoleniu modelu.

Streszczenie

Użyj narzędzia TensorFlow Profiler do profilowania i debugowania wydajności uczenia modelu. Przeczytać podręcznik Profiler i oglądać profilowania wydajności w TF 2 Dyskusja z TensorFlow Dev Summit 2020, aby dowiedzieć się więcej o TensorFlow Profiler.