이 페이지는 Cloud Translation API를 통해 번역되었습니다.
Switch to English

Grappler를 사용한 TensorFlow 그래프 최적화

TensorFlow.org에서보기 Google Colab에서 실행 GitHub에서 소스보기 노트북 다운로드

개요

TensorFlow는 그래프와 eager 실행을 모두 사용하여 계산을 실행합니다. tf.Graph 에는 연산 단위를 나타내는 tf.Operation 객체 (ops)와 연산간에 흐르는 데이터 단위를 나타내는 tf.Tensor 객체 세트가 포함됩니다.

Grappler는 TensorFlow 런타임의 기본 그래프 최적화 시스템입니다. Grappler는 그래프 모드 ( tf.function 내)에서 최적화를 적용하여 그래프 단순화 및 함수 본문 인라인과 같은 기타 상위 수준 최적화를 통해 TensorFlow 계산 성능을 개선하여 절차 간 최적화를 가능하게합니다. 또한 tf.Graph 를 최적화하면 그래프 노드를 컴퓨팅 리소스에 매핑하는 것을 최적화하여 장치 최대 메모리 사용량을 줄이고 하드웨어 활용도를 향상시킵니다.

tf.Graph 최적화를보다 세밀하게 제어하려면 tf.config.optimizer.set_experimental_options() 를 사용하십시오.

사용 가능한 그래프 최적화 프로그램

Grappler는 MetaOptimizer 라는 최상위 드라이버를 통해 그래프 최적화를 수행합니다. TensorFlow에서 다음 그래프 최적화 도구를 사용할 수 있습니다.

  • 상수 폴딩 옵티 마이저- 그래프에서 상수 노드를 폴딩하여 가능한 경우 텐서 값을 정적으로 유추하고 상수를 사용하여 결과를 구체화합니다.
  • 산술 옵티 마이저- 공통 하위 표현식을 제거하고 산술 문을 단순화하여 산술 연산을 단순화합니다.
  • 레이아웃 최적화- 텐서 레이아웃을 최적화하여 컨볼 루션과 같은 데이터 형식 종속 작업을보다 효율적으로 실행합니다.
  • Remapper 최적화 프로그램- 일반적으로 발생하는 하위 그래프를 최적화 된 통합 모 놀리 식 커널로 대체하여 하위 그래프를보다 효율적인 구현으로 다시 매핑합니다.
  • 메모리 최적화 프로그램- 그래프를 분석하여 각 작업에 대한 최대 메모리 사용량을 검사하고 GPU 메모리를 CPU로 교체하기위한 CPU-GPU 메모리 복사 작업을 삽입하여 최대 메모리 사용량을 줄입니다.
  • 종속성 최적화 프로그램- 제어 종속성을 제거하거나 재정렬하여 모델 단계의 중요 경로를 단축하거나 다른 최적화를 활성화합니다. 또한 Identity와 같이 효과적으로 작동하지 않는 노드를 제거합니다.
  • 프 루닝 옵티 마이저- 그래프의 출력에 영향을 미치지 않는 노드를 프룬합니다. 일반적으로 그래프 크기를 줄이고 다른 그래플러 패스에서 처리 속도를 높이기 위해 먼저 실행됩니다.
  • 함수 최적화 도구-TensorFlow 프로그램의 함수 라이브러리를 최적화하고 함수 본문을 인라인하여 다른 절차 간 최적화를 가능하게합니다.
  • 모양 최적화 기- 모양 및 모양 관련 정보에서 작동하는 하위 그래프를 최적화합니다.
  • Autoparallel Optimizer- 배치 차원을 따라 분할하여 그래프를 자동으로 병렬화합니다. 이 최적화 프로그램은 기본적으로 꺼져 있습니다.
  • 루프 최적화 기- 루프 불변 하위 그래프를 루프 밖으로 끌어 내고 루프에서 중복 스택 작업을 제거하여 그래프 제어 흐름을 최적화합니다. 또한 정적으로 알려진 트립 카운트로 루프를 최적화하고 조건부에서 정적으로 알려진 데드 브랜치를 제거합니다.
  • 범위 할당 자 최적화 프로그램- 데이터 이동을 줄이고 일부 작업을 통합하기 위해 범위 할당자를 도입합니다.
  • 호스트 최적화 프로그램에 고정- 작은 작업을 CPU로 교체합니다. 이 최적화 프로그램은 기본적으로 꺼져 있습니다.
  • 자동 혼합 정밀도 최적화 프로그램- 성능 향상을 위해 데이터 유형을 float16으로 변환합니다. 현재는 GPU에만 적용됩니다.
  • 디버그 스트리퍼- 그래프에서 tf.debugging.Assert , tf.debugging.check_numericstf.print 와 같은 디버깅 작업과 관련된 노드를 제거합니다. 이 최적화 프로그램은 기본적으로 꺼져 있습니다.

설정

import numpy as np
import timeit
import traceback
import contextlib


import tensorflow as tf

최적화 상태를 쉽게 전환 할 수있는 컨텍스트 관리자를 만듭니다.

@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 이상은 기본적으로 열심히 실행됩니다. 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")
{'constant_folding': False, 'disable_model_pruning': False, 'disable_meta_optimizer': False}
Tracing!
Vanilla execution: 0.0801323579999007 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.0006300529998952697 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)
Traceback (most recent call last):
  File "<ipython-input-8-1ac473fdfbab>", line 4, in <module>
    test_func(p1)
  File "/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/eager/def_function.py", line 780, in __call__
    result = self._call(*args, **kwds)
tensorflow.python.framework.errors_impl.InvalidArgumentError: 2 root error(s) found.
  (0) Invalid argument:  Bad! : Tensor had Inf values
     [[node CheckNumerics (defined at <ipython-input-7-cbee1561c83e>:5) ]]
  (1) Invalid argument:  Bad! : Tensor had Inf values
     [[node CheckNumerics (defined at <ipython-input-7-cbee1561c83e>:5) ]]
     [[Identity/_4]]
0 successful operations.
0 derived errors ignored. [Op:__inference_simple_func_131]

Errors may have originated from an input operation.
Input Source operations connected to node CheckNumerics:
 input_arg (defined at <ipython-input-8-1ac473fdfbab>:4)

Input Source operations connected to node CheckNumerics:
 input_arg (defined at <ipython-input-8-1ac473fdfbab>:4)

Function call stack:
simple_func -> simple_func


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 그래프 최적화를 참조하십시오.