Оптимизация графика tensorflow с Grappler

Оптимизация графика tensorflow с Grappler

13 августа 2025 г.

Обзор контента

  • Обзор
  • Доступные оптимизаторы графика
  • Настраивать
  • Сравните производительность выполнения с Grappler и без него
  • Постоянный оптимизатор складывания
  • Оптимизатор отладчика отладки
  • Краткое содержание

Обзор

Tensorflow использует как график, так и нетерпеливые выполнения для выполнения вычислений. Аtf.Graphсодержит наборtf.Operationобъекты (OPS), которые представляют подразделения вычислений иtf.TensorОбъекты, которые представляют единицы данных, которые проходят между OPS.

Grappler - это система оптимизации графика по умолчанию в времени выполнения TensorFlow. Grappler применяет оптимизацию в графическом режиме (внутриtf.function) Чтобы улучшить производительность ваших вычислений с тензорфловом посредством упрощений графика и других высокоуровневых оптимизаций, таких как внедряющие функциональные тела, для обеспечения межпроцедурных оптимизаций. Оптимизацияtf.GraphТакже уменьшает использование пиковой памяти устройства и улучшает использование аппаратного обеспечения, оптимизируя отображение узлов графика для вычисления ресурсов.

Использоватьtf.config.optimizer.set_experimental_options()за более тонкий контроль над вашимtf.Graphоптимизация.

Доступные оптимизаторы графика

Grappler выполняет оптимизация графика через драйвер верхнего уровня под названиемMetaOptimizerПолем Следующие оптимизаторы графика доступны с TensorFlow:

  • Постоянный оптимизатор складывания -Статически позволяет значению тензоров, когда это возможно, складывая постоянные узлы на графике и материализует результат с использованием константов.
  • Арифметический оптимизатор -Упрощает арифметические операции путем устранения общих подэкспрессий и упрощения арифметических утверждений.
  • Оптимизатор макета -Оптимизируют макет тензоров для выполнения операций в зависимости от формата данных, таких как контилюции более эффективно.
  • Remapper Optimizer -Ремпс подграфы на более эффективные реализации путем замены обычно встречающихся подграфов оптимизированными плавными монолитными ядрами.
  • Оптимизатор памяти -Анализирует график, чтобы осмотреть использование пиковой памяти для каждой операции, и вставляет операции копирования памяти ЦП-ГП-GPU для обмена памятью графического процессора на ЦП, чтобы уменьшить использование пиковой памяти.
  • Оптимизатор зависимости -Удаляет или переставляет зависимости управления, чтобы сократить критический путь для шага модели или обеспечивает другие оптимизации. Также удаляет узлы, которые эффективно не являются, такие как идентичность.
  • Обрезка оптимизатора -Узлы с черносливами, которые не влияют на вывод с графика. Обычно он работает первым, чтобы уменьшить размер графика и ускорить обработку в других проходах Grappler.
  • Функциональный оптимизатор -Оптимизирует библиотеку функций программы TensorFlow и инлеирует функциональные тела, чтобы обеспечить другие межпроцедурные оптимизации.
  • Оптимизатор формы -Оптимизирует подграфы, которые работают на информации, связанной с формой и формой.
  • Автопараллельный оптимизатор -Автоматически параллелизирует графики, разделяя вдоль пакетного размера. Этот оптимизатор отключен по умолчанию.
  • Оптимизатор петли -Оптимизирует поток управления графиком путем подъема петлей-инвариантных подграфов из петли и удаляя избыточные операции стека в петлях. Также оптимизируют петли со статически известным количеством отключений и удаляют статически известные мертвые ветви в условиях.
  • Оптимизатор Allocator Allocator -Представляет аттестаторы, чтобы уменьшить движение данных и консолидировать некоторые операции.
  • Пына для размещения оптимизатора -Поменяется небольшими операциями на процессор. Этот оптимизатор отключен по умолчанию.
  • Auto Mixed Precision Optimizer -Преобразует типы данных в Float16, где это применимо для повышения производительности. В настоящее время применяется к графическим процессорам и новейшим процессорам Intel Xeon.
  • Стриптизерша отладки -Полосы узлов, связанные с отладкой, такие какtf.debugging.AssertВtf.debugging.check_numerics, иtf.printс графика. Этот оптимизатор отключен по умолчанию.

Настраивать

import numpy as np
import timeit
import traceback
import contextlib


import tensorflow as tf

2024-10-22 01:21:40.497936: E external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:485] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered
2024-10-22 01:21:40.518495: E external/local_xla/xla/stream_executor/cuda/cuda_dnn.cc:8454] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered
2024-10-22 01:21:40.524546: E external/local_xla/xla/stream_executor/cuda/cuda_blas.cc:1452] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered

Создайте менеджер контекста, чтобы легко переключать состояния оптимизатора.

@contextlib.contextmanager
def options(options):
  old_opts = tf.config.optimizer.get_experimental_options()
  tf.config.optimizer.set_experimental_options(options)
  try:
    yield
  finally:
    tf.config.optimizer.set_experimental_options(old_opts)

Сравните производительность выполнения с Grappler и без него

