1# Copyright 2017 The TensorFlow Authors. All Rights Reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14# ============================================================================== 15"""TensorFlow 2.0 Profiler for both Eager Mode and Graph Mode. 16 17The profiler has two mode: 18- Programmatic Mode: start(), stop() and Profiler class. It will perform 19 when calling start() or create Profiler class and will stop 20 when calling stop() or destroying Profiler class. 21- On-demand Mode: start_profiler_server(). It will perform profiling when 22 receive profiling request. 23 24NOTE: Only one active profiler session is allowed. Use of simultaneous 25Programmatic Mode and On-demand Mode is undefined and will likely fail. 26 27NOTE: The Keras TensorBoard callback will automatically perform sampled 28profiling. Before enabling customized profiling, set the callback flag 29"profile_batches=[]" to disable automatic sampled profiling. 30customized profiling. 31""" 32 33import datetime 34import os 35import threading 36 37from tensorflow.python.client import _pywrap_events_writer 38from tensorflow.python.eager import context 39from tensorflow.python.framework import errors 40from tensorflow.python.platform import gfile 41from tensorflow.python.platform import tf_logging as logging 42from tensorflow.python.profiler.internal import _pywrap_profiler 43from tensorflow.python.util import compat 44from tensorflow.python.util.deprecation import deprecated 45 46_profiler = None 47_profiler_lock = threading.Lock() 48_run_num = 0 49# This suffix should be kept in sync with kProfileEmptySuffix in 50# tensorflow/core/profiler/rpc/client/capture_profile.cc. 51_EVENT_FILE_SUFFIX = '.profile-empty' 52 53 54class ProfilerAlreadyRunningError(Exception): 55 pass 56 57 58class ProfilerNotRunningError(Exception): 59 pass 60 61 62@deprecated('2020-07-01', 'use `tf.profiler.experimental.start` instead.') 63def start(options=None): 64 """Start profiling. 65 66 Args: 67 options: profiler options. 68 69 Raises: 70 ProfilerAlreadyRunningError: If another profiling session is running. 71 """ 72 global _profiler 73 with _profiler_lock: 74 if _profiler is not None: 75 raise ProfilerAlreadyRunningError('Another profiler is running.') 76 if context.default_execution_mode == context.EAGER_MODE: 77 context.ensure_initialized() 78 _profiler = _pywrap_profiler.ProfilerSession() 79 try: 80 _profiler.start('', options if options is not None else {}) 81 except errors.AlreadyExistsError: 82 logging.warning('Another profiler session is running which is probably ' 83 'created by profiler server. Please avoid using profiler ' 84 'server and profiler APIs at the same time.') 85 raise ProfilerAlreadyRunningError('Another profiler is running.') 86 87 88@deprecated('2020-07-01', 'use `tf.profiler.experimental.stop` instead.') 89def stop(): 90 """Stop current profiling session and return its result. 91 92 Returns: 93 A binary string of tensorflow.tpu.Trace. User can write the string 94 to file for offline analysis by tensorboard. 95 96 Raises: 97 ProfilerNotRunningError: If there is no active profiling session. 98 """ 99 global _profiler 100 global _run_num 101 with _profiler_lock: 102 if _profiler is None: 103 raise ProfilerNotRunningError( 104 'Cannot stop profiling. No profiler is running.') 105 if context.default_execution_mode == context.EAGER_MODE: 106 context.context().executor.wait() 107 result = _profiler.stop() 108 _profiler = None 109 _run_num += 1 110 return result 111 112 113@deprecated( 114 '2020-07-01', 115 '`tf.python.eager.profiler` has deprecated, use `tf.profiler` instead.' 116) 117def maybe_create_event_file(logdir): 118 """Create an empty event file if not already exists. 119 120 This event file indicates that we have a plugins/profile/ directory in the 121 current logdir. 122 123 Args: 124 logdir: log directory. 125 """ 126 for file_name in gfile.ListDirectory(logdir): 127 if file_name.endswith(_EVENT_FILE_SUFFIX): 128 return 129 # TODO(b/127330388): Use summary_ops_v2.create_file_writer instead. 130 event_writer = _pywrap_events_writer.EventsWriter( 131 compat.as_bytes(os.path.join(logdir, 'events'))) 132 event_writer.InitWithSuffix(compat.as_bytes(_EVENT_FILE_SUFFIX)) 133 134 135@deprecated( 136 '2020-07-01', 137 '`tf.python.eager.profiler` has deprecated, use `tf.profiler` instead.' 138) 139def save(logdir, result): 140 """Save profile result to TensorBoard logdir. 141 142 Args: 143 logdir: log directory read by TensorBoard. 144 result: profiling result returned by stop(). 145 """ 146 plugin_dir = os.path.join( 147 logdir, 'plugins', 'profile', 148 datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')) 149 gfile.MakeDirs(plugin_dir) 150 maybe_create_event_file(logdir) 151 with gfile.Open(os.path.join(plugin_dir, 'local.trace'), 'wb') as f: 152 f.write(result) 153 154 155@deprecated('2020-07-01', 'use `tf.profiler.experimental.server.start`.') 156def start_profiler_server(port): 157 """Start a profiler grpc server that listens to given port. 158 159 The profiler server will keep the program running even the training finishes. 160 Please shutdown the server with CTRL-C. It can be used in both eager mode and 161 graph mode. The service defined in 162 tensorflow/core/profiler/profiler_service.proto. Please use 163 tensorflow/contrib/tpu/profiler/capture_tpu_profile to capture tracable 164 file following https://cloud.google.com/tpu/docs/cloud-tpu-tools#capture_trace 165 166 Args: 167 port: port profiler server listens to. 168 """ 169 if context.default_execution_mode == context.EAGER_MODE: 170 context.ensure_initialized() 171 _pywrap_profiler.start_server(port) 172 173 174@deprecated('2020-07-01', 'use `tf.profiler.experimental.Profile` instead.') 175class Profiler(object): 176 """Context-manager eager profiler api. 177 178 Example usage: 179 ```python 180 with Profiler("/path/to/logdir"): 181 # do some work 182 ``` 183 """ 184 185 def __init__(self, logdir): 186 self._logdir = logdir 187 188 def __enter__(self): 189 start() 190 191 def __exit__(self, typ, value, tb): 192 result = stop() 193 save(self._logdir, result) 194