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 10 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /**
  2. * \file imperative/python/src/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 "./common.h"
  12. #include <pybind11/operators.h>
  13. #include "./helper.h"
  14. #include "./numpy_dtypes.h"
  15. #include "megbrain/comp_node.h"
  16. #include "megbrain/graph.h"
  17. #include "megbrain/imperative/physical_tensor.h"
  18. namespace py = pybind11;
  19. using namespace mgb;
  20. using namespace imperative;
  21. namespace {
  22. template <typename XTensorND>
  23. auto def_TensorND(py::object parent, const char* name) {
  24. return py::class_<XTensorND>(parent, name)
  25. .def_property_readonly(
  26. "shape", py::overload_cast<>(&XTensorND::shape, py::const_))
  27. .def_property_readonly(
  28. "dtype", py::overload_cast<>(&XTensorND::dtype, py::const_))
  29. .def_property_readonly(
  30. "comp_node", py::overload_cast<>(&XTensorND::comp_node, py::const_))
  31. .def("copy_from", &XTensorND::template copy_from<DeviceTensorStorage>)
  32. .def("copy_from", &XTensorND::template copy_from<HostTensorStorage>)
  33. .def("copy_from_fixlayout",
  34. py::overload_cast<const DeviceTensorND&>(
  35. &XTensorND::template copy_from_fixlayout<DeviceTensorStorage>))
  36. .def("copy_from_fixlayout",
  37. py::overload_cast<const HostTensorND&>(
  38. &XTensorND::template copy_from_fixlayout<HostTensorStorage>));
  39. }
  40. std::string default_device = "xpux";
  41. } // namespace
  42. void set_default_device(const std::string& device) {
  43. default_device = device;
  44. }
  45. std::string get_default_device() {
  46. return default_device;
  47. }
  48. void init_common(py::module m) {
  49. auto PyCompNode =
  50. py::class_<CompNode>(m, "CompNode")
  51. .def(py::init())
  52. .def(py::init(
  53. py::overload_cast<const std::string&>(&CompNode::load)))
  54. .def_property_readonly(
  55. "logical_name",
  56. [](const CompNode& cn) { return cn.to_string_logical(); })
  57. .def_property_readonly(
  58. "physical_name",
  59. [](const CompNode& cn) { return cn.to_string(); })
  60. .def_property_readonly(
  61. "get_mem_status_bytes",
  62. [](const CompNode& cn) {
  63. return cn.get_mem_status_bytes();
  64. })
  65. .def_property_readonly(
  66. "get_used_memory",
  67. [](const CompNode& cn) { return cn.get_used_memory(); })
  68. .def_property_readonly(
  69. "get_max_used_memory",
  70. [](const CompNode& cn) { return cn.get_max_used_memory(); })
  71. .def_property_readonly(
  72. "get_reserved_memory",
  73. [](const CompNode& cn) { return cn.get_reserved_memory(); })
  74. .def_property_readonly(
  75. "get_max_reserved_memory",
  76. [](const CompNode& cn) {
  77. return cn.get_max_reserved_memory();
  78. })
  79. .def_static(
  80. "reset_max_memory_stats",
  81. [](const CompNode& cn) {
  82. cn.reset_max_used_memory();
  83. cn.reset_max_reserved_memory();
  84. })
  85. .def("create_event", &CompNode::create_event,
  86. py::arg("flags") = 0ul)
  87. .def_static("_set_default_device", &set_default_device)
  88. .def_static("_get_default_device", &get_default_device)
  89. .def("__str__", &CompNode::to_string_logical)
  90. .def("__repr__",
  91. [](const CompNode& cn) {
  92. return mgb::ssprintf(
  93. "CompNode(\"%s\" from \"%s\")",
  94. cn.to_string_physical().c_str(),
  95. cn.to_string_logical().c_str());
  96. })
  97. .def("__hash__", [](CompNode cn) { return mgb::hash(cn); })
  98. .def_static("_sync_all", &CompNode::sync_all)
  99. .def(py::self == py::self)
  100. .def_static(
  101. "_get_device_count", &CompNode::get_device_count,
  102. "Get total number of specific devices on this system")
  103. .def(py::pickle(
  104. [](const CompNode& cn) {
  105. return py::str(cn.to_string_logical());
  106. },
  107. [](py::str cn) { return CompNode::load(cn); }));
  108. py::class_<CompNode::Event, std::shared_ptr<CompNode::Event>>(PyCompNode, "Event")
  109. .def("record", &CompNode::Event::record)
  110. .def("wait", &CompNode::Event::host_wait);
  111. py::implicitly_convertible<std::string, CompNode>();
  112. def_TensorND<DeviceTensorND>(m, "DeviceTensorND")
  113. .def("numpy", [](const DeviceTensorND& self) {
  114. HostTensorND hv;
  115. hv.copy_from(self).sync();
  116. return py::handle(
  117. npy::ndarray_from_tensor(hv, npy::ShareType::TRY_SHARE));
  118. });
  119. def_TensorND<HostTensorND>(m, "HostTensorND")
  120. .def(py::init([](py::array data, CompNode cn, DType dtype) {
  121. if (!cn.valid()) {
  122. throw py::type_error("device must not be None");
  123. }
  124. return npy::np2tensor(data.ptr(), npy::Meth::borrow(cn), dtype);
  125. }))
  126. .def("numpy", [](const HostTensorND& self) {
  127. return py::reinterpret_steal<py::object>(
  128. npy::ndarray_from_tensor(self, npy::ShareType::TRY_SHARE));
  129. });
  130. py::class_<cg::OperatorNodeConfig>(m, "OperatorNodeConfig")
  131. .def(py::init())
  132. .def_property(
  133. "name",
  134. [](const OperatorNodeConfig& config) -> py::object {
  135. auto name = config.name();
  136. if (name.valid()) {
  137. return py::str(name.val());
  138. } else {
  139. return py::none();
  140. }
  141. },
  142. [](OperatorNodeConfig& config, std::string name) {
  143. config.name(std::move(name));
  144. })
  145. .def_property(
  146. "dtype",
  147. [](const OperatorNodeConfig& config) {
  148. return config.output_dtype();
  149. },
  150. [](OperatorNodeConfig& config, DType dtype) {
  151. config.output_dtype(dtype);
  152. })
  153. .def_property(
  154. "comp_node_arr",
  155. [](const OperatorNodeConfig& config) -> py::tuple {
  156. auto arr = config.comp_node();
  157. std::vector<CompNode> tmp(arr.begin(), arr.end());
  158. return py::cast(tmp);
  159. },
  160. [](OperatorNodeConfig& config, std::vector<CompNode> cns) {
  161. config.comp_node_arr({cns.begin(), cns.end()});
  162. })
  163. .def_property(
  164. "comp_node",
  165. [](const OperatorNodeConfig& config) {
  166. auto arr = config.comp_node();
  167. if (arr.size() != 1) {
  168. throw py::value_error("invalid number of comp_node");
  169. }
  170. return arr[0];
  171. },
  172. [](OperatorNodeConfig& config, CompNode cn) {
  173. OperatorNodeConfig::CompNodeArray arr{cn};
  174. config.comp_node_arr(arr);
  175. });
  176. py::class_<LogicalTensorDesc>(m, "TensorAttr")
  177. .def(py::init())
  178. .def(py::init([](const TensorShape& shape, const DType& dtype,
  179. const CompNode& comp_node) {
  180. return LogicalTensorDesc{TensorLayout{shape, dtype}, comp_node};
  181. }))
  182. .def_property(
  183. "shape",
  184. [](const LogicalTensorDesc& desc) {
  185. return static_cast<TensorShape>(desc.layout);
  186. },
  187. [](LogicalTensorDesc& desc, TensorShape shape) {})
  188. .def_property(
  189. "dtype",
  190. [](const LogicalTensorDesc& desc) { return desc.layout.dtype; },
  191. [](LogicalTensorDesc& desc, DType dtype) {
  192. desc.layout.dtype = dtype;
  193. })
  194. .def_readwrite("comp_node", &LogicalTensorDesc::comp_node);
  195. py::enum_<CompNode::DeviceType>(m, "DeviceType")
  196. .value("UNSPEC", CompNode::DeviceType::UNSPEC)
  197. .value("CUDA", CompNode::DeviceType::CUDA)
  198. .value("ROCM", CompNode::DeviceType::ROCM)
  199. .value("CPU", CompNode::DeviceType::CPU)
  200. .value("CAMBRICON", CompNode::DeviceType::CAMBRICON)
  201. .value("ATLAS", CompNode::DeviceType::ATLAS)
  202. .value("MULTITHREAD", CompNode::DeviceType::MULTITHREAD)
  203. .value("MAX_DEVICE_ID", CompNode::DeviceType::MAX_DEVICE_ID);
  204. m.def("set_prealloc_config", &CompNode::set_prealloc_config,
  205. "specifies how to pre-allocate from raw dev allocator");
  206. m.def("get_cuda_compute_capability", &CompNode::get_compute_capability);
  207. m.def("what_is_xpu",
  208. [] { return CompNode::Locator::parse("xpux").to_physical().type; });
  209. init_npy_num_bfloat16(m);
  210. init_npy_num_intbx(m);
  211. init_dtypes(m);
  212. }