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

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

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

개요

TensorFlow는 그래프와 열성적인 실행을 모두 사용하여 계산을 실행합니다. tf.Graph 에는 연산 단위를 나타내는 tf.Operation 객체 (ops)와 tf.Tensor 간에 흐르는 데이터 단위를 나타내는 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와 같이 효과적으로 작동하지 않는 노드를 제거합니다.
  • 정리 최적화 프로그램- 그래프의 출력에 영향을 미치지 않는 노드를 정리 합니다. 일반적으로 그래프 크기를 줄이고 다른 Grappler 패스에서 처리 속도를 높이기 위해 먼저 실행됩니다.
  • 함수 최적화 기 -TensorFlow 프로그램의 함수 라이브러리를 최적화하고 함수 간을 인라인하여 다른 절차 간 최적화를 가능하게합니다.
  • 셰이프 옵티 마이저- 셰이프 및 셰이프 관련 정보에서 작동하는 하위 그래프를 최적화합니다.
  • 자동 병렬 최적화 프로그램- 배치 차원을 따라 분할하여 그래프를 자동으로 병렬화합니다. 이 옵티마이 저는 기본적으로 꺼져 있습니다.
  • 루프 최적화 프로그램- 루프 불변 하위 그래프를 루프 밖으로 가져오고 루프에서 중복 스택 작업을 제거하여 그래프 제어 흐름을 최적화합니다. 또한 정적으로 알려진 트립 카운트로 루프를 최적화하고 조건부에서 정적으로 알려진 데드 브랜치를 제거합니다.
  • 범위가 지정된 할당 자 최적화 프로그램-범위가 지정된 할당자를 소개하여 데이터 이동을 줄이고 일부 작업을 통합합니다.
  • 호스트 최적화에 핀- 작은 작업을 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.004905937999865273 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.0005699149999145448 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 580, 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) ]]
     [[Identity/_4]]
  (1) Invalid argument:  Bad! : Tensor had Inf values
     [[node CheckNumerics (defined at <ipython-input-7-cbee1561c83e>:5) ]]
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_numericsInf 인수로 인해 유효하지 않은 인수 오류를 발생 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 그래프 최적화를 참조하십시오.