mindspore2022/mindspore/ccsrc/utils/profile.h

234 lines
5.3 KiB
C++

/**
* Copyright 2019 Huawei Technologies Co., Ltd
*
* 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
*
* http://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.
*/
#ifndef MINDSPORE_CCSRC_UTILS_PROFILE_H_
#define MINDSPORE_CCSRC_UTILS_PROFILE_H_
#include <map>
#include <string>
#include <fstream>
#include <iomanip>
#include <sstream>
#include "utils/log_adapter.h"
namespace mindspore {
struct TimeInfo;
using TimeInfoMap = std::map<std::string, const TimeInfo*>;
extern double GetTime();
class ProfileBase;
struct TimeInfo {
explicit TimeInfo(double time = -1.0) : time_(time), dict_(nullptr) {}
TimeInfo(const TimeInfo&) = delete;
~TimeInfo();
double time_;
TimeInfoMap* dict_;
};
// Utility class for Profile.
class ProfContext {
friend class Profile;
friend class ProfileBase;
friend class ProfTransaction;
public:
ProfContext(const std::string& name, ProfileBase* prof);
~ProfContext();
ProfContext(const ProfContext&) = delete;
ProfContext& operator=(const ProfContext&) = delete;
void SetTime(double time) noexcept;
void Insert(const std::string& name, const TimeInfo* time) noexcept;
bool IsTopContext() const noexcept;
private:
std::string name_;
ProfileBase* prof_;
ProfContext* parent_;
TimeInfo* time_info_;
};
class ProfileBase {
friend class ProfContext;
friend class ProfTransaction;
public:
ProfileBase();
virtual ~ProfileBase();
virtual void Print(void) {}
virtual ProfContext* Step(const std::string&) { return nullptr; }
virtual ProfContext* Lap(int) { return nullptr; }
virtual void Pop(void) {}
// top level profile context
ProfContext context_;
// profile context pointer, act as a stack pointer
ProfContext* ctx_ptr_ = nullptr;
};
class Profile : public ProfileBase {
public:
Profile() = default;
~Profile() override = default;
Profile(const Profile&) = delete;
Profile& operator=(const Profile&) = delete;
void Print(void) override;
ProfContext* Step(const std::string& name) override;
ProfContext* Lap(int count) override;
void Pop(void) noexcept override;
};
class ProfTransaction {
public:
explicit ProfTransaction(const ProfileBase* prof);
explicit ProfTransaction(ProfContext* const ctx) : ctx_(ctx) {}
ProfTransaction(const ProfTransaction&) = delete;
~ProfTransaction();
template <class Function>
void operator-(const Function& func) {
double start_time = GetTime();
func();
double end_time = GetTime();
if (ctx_ != nullptr) {
ctx_->SetTime(end_time - start_time);
}
}
private:
ProfContext* ctx_ = nullptr;
};
class NoProfTransaction {
public:
explicit NoProfTransaction(ProfileBase* prof) {}
explicit NoProfTransaction(ProfContext* ctx) {}
~NoProfTransaction() = default;
template <class Function>
void operator-(const Function& func) {
func();
}
};
class DumpTime {
public:
~DumpTime() {
try {
Save();
} catch (const std::exception& e) {
MS_LOG(ERROR) << "Cannot save file by profile::DumpTime::save";
} catch (...) {
MS_LOG(ERROR) << "Uncaught exception";
}
}
DumpTime(const DumpTime&) = delete;
DumpTime& operator=(const DumpTime&) = delete;
static DumpTime& GetInstance() {
static DumpTime instance;
return instance;
}
void set_file_path(const std::string& save_path) { file_path_ = save_path; }
void Record(const std::string& name, const double time, const bool is_start);
void Save();
private:
DumpTime() = default;
std::stringstream file_ss_;
std::ofstream file_out_;
std::string file_path_ = "./timeline.json";
};
struct TimeStat {
TimeStat() {
time_ = 0.0;
count_ = 0;
}
~TimeStat() = default;
void operator+=(double t) {
time_ += t;
count_ += 1;
}
TimeStat operator+(double t) {
TimeStat ts = *this;
ts += t;
return ts;
}
double time_;
int count_;
};
class MsProfile {
public:
~MsProfile() { Clear(); }
static void Reset() { GetSingleton().Clear(); }
static ProfileBase* GetProfile() {
MsProfile& ms_prof = GetSingleton();
if (ms_prof.profile_ == nullptr) {
#ifdef ENABLE_PROFILE
ms_prof.profile_ = new Profile();
#else
ms_prof.profile_ = new ProfileBase();
#endif
}
return ms_prof.profile_;
}
static void StatTime(const std::string& id, double time) { GetSingleton().time_stat_[id] += time; }
static void Print();
private:
MsProfile() = default;
static MsProfile& GetSingleton() {
static MsProfile profile;
return profile;
}
void Clear() {
time_stat_.clear();
if (profile_ != nullptr) {
delete profile_;
profile_ = nullptr;
}
}
std::map<std::string, TimeStat> time_stat_; // record time and count info from some activity
ProfileBase* profile_ = nullptr; // record hierarchical profile info
};
} // namespace mindspore
#ifdef ENABLE_PROFILE
#define WITH(x) ProfTransaction(x) -
#else
#define WITH(x) NoProfTransaction(x) -
#endif
#endif // MINDSPORE_CCSRC_UTILS_PROFILE_H_