You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

common.cpp 9.5 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /**
  2. * \file src/core/impl/common.cpp
  3. * MegEngine is Licensed under the Apache License, Version 2.0 (the "License")
  4. *
  5. * Copyright (c) 2014-2021 Megvii Inc. All rights reserved.
  6. *
  7. * Unless required by applicable law or agreed to in writing,
  8. * software distributed under the License is distributed on an
  9. * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. */
  11. #include "megbrain/common.h"
  12. #include "megbrain/exception.h"
  13. #include "megbrain/system.h"
  14. #include "megbrain/utils/thread.h"
  15. #include "megdnn/basic_types.h"
  16. #include <cstdio>
  17. #include <cstdlib>
  18. #include <ctime>
  19. #include <cstring>
  20. #ifdef __ANDROID__
  21. #include <android/log.h>
  22. #include <sys/system_properties.h>
  23. #endif
  24. using namespace mgb;
  25. namespace {
  26. LogLevel config_default_log_level() {
  27. auto default_level = LogLevel::ERROR;
  28. //! env to config LogLevel
  29. //! DEBUG = 0, INFO = 1, WARN = 2, ERROR = 3, NO_LOG = 4
  30. //! for example , export RUNTIME_OVERRIDE_LOG_LEVEL=0, means set LogLevel to
  31. //! DEBUG
  32. if (auto env = ::std::getenv("RUNTIME_OVERRIDE_LOG_LEVEL"))
  33. default_level = static_cast<LogLevel>(std::stoi(env));
  34. #ifdef __ANDROID__
  35. //! special for Android prop, attention: getprop may need permission
  36. char buf[PROP_VALUE_MAX];
  37. if (__system_property_get("RUNTIME_OVERRIDE_LOG_LEVEL", buf) > 0) {
  38. default_level = static_cast<LogLevel>(atoi(buf));
  39. }
  40. #endif
  41. return default_level;
  42. }
  43. LogLevel min_log_level = config_default_log_level();
  44. } // namespace
  45. #if MGB_ENABLE_LOGGING
  46. #if MGB_EXTERN_API_TIME
  47. extern "C" {
  48. void mgb_extern_api_get_time(int64_t *sec, int64_t *nsec);
  49. }
  50. #endif
  51. namespace {
  52. void default_log_handler(LogLevel level,
  53. const char *file, const char *func, int line, const char *fmt,
  54. va_list ap) {
  55. if (level < min_log_level)
  56. return;
  57. #define HDR_FMT "[%s %s@%s:%d]%s"
  58. fmt = convert_fmt_str(fmt);
  59. // we have to use a Spinlock here, since log handler might be called during
  60. // global finalization when mtx has been destructed
  61. static Spinlock mtx;
  62. static const char *hdr_fmt = nullptr;
  63. if (!hdr_fmt) {
  64. if (sys::stderr_ansi_color())
  65. hdr_fmt = "\x1b[32m" HDR_FMT "\x1b[0m ";
  66. else
  67. hdr_fmt = HDR_FMT " ";
  68. }
  69. const char *warn_reminder = "";
  70. switch (level) {
  71. case LogLevel::ERROR:
  72. if (sys::stderr_ansi_color())
  73. warn_reminder = "\x1b[1;4;31m[ERR]\x1b[0m";
  74. else
  75. warn_reminder = "[ERR]";
  76. break;
  77. case LogLevel::WARN:
  78. if (sys::stderr_ansi_color())
  79. warn_reminder = "\x1b[1;31m[WARN]\x1b[0m";
  80. else
  81. warn_reminder = "[WARN]";
  82. break;
  83. case LogLevel::INFO:
  84. break;
  85. case LogLevel::DEBUG:
  86. if (sys::stderr_ansi_color())
  87. warn_reminder = "\x1b[36m[DEBUG]\x1b[0m";
  88. else
  89. warn_reminder = "[DEBUG]";
  90. break;
  91. default:
  92. mgb_throw(MegBrainError, "bad log level");
  93. }
  94. char timestr[64];
  95. #if MGB_EXTERN_API_TIME
  96. {
  97. static int64_t sec_start, nsec_start;
  98. int64_t sec, nsec;
  99. mgb_extern_api_get_time(&sec, &nsec);
  100. if (!sec_start) {
  101. sec_start = sec;
  102. nsec_start = nsec;
  103. }
  104. sec -= sec_start;
  105. nsec -= nsec_start;
  106. if (nsec < 0) {
  107. -- sec;
  108. nsec += 1000000000;
  109. }
  110. snprintf(timestr, sizeof(timestr), "%.3f",
  111. static_cast<int>(sec) + static_cast<int>(nsec) * 1e-9);
  112. }
  113. #else
  114. {
  115. time_t cur_time;
  116. MGB_LOCK_GUARD(mtx);
  117. time(&cur_time);
  118. strftime(timestr, sizeof(timestr), "%d %H:%M:%S", localtime(&cur_time));
  119. }
  120. #endif
  121. {
  122. // find file basename part
  123. auto f0 = file;
  124. file = f0 + strlen(f0) - 1;
  125. while (file >= f0 && *file != '/' && *file != '\\')
  126. -- file;
  127. ++ file;
  128. }
  129. {
  130. MGB_LOCK_GUARD(mtx);
  131. fprintf(stderr, hdr_fmt, timestr, func, file, line, warn_reminder);
  132. vfprintf(stderr, fmt, ap);
  133. fputc('\n', stderr);
  134. }
  135. #ifdef __ANDROID__
  136. android_LogPriority android_level;
  137. switch (level) {
  138. case LogLevel::WARN:
  139. android_level = ANDROID_LOG_WARN;
  140. break;
  141. case LogLevel::INFO:
  142. android_level = ANDROID_LOG_INFO;
  143. break;
  144. case LogLevel::DEBUG:
  145. android_level = ANDROID_LOG_DEBUG;
  146. break;
  147. default:
  148. android_level = ANDROID_LOG_ERROR;
  149. }
  150. __android_log_vprint(android_level, "runtime", fmt, ap);
  151. #endif
  152. #undef HDR_FMT
  153. }
  154. LogHandler log_handler = default_log_handler;
  155. class MegDNNLogHandler {
  156. static void dnn_log_handler(megdnn::LogLevel dnn_level, const char* file,
  157. const char* func, int line, const char* fmt,
  158. va_list ap) {
  159. mgb::LogLevel mgb_level;
  160. switch (dnn_level) {
  161. case megdnn::LogLevel::DEBUG:
  162. mgb_level = LogLevel::DEBUG;
  163. break;
  164. case megdnn::LogLevel::INFO:
  165. mgb_level = LogLevel::INFO;
  166. break;
  167. case megdnn::LogLevel::WARN:
  168. mgb_level = LogLevel::WARN;
  169. break;
  170. default:
  171. mgb_level = LogLevel::ERROR;
  172. }
  173. if (mgb_level < min_log_level) {
  174. return;
  175. }
  176. std::string new_fmt{"[dnn] "};
  177. new_fmt.append(fmt);
  178. log_handler(mgb_level, file, func, line, new_fmt.c_str(), ap);
  179. }
  180. public:
  181. MegDNNLogHandler() { megdnn::set_log_handler(dnn_log_handler); }
  182. };
  183. MegDNNLogHandler g_megdnn_log_handler_init;
  184. } // anonymous namespace
  185. void mgb::__log__(LogLevel level,
  186. const char *file, const char *func, int line, const char *fmt, ...) {
  187. if (level < min_log_level)
  188. return;
  189. va_list ap;
  190. va_start(ap, fmt);
  191. log_handler(level, file, func, line, fmt, ap);
  192. va_end(ap);
  193. }
  194. /* ===================== forward log in MegWave ===================== */
  195. // common::Log is a weak symbol in megwave
  196. namespace common {
  197. enum class LogLevel { kInfo, kWarn, kDebug, kFatal };
  198. void Log(LogLevel level, char const* file, int line, char const* func,
  199. char const *fmt, ...) {
  200. std::string new_fmt("[wave] ");
  201. new_fmt.append(fmt);
  202. va_list ap;
  203. va_start(ap, fmt);
  204. log_handler(level == LogLevel::kWarn ? mgb::LogLevel::WARN :
  205. mgb::LogLevel::DEBUG,
  206. file, func, line, new_fmt.c_str(), ap);
  207. va_end(ap);
  208. }
  209. }
  210. #else // MGB_ENABLE_LOGGING
  211. namespace {
  212. void default_log_handler(LogLevel ,
  213. const char *, const char *, int , const char *,
  214. va_list ) {
  215. }
  216. LogHandler log_handler = default_log_handler;
  217. }
  218. #endif // MGB_ENABLE_LOGGING
  219. LogLevel mgb::set_log_level(LogLevel level) {
  220. if (auto env = ::std::getenv("RUNTIME_OVERRIDE_LOG_LEVEL"))
  221. level = static_cast<LogLevel>(std::stoi(env));
  222. #ifdef __ANDROID__
  223. //! special for Android prop, attention: getprop may need permission
  224. char buf[PROP_VALUE_MAX];
  225. if (__system_property_get("RUNTIME_OVERRIDE_LOG_LEVEL", buf) > 0) {
  226. level = static_cast<LogLevel>(atoi(buf));
  227. }
  228. #endif
  229. auto ret = min_log_level;
  230. min_log_level = level;
  231. return ret;
  232. }
  233. LogLevel mgb::get_log_level() {
  234. return min_log_level;
  235. }
  236. LogHandler mgb::set_log_handler(LogHandler handler) {
  237. auto ret = log_handler;
  238. log_handler = handler;
  239. return ret;
  240. }
  241. void mgb::__assert_fail__(
  242. const char *file, int line, const char *func,
  243. const char *expr, const char *msg_fmt, ...) {
  244. std::string msg = ssprintf("assertion `%s' failed at %s:%d: %s",
  245. expr, file, line, func);
  246. if (msg_fmt) {
  247. msg_fmt = convert_fmt_str(msg_fmt);
  248. va_list ap;
  249. va_start(ap, msg_fmt);
  250. msg.append("\nextra message: ");
  251. msg.append(svsprintf(msg_fmt, ap));
  252. va_end(ap);
  253. }
  254. mgb_throw_raw(AssertionError{msg});
  255. }
  256. #if MGB_ENABLE_LOGGING && !MGB_ENABLE_EXCEPTION
  257. void mgb::__on_exception_throw__(const std::exception &exc) {
  258. mgb_log_error("exception thrown: %s", exc.what());
  259. mgb_log_error("abort now due to previous error");
  260. mgb_trap();
  261. }
  262. #endif
  263. std::string mgb::svsprintf(const char *fmt, va_list ap_orig) {
  264. fmt = convert_fmt_str(fmt);
  265. int size = 100; /* Guess we need no more than 100 bytes */
  266. char *p;
  267. if ((p = (char*)malloc(size)) == nullptr)
  268. goto err;
  269. for (; ;) {
  270. va_list ap;
  271. va_copy(ap, ap_orig);
  272. int n = vsnprintf(p, size, fmt, ap);
  273. va_end(ap);
  274. #ifdef WIN32
  275. if (n == -1) {
  276. n = _vscprintf(fmt, ap_orig);
  277. mgb_assert(n >= size);
  278. }
  279. #endif
  280. if (n < 0)
  281. goto err;
  282. if (n < size) {
  283. std::string rst(p);
  284. free(p);
  285. return rst;
  286. }
  287. size = n + 1;
  288. char *np = (char*)realloc(p, size);
  289. if (!np) {
  290. free(p);
  291. goto err;
  292. } else
  293. p = np;
  294. }
  295. err:
  296. fprintf(stderr, "could not allocate memory for svsprintf; fmt=%s\n",
  297. fmt);
  298. mgb_trap();
  299. }
  300. std::string mgb::ssprintf(const char *fmt, ...) {
  301. va_list ap;
  302. va_start(ap, fmt);
  303. auto rst = svsprintf(fmt, ap);
  304. va_end(ap);
  305. return rst;
  306. }
  307. // vim: syntax=cpp.doxygen foldmethod=marker foldmarker=f{{{,f}}}

MegEngine 安装包中集成了使用 GPU 运行代码所需的 CUDA 环境,不用区分 CPU 和 GPU 版。 如果想要运行 GPU 程序,请确保机器本身配有 GPU 硬件设备并安装好驱动。 如果你想体验在云端 GPU 算力平台进行深度学习开发的感觉,欢迎访问 MegStudio 平台