In [0]:
#@title Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
TensorFlow uses both graph and eager executions to execute computations. A tf.Graph
contains a set of tf.Operation
objects (ops) which represent units of computation and tf.Tensor
objects which represent the units of data that flow between ops.
Grappler is the default graph optimization system in the TensorFlow runtime. Grappler applies optimizations in graph mode (within tf.function
) to improve the performance of your TensorFlow computations through graph simplifications and other high-level optimizations such as inlining function bodies to enable inter-procedural optimizations. Optimizing the tf.Graph
also reduces the device peak memory usage and improves hardware utilization by optimizing the mapping of graph nodes to compute resources.
Use tf.config.optimizer.set_experimental_options()
for finer control over your tf.Graph
optimizations.
Grappler performs graph optimizations through a top-level driver called the MetaOptimizer
. The following graph optimizers are available with TensorFlow:
tf.debugging.Assert
, tf.debugging.check_numerics
, and tf.print
from the graph. This optimizer is turned OFF by default.
In [0]:
import numpy as np
import timeit
import traceback
import contextlib
import tensorflow as tf
Create a context manager to easily toggle optimizer states.
In [0]:
@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)
TensorFlow 2 and beyond executes eagerly by default. Use tf.function
to switch the default execution to Graph mode. Grappler runs automatically in the background to apply the graph optimizations above and improve execution performance.
In [0]:
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
Turn off the constant folding optimizer and execute the function:
In [0]:
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")
Enable the constant folding optimizer and execute the function again to observe a speed-up in function execution.
In [0]:
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")
In [0]:
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
First, execute the function with the debug stripper optimizer turned off.
In [0]:
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)
tf.debugging.check_numerics
raises an invalid argument error because of the Inf
argument to test_func
.
Enable the debug stripper optimizer and execute the function again.
In [0]:
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)
The debug stripper optimizer strips the tf.debug.check_numerics
node from the graph and executes the function without raising any errors.
The TensorFlow runtime uses Grappler to optimize graphs automatically before execution. Use tf.config.optimizer.set_experimental_options
to enable or disable the various graph optimizers.
For more information on Grappler, see TensorFlow Graph Optimizations.