Tensorflow 2 и Behing Recemption выполняется с нетерпением по умолчанию. Использоватьtf.functionЧтобы переключить выполнение по умолчанию в режим графика. Grappler работает автоматически в фоновом режиме, чтобы применить приведенные выше графические оптимизации и повысить производительность выполнения.

Постоянный оптимизатор складывания

В качестве предварительного примера рассмотрите функцию, которая выполняет операции на константах и возвращает вывод.

def test_function_1():
  @tf.function
  def simple_function(input_arg):
    print('Tracing!')
    a = tf.constant(np.random.randn(2000,2000), dtype = tf.float32)
    c = a
    for n in range(50):
      c = c@a
    return tf.reduce_mean(c+input_arg)

  return simple_function

Выключите постоянный оптимизатор складывания и выполните функцию:

with options({'constant_folding': False}):
  print(tf.config.optimizer.get_experimental_options())
  simple_function = test_function_1()
  # Trace once
  x = tf.constant(2.2)
  simple_function(x)
  print("Vanilla execution:", timeit.timeit(lambda: simple_function(x), number = 1), "s")

WARNING: All log messages before absl::InitializeLog() is called are written to STDERR
I0000 00:00:1729560103.034816   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560103.038481   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560103.042253   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560103.046045   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560103.057719   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560103.061186   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560103.064513   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560103.068051   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560103.071607   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560103.075025   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560103.078392   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560103.081893   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.352532   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.354590   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.356672   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.358683   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.360804   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.362737   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.364643   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.366576   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.368663   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.370608   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.372559   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.374467   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.414463   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.416494   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.418461   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.420413   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.422446   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.424357   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.426261   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.428204   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.430256   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.433836   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.436197   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
I0000 00:00:1729560104.438538   10375 cuda_executor.cc:1015] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355
{'constant_folding': False, 'disable_model_pruning': False, 'disable_meta_optimizer': False}
Tracing!
Vanilla execution: 0.002112719000024299 s

Включите постоянный оптимизатор складывания и снова выполните функцию, чтобы наблюдать ускорение в выполнении функции.

with options({'constant_folding': True}):
  print(tf.config.optimizer.get_experimental_options())
  simple_function = test_function_1()
  # Trace once
  x = tf.constant(2.2)
  simple_function(x)
  print("Constant folded execution:", timeit.timeit(lambda: simple_function(x), number = 1), "s")

{'constant_folding': True, 'disable_model_pruning': False, 'disable_meta_optimizer': False}
Tracing!
Constant folded execution: 0.0007726810000576734 s

Оптимизатор отладчика отладки

Рассмотрим простую функцию, которая проверяет числовое значение его входного аргумента и возвращает ее.

def test_function_2():
  @tf.function
  def simple_func(input_arg):
    output = input_arg
    tf.debugging.check_numerics(output, "Bad!")
    return output
  return simple_func

Во -первых, выполните функцию с выключенным оптимизатором отладки.

test_func = test_function_2()
p1 = tf.constant(float('inf'))
try:
  test_func(p1)
except tf.errors.InvalidArgumentError as e:
  traceback.print_exc(limit=2)

2024-10-22 01:22:00.656591: E tensorflow/core/kernels/check_numerics_op.cc:299] abnormal_detected_host @0x7f5f72c00100 = {0, 1} Bad!
Traceback (most recent call last):
  File "/tmpfs/tmp/ipykernel_10375/3616845043.py", line 4, in <module>
    test_func(p1)
  File "/tmpfs/src/tf_docs_env/lib/python3.9/site-packages/tensorflow/python/util/traceback_utils.py", line 153, in error_handler
    raise e.with_traceback(filtered_tb) from None
tensorflow.python.framework.errors_impl.InvalidArgumentError: Graph execution error:

Detected at node CheckNumerics defined at (most recent call last):
  File "/usr/lib/python3.9/runpy.py", line 197, in _run_module_as_main

  File "/usr/lib/python3.9/runpy.py", line 87, in _run_code

tf.debugging.check_numericsвызывает неверную ошибку аргумента из -заInfаргументtest_funcПолем

Включите оптимизатор отладки и выполните функцию снова.

with options({'debug_stripper': True}):
  test_func2 = test_function_2()
  p1 = tf.constant(float('inf'))
  try:
    test_func2(p1)
  except tf.errors.InvalidArgumentError as e:
    traceback.print_exc(limit=2)

Оптимизатор отладчика отладки лишивает оптимизаторtf.debug.check_numericsУзел с графика и выполняет функцию, не поднимая никаких ошибок.

Краткое содержание

Время выполнения TensorFlow использует Grappler для автоматической оптимизации графиков перед выполнением. Использоватьtf.config.optimizer.set_experimental_optionsЧтобы включить или отключить различные оптимизаторы графика.

Для получения дополнительной информации о Grappler см.Оптимизация графика TensorFlowПолем

Первоначально опубликовано наTensorflowВеб -сайт, эта статья появляется здесь под новым заголовком и имеет лицензию в CC на 4.0. Образцы кода, разделенные по лицензии Apache 2.0.


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE