TensorFlow.org에서보기 | Google Colab에서 실행하기 | GitHub에서 소그 보기 | 노트북 다운로드하기 |
개요
TensorFlow는 그래프와 Eager 실행을 모두 사용하여 계산을 실행합니다. tf.Graph
에는 계산 단위를 나타내는 tf.Operation
객체(ops) 및 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와 같이 효과적으로 no-ops인 노드를 제거합니다.
- 잘라내기 옵티마이저 - 그래프 출력에 영향을 미치지 않는 노드를 잘라냅니다. 일반적으로 그래프 크기를 줄이고 다른 Grappler 패스에서 처리 속도를 높이기 위해 먼저 실행됩니다.
- 함수 옵티마이저 -TensorFlow 프로그램의 함수 라이브러리를 최적화하고 함수 본문을 인라인 처리하여 다른 절차 간에 최적화를 가능하게 합니다.
- 형상 옵티마이저 - 형상 및 형상 관련 정보를 기반으로 작동하는 하위 그래프를 최적화합니다.
- 자동 병렬 옵티마이저 - 배치 차원을 따라 분할하여 그래프를 자동으로 병렬화합니다. 이 옵티마이저는 기본적으로 꺼져(OFF) 있습니다.
- 루프 옵티마이저 - 루프 고정 하위 그래프를 루프 밖으로 가져오고 루프에서 중복 스택 연산을 제거하여 그래프 제어 흐름을 최적화합니다. 또한, 정적으로 알려진 트립 카운트로 루프를 최적화하고 조건부에서 정적으로 알려진 데드 분기를 제거합니다.
- 범위가 지정된 할당자 옵티마이저 - 데이터 이동을 줄이고 일부 연산을 통합하기 위해 범위가 지정된 할당자를 소개합니다.
- 호스트 옵티마이저로 고정 - 작은 연산을 CPU로 전환합니다. 이 옵티마이저는 기본적으로 꺼져(OFF) 있습니다.
- 자동 혼합 정밀 옵티마이저 - 성능 향상을 위해 가능한 경우 데이터 유형을 float16으로 변환합니다. 현재 GPU에만 적용됩니다.
- 디버그 스트리퍼 - 그래프에서
tf.debugging.Assert
,tf.debugging.check_numerics
및tf.print
와 같은 디버깅 연산과 관련된 노드를 제거합니다. 이 옵티마이저는 기본적으로 꺼져(OFF) 있습니다.
설정
import numpy as np
import timeit
import traceback
import contextlib
import tensorflow as tf
2022-12-14 21:46:41.467960: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer.so.7'; dlerror: libnvinfer.so.7: cannot open shared object file: No such file or directory 2022-12-14 21:46:41.468057: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer_plugin.so.7'; dlerror: libnvinfer_plugin.so.7: cannot open shared object file: No such file or directory 2022-12-14 21:46:41.468066: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Cannot dlopen some TensorRT libraries. If you would like to use Nvidia GPU with TensorRT, please make sure the missing libraries mentioned above are installed properly.
옵티마이저 상태를 쉽게 전환할 수 있는 컨텍스트 관리자를 작성합니다.
@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.0012105499999961467 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.000868921999426675 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)
2022-12-14 21:47:01.279687: E tensorflow/core/kernels/check_numerics_op.cc:293] abnormal_detected_host @0x7faeb2600100 = {0, 1} Bad! Traceback (most recent call last): File "/tmpfs/tmp/ipykernel_135690/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 return _run_code(code, main_globals, None, File "/usr/lib/python3.9/runpy.py", line 87, in _run_code exec(code, run_globals) File "/tmpfs/src/tf_docs_env/lib/python3.9/site-packages/ipykernel_launcher.py", line 17, in <module> app.launch_new_instance() File "/tmpfs/src/tf_docs_env/lib/python3.9/site-packages/traitlets/config/application.py", line 992, in launch_instance app.start() File "/tmpfs/src/tf_docs_env/lib/python3.9/site-packages/ipykernel/kernelapp.py", line 711, in start self.io_loop.start() File "/tmpfs/src/tf_docs_env/lib/python3.9/site-packages/tornado/platform/asyncio.py", line 215, in start self.asyncio_loop.run_forever() File "/usr/lib/python3.9/asyncio/base_events.py", line 601, in run_forever self._run_once() File "/usr/lib/python3.9/asyncio/base_events.py", line 1905, in _run_once handle._run() File "/usr/lib/python3.9/asyncio/events.py", line 80, in _run self._context.run(self._callback, *self._args) File "/tmpfs/src/tf_docs_env/lib/python3.9/site-packages/ipykernel/kernelbase.py", line 510, in dispatch_queue await self.process_one() File "/tmpfs/src/tf_docs_env/lib/python3.9/site-packages/ipykernel/kernelbase.py", line 499, in process_one await dispatch(*args) File "/tmpfs/src/tf_docs_env/lib/python3.9/site-packages/ipykernel/kernelbase.py", line 406, in dispatch_shell await result File "/tmpfs/src/tf_docs_env/lib/python3.9/site-packages/ipykernel/kernelbase.py", line 729, in execute_request reply_content = await reply_content File "/tmpfs/src/tf_docs_env/lib/python3.9/site-packages/ipykernel/ipkernel.py", line 411, in do_execute res = shell.run_cell( File "/tmpfs/src/tf_docs_env/lib/python3.9/site-packages/ipykernel/zmqshell.py", line 531, in run_cell return super().run_cell(*args, **kwargs) File "/tmpfs/src/tf_docs_env/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 2940, in run_cell result = self._run_cell( File "/tmpfs/src/tf_docs_env/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 2995, in _run_cell return runner(coro) File "/tmpfs/src/tf_docs_env/lib/python3.9/site-packages/IPython/core/async_helpers.py", line 129, in _pseudo_sync_runner coro.send(None) File "/tmpfs/src/tf_docs_env/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3194, in run_cell_async has_raised = await self.run_ast_nodes(code_ast.body, cell_name, File "/tmpfs/src/tf_docs_env/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3373, in run_ast_nodes if await self.run_code(code, result, async_=asy): File "/tmpfs/src/tf_docs_env/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3433, in run_code exec(code_obj, self.user_global_ns, self.user_ns) File "/tmpfs/tmp/ipykernel_135690/3616845043.py", line 4, in <module> test_func(p1) File "/tmpfs/tmp/ipykernel_135690/2241890286.py", line 5, in simple_func tf.debugging.check_numerics(output, "Bad!") Node: 'CheckNumerics' Bad! : Tensor had Inf values [[{ {node CheckNumerics} }]] [Op:__inference_simple_func_131]
tf.debugging.check_numerics
는 test_func
에 대한 Inf
인수로 인해 유효하지 않은 인수 오류를 발생시킵니다.
디버그 스트리퍼 옵티마이저를 활성화하고 함수를 다시 실행합니다.
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 그래프 최적화를 참조하세요.