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.

config.py 14 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. # -*- coding: utf-8 -*-
  2. # MegEngine is Licensed under the Apache License, Version 2.0 (the "License")
  3. #
  4. # Copyright (c) 2014-2020 Megvii Inc. All rights reserved.
  5. #
  6. # Unless required by applicable law or agreed to in writing,
  7. # software distributed under the License is distributed on an
  8. # "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. import collections
  10. import os
  11. from . import mgb as _mgb
  12. _default_device_type = "CUDA"
  13. def set_device_map(logical_dev, physical_dev, device_type=None):
  14. """map from *logical_dev* to *physical_dev* for furture comp node
  15. loading
  16. example::
  17. set_device_map(0, 2, 'CPU') # cpu0 -> cpu2
  18. set_device_map('gpu3', 'gpu0') # gpu0 -> gpu0
  19. :param device_type: specify the device type if devices are given by
  20. integers; if devices are given by integers and ``device_type`` is not
  21. given, the default value ``'CUDA'`` would be used. Possible values are
  22. ``'CUDA'`` and ``'CPU'``.
  23. """
  24. if device_type is None:
  25. device_type = _default_device_type
  26. if device_type == "CUDA":
  27. xpu = "gpu"
  28. else:
  29. assert device_type == "CPU"
  30. xpu = "cpu"
  31. def rmxpu(v):
  32. if isinstance(v, str):
  33. assert v.startswith(xpu) or v.startswith("xpu"), (
  34. "bad comp node in set_device_map: "
  35. "device_type={} comp_node={}".format(device_type, v)
  36. )
  37. return v[3:]
  38. return v
  39. logical_dev, physical_dev = map(rmxpu, [logical_dev, physical_dev])
  40. _mgb.CompNode._set_device_map(device_type, int(logical_dev), int(physical_dev))
  41. def set_default_device(physical_dev, device_type=None):
  42. """set physcal device for xpux
  43. when *device_type* is None and *physical_dev* starts with *gpu* or *cpu*,
  44. the default device type would be modified accordingly for future calls to
  45. :func:`set_device_map` when remapping device number.
  46. """
  47. global _default_device_type
  48. if (
  49. device_type is None
  50. and isinstance(physical_dev, str)
  51. and not physical_dev.isdigit()
  52. and not physical_dev.startswith("xpu")
  53. ):
  54. t = physical_dev[:3]
  55. if t == "gpu":
  56. _default_device_type = "CUDA"
  57. else:
  58. assert t == "cpu", "bad physical_dev: {}".format(physical_dev)
  59. _default_device_type = "CPU"
  60. set_default_device_type(_default_device_type)
  61. device_type = _default_device_type
  62. set_device_map(-1, physical_dev, device_type)
  63. def set_default_device_type(device_type):
  64. """set device type for xpu"""
  65. global _default_device_type
  66. device_type = device_type.upper()
  67. _mgb.CompNode._set_unspec_device_type(device_type)
  68. _default_device_type = device_type
  69. def set_fork_cuda_warning_flag(flag):
  70. """set warning to be printed at fork if cuda has been initialized
  71. :type flag: int
  72. :param flag: controls how the warning should be printed:
  73. * 0: disable warning
  74. * 1: print warning to log
  75. * 2: print warning to log and raise exception
  76. """
  77. _mgb._config.set_fork_cuda_warning_flag(int(flag))
  78. def get_device_count(device_type="xpu", warn=True):
  79. """get number of devices installed on this system
  80. :param device_type: device type, one of 'xpu', 'gpu' or 'cpu'
  81. :type device_type: str
  82. """
  83. return _mgb.CompNode._get_device_count(device_type.upper(), warn)
  84. def set_mem_reserve_size(size):
  85. """set memory reserve size:
  86. * If *size* is greater than 1, it is the absolute amount of memory to
  87. be reserved in MB;
  88. * If *size* is in the range (0, 1), it is the ratio of total memory;
  89. * If *size* is 0, memory reservation and pre-allocation would be
  90. disabled;
  91. * If *size* is -1, disable custom memory allocator and use cuda APIs
  92. directly.
  93. """
  94. _mgb._config.set_mem_reserve_size(float(size))
  95. def set_comp_graph_option(comp_graph, name, val):
  96. """set computing graph option and return its old value
  97. :type comp_graph: :class:`.CompGraph`
  98. :param comp_graph: the computing graph whose option should be modified
  99. :type name: str
  100. :param name: option name
  101. Currently supported options are:
  102. * "no_profiling_on_shape_change": bool;
  103. When execution strategy is set to profiling, always use the
  104. initial profile result and do not re-run profiling even if input
  105. shape changes.
  106. * "seq_opt.enable_mem_plan_opt": bool
  107. * "seq_opt.enable_mem_reuse_alloc": bool
  108. * "seq_opt.enable_seq_comp_node_opt": bool
  109. * "force_dynamic_alloc": bool
  110. * "var_sanity_check_first_run": bool
  111. * "enable_sublinear_memory_opt": bool
  112. * "enable_memory_swap": bool; whether to enable memory swap; it
  113. usually performs worse than sublinear memory
  114. * "enable_var_mem_defragment": bool
  115. * "allocate_static_mem_after_graph_compile": bool
  116. * "enable_grad_var_static_reshape": bool:
  117. If set to ``True``, dynamically-shaped gradients whose original
  118. shape is statically inferrable would be reshaped, so static
  119. shape inference can continue
  120. * "async_exec_level": int
  121. * ``0``: do not dispatch asynchronously
  122. * ``1``: async dispatch if there are more than 1 cuda comp
  123. nodes
  124. * mask ``0b10``: async for comp nodes with unlimited queue
  125. (e.g. CPU comp nodes)
  126. * mask ``0b100``: async for even one comp node
  127. * "log_level": int
  128. * ``0``: no log info for graph construction/compiling
  129. * ``1``: static memory allocation status,
  130. WorkspaceLimitGetter summary, and optimizer summary
  131. * ``2``: optimizer details and duplicated operators tha are
  132. removed
  133. * "graph_opt.jit": whether to enable JIT
  134. * "graph_opt.tensorrt": whether to enable fine-grained automatic
  135. replacement for TensorRT operators
  136. * "graph_opt.android_nn": whether to enable fine-grained automatic
  137. replacement for Android NN operators
  138. * "graph_opt_level": int
  139. * ``0``: disable
  140. * ``1``: level-1: inplace arith transformations during graph
  141. construction
  142. * ``2``: (default) level-2: level-1, plus global optimization
  143. before graph compiling
  144. * ``3``: also enable JIT
  145. :param val: new option value
  146. :return: old option value
  147. """
  148. if name == "log_static_mem_alloc":
  149. name = "log_level"
  150. if name == "enable_async_exec":
  151. name = "async_exec_level"
  152. return _mgb._config.set_comp_graph_option(comp_graph, name, int(val))
  153. def comp_graph_is_eager(comp_graph):
  154. return _mgb._config.comp_graph_is_eager(comp_graph)
  155. def add_extra_vardep(var, dep):
  156. """add *dep* as an extra dependency of *var*, so if *var* is required to
  157. compute the final output when compiling a comp graph, *dep* would also be
  158. included in the computing sequence. Note that the order computing of these
  159. two vars is not guaranteed.
  160. """
  161. assert isinstance(var, _mgb.SymbolVar) and isinstance(dep, _mgb.SymbolVar)
  162. assert var.owner_graph == dep.owner_graph
  163. return _mgb._config.add_extra_vardep(var, dep)
  164. class _GraphPropertyBase:
  165. """helper class for implementing operator property setter context managers"""
  166. _cur_graph = None
  167. _graph2stack = None
  168. """class attribute that maintains mapping from graph to property stack;
  169. should be defined by child classes"""
  170. __prop_setup__ = None
  171. """overwritten by subclass to setup property"""
  172. __prop_clear__ = None
  173. """overwritten by subclass to clear property"""
  174. def __init__(self, comp_graph, prop):
  175. """:param comp_graph: computing graph, or None to not set this
  176. property"""
  177. if comp_graph is not None:
  178. assert isinstance(
  179. comp_graph, _mgb.CompGraph
  180. ), "invalid comp graph: {!r}".format(comp_graph)
  181. self._cur_graph = comp_graph
  182. self._graph2stack.setdefault(comp_graph, []).append(prop)
  183. def __setup(self, prop):
  184. self.__prop_setup__(self._cur_graph, prop)
  185. def __clear(self):
  186. self.__prop_clear__(self._cur_graph)
  187. def __enter__(self):
  188. if self._cur_graph is None:
  189. return
  190. stack = self._graph2stack[self._cur_graph]
  191. if len(stack) > 1:
  192. # clear nested property
  193. self.__clear()
  194. self.__setup(stack[-1])
  195. def __exit__(self, exc_type, exc_value, exc_traceback):
  196. if self._cur_graph is None:
  197. return
  198. stack = self._graph2stack[self._cur_graph]
  199. self.__clear()
  200. stack.pop()
  201. if stack:
  202. # restore nested property
  203. self.__setup(stack[-1])
  204. else:
  205. del self._graph2stack[self._cur_graph]
  206. class exc_opr_tracker_scope(_GraphPropertyBase):
  207. """context manager for associating an object with all operators created
  208. within this context; so when an exception is raised, information about the
  209. corresponding operator could be retrieved from
  210. :attr:`.MegBrainError.tracker`
  211. :param comp_graph: the computing graph where the operators should be tracked
  212. :type comp_graph: :class:`.CompGraph`
  213. :param tracker: an arbitrary python object to track the operators
  214. """
  215. _graph2stack = {}
  216. def __init__(self, comp_graph, tracker):
  217. assert (
  218. tracker is not None
  219. ), "bad args for exc_opr_tracker_scope: {!r} {!r}".format(comp_graph, tracker)
  220. super().__init__(comp_graph, tracker)
  221. __prop_setup__ = _mgb._config.begin_set_exc_opr_tracker
  222. __prop_clear__ = _mgb._config.end_set_exc_opr_tracker
  223. class opr_priority_scope(_GraphPropertyBase):
  224. """context manager for setting priority for all operators created in this
  225. context
  226. :param comp_graph: the computing graph for which operator priority should
  227. be set
  228. :type comp_graph: :class:`.CompGraph`
  229. :param priority: operator priority. Smaller number means higher priority.
  230. Default value is 0. Grad operator would use negative priority by
  231. default.
  232. """
  233. _graph2stack = {}
  234. LOWEST_PRIORITY = 2 ** 31 - 1
  235. """lowest prority (i.e. max possible value)"""
  236. HIGHEST_PRIORITY = -LOWEST_PRIORITY
  237. """highest prority (i.e. min possible value)"""
  238. def __init__(self, comp_graph, priority):
  239. super().__init__(comp_graph, int(priority))
  240. __prop_setup__ = _mgb._config.begin_set_opr_priority
  241. __prop_clear__ = _mgb._config.end_set_opr_priority
  242. OprTrackerResult = collections.namedtuple(
  243. "OprTrackerResult", ["msg", "tracker", "grad_tracker"]
  244. )
  245. def get_opr_tracker(cg, var_id):
  246. """get the tracking object associated with the owner operator of a var
  247. :param cg: the computing graph
  248. :param var_id: id of the var whose owner opr tracker should be found
  249. :return: if no var is found, ``None`` is returned; otherwise return an
  250. :class:`OprTrackerResult` object
  251. """
  252. assert isinstance(cg, _mgb.CompGraph)
  253. ret = _mgb._config.get_opr_tracker(cg, int(var_id))
  254. if ret is None:
  255. return
  256. return OprTrackerResult(*ret)
  257. def set_opr_sublinear_memory_endpoint(var):
  258. """set the owner operator of a symvar to be endpoint of sublinear memory
  259. optimizer
  260. :type var: :class:`.SymbolVar`
  261. """
  262. _mgb._config.set_opr_sublinear_memory_endpoint(var)
  263. def max_size_t():
  264. """get max value of size_t type on local architecture"""
  265. return _mgb.max_size_t()
  266. def is_cuda_ctx_set():
  267. """return whether current thread has an active cuda driver context"""
  268. return _mgb._config.is_cuda_ctx_set()
  269. def get_include_path():
  270. """get include path for building megbrain extensions"""
  271. return os.path.join(os.path.realpath(os.path.dirname(__file__)), "include")
  272. def get_cuda_gencode(only_cap=False):
  273. """get -gencode options to be passed to nvcc for compiling on local
  274. machine
  275. :param only_cap: if True, return only a list of cuda compute capability
  276. strings (like ``['35', '52']`` )
  277. """
  278. ret = _mgb._config.get_cuda_gencode().split()
  279. if not only_cap:
  280. ret = " ".join(map("-gencode arch=compute_{0},code=sm_{0}".format, ret))
  281. return ret
  282. def get_cuda_lib_path():
  283. """get the cuda root path by locating loaded libcudart.so
  284. """
  285. return _mgb._config.get_cuda_lib_path()
  286. def get_cuda_include_path():
  287. """get the cuda include path by locating loaded libcudart.so, including
  288. libcudart.so's path, parent path and `parent path`/include
  289. """
  290. return _mgb._config.get_cuda_include_path()
  291. def get_cuda_version():
  292. """get runtime cuda version
  293. """
  294. return _mgb._config.get_cuda_version()
  295. def is_compiled_with_cuda():
  296. """whether cuda is enabled at compile time"""
  297. return _mgb._config.is_compiled_with_cuda()
  298. def load_opr_library(path):
  299. """Load an external operator library. This essentially sets megbrain
  300. symbols as public and load the library.
  301. :param path: path to the shared object; if it is None, then only megbrain
  302. symbols are made public.
  303. """
  304. _mgb._config.load_opr_library(
  305. os.path.realpath(os.path.join(os.path.dirname(__file__), "_mgb.so")), path
  306. )
  307. def dump_registered_oprs():
  308. """
  309. get all registered oprs, return dict(id, name)
  310. """
  311. return dict(_mgb._config.dump_registered_oprs())
  312. def create_mm_server(server_addr, port):
  313. """
  314. create mm server with server address
  315. throw exception if server_addr is already used
  316. """
  317. return _mgb._config.create_mm_server(server_addr, port)
  318. def group_barrier(server_addr, port, size, rank):
  319. """
  320. block until all ranks reach this barrier
  321. """
  322. return _mgb._config.group_barrier(server_addr, port, size, rank)

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

Contributors (1)