1 /** 2 * Copyright 2019 Huawei Technologies Co., Ltd 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef MINDSPORE_CORE_UTILS_PROFILE_H_ 18 #define MINDSPORE_CORE_UTILS_PROFILE_H_ 19 20 #include <map> 21 #include <string> 22 #include <fstream> 23 #include <iomanip> 24 #include <sstream> 25 #include "utils/log_adapter.h" 26 27 namespace mindspore { 28 struct TimeInfo; 29 using TimeInfoMap = std::map<std::string, const TimeInfo *>; 30 31 extern double GetTime(); 32 33 class ProfileBase; 34 35 struct TimeInfo { time_TimeInfo36 explicit TimeInfo(double time = -1.0) : time_(time), dict_(nullptr), actionNum_(0) {} 37 TimeInfo(const TimeInfo &) = delete; 38 ~TimeInfo(); 39 40 double time_; 41 TimeInfoMap *dict_; 42 size_t actionNum_; 43 }; 44 45 // Utility class for Profile. 46 class ProfContext { 47 friend class Profile; 48 friend class ProfileBase; 49 friend class ProfTransaction; 50 51 public: 52 ProfContext(const std::string &name, ProfileBase *prof); 53 ~ProfContext(); 54 55 ProfContext(const ProfContext &) = delete; 56 ProfContext &operator=(const ProfContext &) = delete; 57 58 void SetTime(double time) noexcept; 59 void Insert(const std::string &name, const TimeInfo *time) noexcept; 60 bool IsTopContext() const noexcept; 61 62 private: 63 std::string name_; 64 ProfileBase *prof_; 65 ProfContext *parent_; 66 TimeInfo *time_info_; 67 }; 68 69 class ProfileBase { 70 friend class ProfContext; 71 friend class ProfTransaction; 72 73 public: 74 ProfileBase(); 75 virtual ~ProfileBase(); 76 Print(void)77 virtual void Print(void) {} Step(const std::string &)78 virtual ProfContext *Step(const std::string &) { return nullptr; } Lap(int)79 virtual ProfContext *Lap(int) { return nullptr; } Pop(void)80 virtual void Pop(void) noexcept {} 81 82 // top level profile context 83 ProfContext context_; 84 // profile context pointer, act as a stack pointer 85 ProfContext *ctx_ptr_ = nullptr; 86 }; 87 88 class Profile : public ProfileBase { 89 public: 90 Profile() = default; 91 ~Profile() override = default; 92 Profile(const Profile &) = delete; 93 Profile &operator=(const Profile &) = delete; 94 95 void Print(void) override; 96 ProfContext *Step(const std::string &name) override; 97 ProfContext *Lap(int count) override; 98 void Pop(void) noexcept override; 99 }; 100 101 class ProfTransaction { 102 public: 103 explicit ProfTransaction(const ProfileBase *prof); ProfTransaction(ProfContext * const ctx)104 explicit ProfTransaction(ProfContext *const ctx) : ctx_(ctx) {} 105 ProfTransaction(const ProfTransaction &) = delete; 106 ~ProfTransaction(); 107 108 template <class Function> 109 void operator-(const Function &func) { 110 double start_time = GetTime(); 111 func(); 112 double end_time = GetTime(); 113 if (ctx_ != nullptr) { 114 ctx_->SetTime(end_time - start_time); 115 } 116 } 117 118 private: 119 ProfContext *ctx_ = nullptr; 120 }; 121 122 class NoProfTransaction { 123 public: NoProfTransaction(ProfileBase * prof)124 explicit NoProfTransaction(ProfileBase *prof) {} NoProfTransaction(ProfContext * ctx)125 explicit NoProfTransaction(ProfContext *ctx) {} 126 ~NoProfTransaction() = default; 127 128 template <class Function> 129 void operator-(const Function &func) { 130 func(); 131 } 132 }; 133 134 class DumpTime { 135 public: ~DumpTime()136 ~DumpTime() { 137 try { 138 Save(); 139 } catch (const std::exception &e) { 140 MS_LOG(ERROR) << "Cannot save file by profile::DumpTime::save"; 141 } catch (...) { 142 MS_LOG(ERROR) << "Uncaught exception"; 143 } 144 } 145 DumpTime(const DumpTime &) = delete; 146 DumpTime &operator=(const DumpTime &) = delete; GetInstance()147 static DumpTime &GetInstance() { 148 static DumpTime instance; 149 return instance; 150 } set_file_path(const std::string & save_path)151 void set_file_path(const std::string &save_path) { file_path_ = save_path; } 152 void Record(const std::string &name, const double time, const bool is_start); 153 void Save(); 154 155 private: 156 DumpTime() = default; 157 std::stringstream file_ss_; 158 std::ofstream file_out_; 159 std::string file_path_ = "./timeline.json"; 160 }; 161 162 struct TimeStat { TimeStatTimeStat163 TimeStat() { 164 time_ = 0.0; 165 count_ = 0; 166 } 167 ~TimeStat() = default; 168 169 void operator+=(double t) { 170 time_ += t; 171 count_ += 1; 172 } 173 174 TimeStat operator+(double t) { 175 TimeStat ts = *this; 176 ts += t; 177 return ts; 178 } 179 180 double time_; 181 int count_; 182 }; 183 184 class MsProfile { 185 public: ~MsProfile()186 ~MsProfile() { Clear(); } 187 Reset()188 static void Reset() { GetSingleton().Clear(); } 189 GetProfile()190 static ProfileBase *GetProfile() { 191 MsProfile &ms_prof = GetSingleton(); 192 if (ms_prof.profile_ == nullptr) { 193 #ifdef ENABLE_PROFILE 194 ms_prof.profile_ = new Profile(); 195 #else 196 ms_prof.profile_ = new ProfileBase(); 197 #endif 198 } 199 return ms_prof.profile_; 200 } StatTime(const std::string & id,double time)201 static void StatTime(const std::string &id, double time) { GetSingleton().time_stat_[id] += time; } 202 203 static void Print(); 204 205 private: 206 MsProfile() = default; 207 GetSingleton()208 static MsProfile &GetSingleton() { 209 static MsProfile profile; 210 return profile; 211 } 212 Clear()213 void Clear() { 214 time_stat_.clear(); 215 if (profile_ != nullptr) { 216 delete profile_; 217 profile_ = nullptr; 218 } 219 } 220 221 std::map<std::string, TimeStat> time_stat_; // record time and count info from some activity 222 ProfileBase *profile_ = nullptr; // record hierarchical profile info 223 }; 224 } // namespace mindspore 225 226 #ifdef ENABLE_PROFILE 227 #define WITH(x) ProfTransaction(x) - 228 #else 229 #define WITH(x) NoProfTransaction(x) - 230 #endif 231 232 #endif // MINDSPORE_CORE_UTILS_PROFILE_H_ 233