• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2018 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 
16 #include "tensorflow/core/profiler/lib/profiler_session.h"
17 
18 #include <memory>
19 #include <utility>
20 
21 #include "absl/memory/memory.h"
22 #include "tensorflow/core/platform/errors.h"
23 #include "tensorflow/core/platform/logging.h"
24 #include "tensorflow/core/platform/mutex.h"
25 #include "tensorflow/core/platform/platform.h"
26 #include "tensorflow/core/platform/status.h"
27 #include "tensorflow/core/platform/types.h"
28 #include "tensorflow/core/profiler/lib/profiler_interface.h"
29 #include "tensorflow/core/profiler/profiler_options.pb.h"
30 #include "tensorflow/core/profiler/protobuf/xplane.pb.h"
31 #include "tensorflow/core/protobuf/config.pb.h"
32 #include "tensorflow/core/protobuf/error_codes.pb.h"
33 
34 #if !defined(IS_MOBILE_PLATFORM)
35 #include "tensorflow/core/profiler/convert/post_process_single_host_xplane.h"
36 #include "tensorflow/core/profiler/lib/profiler_factory.h"
37 #include "tensorflow/core/profiler/lib/profiler_lock.h"
38 #include "tensorflow/core/profiler/utils/time_utils.h"
39 #endif
40 
41 namespace tensorflow {
42 namespace {
43 
GetOptions(const ProfileOptions & opts)44 ProfileOptions GetOptions(const ProfileOptions& opts) {
45   if (opts.version()) return opts;
46   ProfileOptions options = ProfilerSession::DefaultOptions();
47   options.set_include_dataset_ops(opts.include_dataset_ops());
48   return options;
49 }
50 
51 };  // namespace
52 
Create(const ProfileOptions & options)53 /*static*/ std::unique_ptr<ProfilerSession> ProfilerSession::Create(
54     const ProfileOptions& options) {
55   return absl::WrapUnique(new ProfilerSession(options));
56 }
57 
Status()58 tensorflow::Status ProfilerSession::Status() {
59   mutex_lock l(mutex_);
60   return status_;
61 }
62 
CollectDataInternal(profiler::XSpace * space)63 Status ProfilerSession::CollectDataInternal(profiler::XSpace* space) {
64   mutex_lock l(mutex_);
65   TF_RETURN_IF_ERROR(status_);
66 #if !defined(IS_MOBILE_PLATFORM)
67   LOG(INFO) << "Profiler session collecting data.";
68   for (auto& profiler : profilers_) {
69     profiler->Stop().IgnoreError();
70   }
71 
72   for (auto& profiler : profilers_) {
73     profiler->CollectData(space).IgnoreError();
74   }
75 
76   if (active_) {
77     // Allow another session to start.
78     profiler::ReleaseProfilerLock();
79     active_ = false;
80   }
81 #endif
82   return Status::OK();
83 }
84 
CollectData(profiler::XSpace * space)85 Status ProfilerSession::CollectData(profiler::XSpace* space) {
86 #if !defined(IS_MOBILE_PLATFORM)
87   TF_RETURN_IF_ERROR(CollectDataInternal(space));
88   PostProcessSingleHostXSpace(space, start_time_ns_);
89 #endif
90   return Status::OK();
91 }
92 
ProfilerSession(const ProfileOptions & options)93 ProfilerSession::ProfilerSession(const ProfileOptions& options)
94 #if defined(IS_MOBILE_PLATFORM)
95     : active_(false),
96       status_(tensorflow::Status(
97           error::UNIMPLEMENTED,
98           "Profiler is unimplemented for mobile platforms.")),
99 #else
100     : active_(profiler::AcquireProfilerLock()),
101 #endif
102       options_(GetOptions(options)) {
103 #if !defined(IS_MOBILE_PLATFORM)
104   if (!active_) {
105     status_ = tensorflow::Status(error::ALREADY_EXISTS,
106                                  "Another profiler session is active.");
107     return;
108   }
109 
110   LOG(INFO) << "Profiler session initializing.";
111   // Sleep until it is time to start profiling.
112   if (options_.start_timestamp_ns() > 0) {
113     int64_t sleep_duration_ns =
114         options_.start_timestamp_ns() - profiler::GetCurrentTimeNanos();
115     if (sleep_duration_ns < 0) {
116       LOG(WARNING) << "Profiling is late by " << -sleep_duration_ns
117                    << " nanoseconds and will start immediately.";
118     } else {
119       LOG(INFO) << "Delaying start of profiler session by "
120                 << sleep_duration_ns;
121       profiler::SleepForNanos(sleep_duration_ns);
122     }
123   }
124 
125   LOG(INFO) << "Profiler session started.";
126   start_time_ns_ = profiler::GetCurrentTimeNanos();
127   CreateProfilers(options_, &profilers_);
128   status_ = Status::OK();
129 
130   for (auto& profiler : profilers_) {
131     DCHECK(profiler != nullptr);
132     auto start_status = profiler->Start();
133     if (!start_status.ok()) {
134       LOG(WARNING) << "Encountered error while starting profiler: "
135                    << start_status.ToString();
136     }
137   }
138 #endif
139 }
140 
~ProfilerSession()141 ProfilerSession::~ProfilerSession() {
142 #if !defined(IS_MOBILE_PLATFORM)
143   LOG(INFO) << "Profiler session tear down.";
144   for (auto& profiler : profilers_) {
145     profiler->Stop().IgnoreError();
146   }
147 
148   if (active_) {
149     // Allow another session to start.
150     profiler::ReleaseProfilerLock();
151   }
152 #endif
153 }
154 
155 }  // namespace tensorflow
156