1 /**
2 * Copyright 2019-2022 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 #ifndef MINDSPORE_CORE_UTILS_MS_UTILS_H_
17 #define MINDSPORE_CORE_UTILS_MS_UTILS_H_
18
19 #include <memory>
20 #include <utility>
21 #include <string>
22 #include <vector>
23 #include <atomic>
24 #include <thread>
25 #include <limits>
26 #include <cmath>
27 #include <chrono>
28 #include <algorithm>
29 #include <cctype>
30 #include "mindapi/base/macros.h"
31 namespace mindspore {
32 class MSLogTime {
33 public:
MSLogTime()34 MSLogTime() {}
~MSLogTime()35 ~MSLogTime() {}
Start()36 inline void Start() { this->start = std::chrono::system_clock::now(); }
End()37 inline void End() { this->end = std::chrono::system_clock::now(); }
GetRunTimeUS()38 uint64_t GetRunTimeUS() {
39 auto ms_duration = std::chrono::duration_cast<std::chrono::microseconds>(this->end - this->start);
40 uint64_t ms = ms_duration.count();
41 return ms;
42 }
43
44 private:
45 std::chrono::system_clock::time_point start;
46 std::chrono::system_clock::time_point end;
47 };
48 } // namespace mindspore
49
50 #define DISABLE_COPY_AND_ASSIGN(ClassType) \
51 ClassType(const ClassType &) = delete; \
52 ClassType &operator=(const ClassType &) = delete;
53
54 #define TRY_AND_CATCH_WITH_EXCEPTION(expr, error_msg) \
55 do { \
56 try { \
57 (expr); \
58 } catch (const std::exception &e) { \
59 MS_LOG(EXCEPTION) << "Caught exception of " << e.what() << ". " << error_msg; \
60 } \
61 } while (0)
62
63 namespace mindspore {
64 namespace common {
SafeCStr(const std::string & str)65 inline const char *SafeCStr(const std::string &str) { return str.c_str(); }
66 MS_CORE_API const char *SafeCStr(const std::string &&str);
67
68 // Memory dev config.
69 const char kAllocConf[] = "MS_ALLOC_CONF";
70 const char kAllocEnableVmm[] = "enable_vmm";
71 const char kAllocVmmAlignSize[] = "vmm_align_size";
72 const char kAllocMemoryRecycle[] = "memory_recycle";
73 const char kAllocMemoryTracker[] = "memory_tracker";
74 const char kAllocDefragMemoryStepFreq[] = "defrag_memory_step_freq";
75
76 // Runtime dev config.
77 const char kRuntimeConf[] = "MS_DEV_RUNTIME_CONF";
78 const char kRuntimeInline[] = "inline";
79 const char kRuntimeSwitchInline[] = "switch_inline";
80 const char kRuntimeMultiStream[] = "multi_stream";
81 const char kRuntimePipeline[] = "pipeline";
82 const char kRuntimeView[] = "view";
83 const char kRuntimeInsertTensorMove[] = "insert_tensormove";
84 const char kRuntimeAllfinite[] = "all_finite";
85 const char kRuntimeParalletAssignAddOpt[] = "parallel_assignadd_opt";
86 // Runtime debug config.
87 const char kRuntimeSynchronize[] = "synchronize";
88 const char kRuntimeMemoryTrack[] = "memory_track";
89 const char kRuntimeMemoryStat[] = "memory_statistics";
90 const char kRuntimeCompileStat[] = "compile_statistics";
91 const char kRuntimePerformanceStat[] = "performance_statistics";
92 const char kRuntimePerformanceStatTopNum[] = "performance_statistics_top_num";
93 MS_CORE_API void ResetConfig(const std::string &config);
94 MS_CORE_API std::string GetConfigValue(const std::string &config, const std::string &config_key);
95 MS_CORE_API bool IsEnableRuntimeConfig(const std::string &runtime_config);
96 MS_CORE_API bool IsDisableRuntimeConfig(const std::string &runtime_config);
97 MS_CORE_API std::string GetAllocConfigValue(const std::string &alloc_config);
98 MS_CORE_API bool IsEnableAlllocConfig(const std::string &alloc_config);
99 MS_CORE_API bool IsDisableAlllocConfig(const std::string &alloc_config);
100
GetEnv(const std::string & envvar)101 static inline std::string GetEnv(const std::string &envvar) {
102 const char *value = std::getenv(envvar.c_str());
103
104 if (value == nullptr) {
105 return std::string();
106 }
107
108 return std::string(value);
109 }
110
111 static inline int SetEnv(const char *envname, const char *envvar, int overwrite = 1) {
112 #if defined(_WIN32)
113 return 0;
114 #else
115 return ::setenv(envname, envvar, overwrite);
116 #endif
117 }
118
SetOMPThreadNum()119 static inline void SetOMPThreadNum() {
120 const size_t kOMPThreadMaxNum = 16;
121 const size_t kOMPThreadMinNum = 1;
122 // The actor concurrent execution max num.
123 const size_t kActorConcurrentMaxNum = 4;
124
125 size_t cpu_core_num = std::thread::hardware_concurrency();
126 size_t cpu_core_num_half = cpu_core_num / 2;
127 // Ensure that the calculated number of OMP threads is at most half the number of CPU cores.
128 size_t OMP_thread_num = cpu_core_num_half / kActorConcurrentMaxNum;
129
130 OMP_thread_num = OMP_thread_num < kOMPThreadMinNum ? kOMPThreadMinNum : OMP_thread_num;
131 OMP_thread_num = OMP_thread_num > kOMPThreadMaxNum ? kOMPThreadMaxNum : OMP_thread_num;
132
133 std::string OMP_env = std::to_string(OMP_thread_num);
134 (void)SetEnv("OMP_NUM_THREADS", OMP_env.c_str(), 0);
135 }
136
IsLittleByteOrder()137 static inline bool IsLittleByteOrder() {
138 uint32_t check_code = 0x12345678;
139 auto check_pointer = reinterpret_cast<uint8_t *>(&check_code);
140 uint8_t head_code = 0x78;
141 if (check_pointer[0] == head_code) {
142 return true;
143 }
144 return false;
145 }
146
UseMPI()147 static inline bool UseMPI() {
148 // If these OpenMPI environment variables are set, we consider this process is launched by OpenMPI.
149 std::string ompi_command_env = GetEnv("OMPI_COMMAND");
150 std::string pmix_rank_env = GetEnv("PMIX_RANK");
151 if (!ompi_command_env.empty() && !pmix_rank_env.empty()) {
152 if (!GetEnv("MS_ROLE").empty()) {
153 return false;
154 }
155 return true;
156 }
157 return false;
158 }
159
UseDynamicCluster()160 static inline bool UseDynamicCluster() {
161 // If environment variable 'MS_ROLE' or 'MS_SCHED_HOST' is set, we consider this process is participating in cluster
162 // building.
163 return !common::GetEnv("MS_ROLE").empty() || !common::GetEnv("MS_SCHED_HOST").empty();
164 }
165
166 // UseDynamicCluster or UseMPI. If false, means use rank table file.
UseHostCollective()167 static inline bool UseHostCollective() { return common::UseDynamicCluster() || common::UseMPI(); }
168
169 template <typename T>
IsEqual(const T * a,const T * b)170 bool IsEqual(const T *a, const T *b) {
171 if (a == b) {
172 return true;
173 }
174 if (a == nullptr || b == nullptr) {
175 return false;
176 }
177 return *a == *b;
178 }
179
180 template <typename T>
IsEqual(const std::shared_ptr<T> & a,const std::shared_ptr<T> & b)181 bool IsEqual(const std::shared_ptr<T> &a, const std::shared_ptr<T> &b) {
182 return IsEqual(a.get(), b.get());
183 }
184
185 template <typename T>
IsAttrsEqual(const T & a,const T & b)186 bool IsAttrsEqual(const T &a, const T &b) {
187 if (&a == &b) {
188 return true;
189 }
190 if (a.size() != b.size()) {
191 return false;
192 }
193 auto iter1 = a.begin();
194 auto iter2 = b.begin();
195 while (iter1 != a.end()) {
196 if (iter1->first != iter2->first) {
197 return false;
198 }
199 if (!IsEqual(iter1->second, iter2->second)) {
200 return false;
201 }
202 ++iter1;
203 ++iter2;
204 }
205 return true;
206 }
207
IsFloatEqual(const float & a,const float & b)208 inline bool IsFloatEqual(const float &a, const float &b) {
209 return (std::fabs(a - b) <= std::numeric_limits<float>::epsilon());
210 }
211
IsDoubleEqual(const double & a,const double & b)212 inline bool IsDoubleEqual(const double &a, const double &b) {
213 return (std::fabs(a - b) <= std::numeric_limits<double>::epsilon());
214 }
215
IsStrNumeric(const std::string & str)216 inline bool IsStrNumeric(const std::string &str) {
217 return std::all_of(str.begin(), str.end(), [](char c) { return std::isdigit(c); });
218 }
219
IsNeedMemoryStatistic()220 inline bool IsNeedMemoryStatistic() {
221 static const char kMemoryStatistic[] = "MS_MEMORY_STATISTIC";
222 static const auto need_statistic = GetEnv(kMemoryStatistic);
223 return !need_statistic.empty() && need_statistic != "0";
224 }
225
IsNeedProfileMemory()226 inline bool IsNeedProfileMemory() {
227 static const char kLaunchSkippedEnv[] = "MS_KERNEL_LAUNCH_SKIP";
228 static const char kSimulationLevel[] = "MS_SIMULATION_LEVEL";
229 static const auto launch_skipped = GetEnv(kLaunchSkippedEnv);
230 static const auto simulation_level = common::GetEnv(kSimulationLevel);
231 static const bool skip_launch = (launch_skipped == "all" || launch_skipped == "ALL" || !simulation_level.empty());
232 return skip_launch;
233 }
234 } // namespace common
235 } // namespace mindspore
236
237 #endif // MINDSPORE_CORE_UTILS_MS_UTILS_H_
238