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.

imperative.cpp 7.6 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. #include "./helper.h"
  2. #include "megbrain/comp_node_env.h"
  3. #include "megbrain/imperative/blob_manager.h"
  4. #include "megbrain/imperative/ops/autogen.h"
  5. #include "megbrain/imperative/ops/opr_attr.h"
  6. #include "megbrain/opr/basic_arith.h"
  7. #include "megbrain/opr/basic_arith_wrapper.h"
  8. #include "megbrain/opr/blas.h"
  9. #include "megbrain/opr/dnn/batch_norm.h"
  10. #include "megbrain/opr/dnn/convolution.h"
  11. #include "megbrain/opr/tensor_manip.h"
  12. #include "megbrain/opr/utility.h"
  13. using namespace mgb;
  14. using namespace cg;
  15. using namespace imperative;
  16. TEST(TestImperative, APlusB) {
  17. auto op = OprAttr::make("Elemwise");
  18. auto&& attr = op->cast_final_safe<OprAttr>();
  19. using Param = opr::Elemwise::Param;
  20. Param param{Param::Mode::ADD};
  21. attr.param.write_pod(param);
  22. OprChecker(op).run({TensorShape{42}, TensorShape{42}});
  23. }
  24. TEST(TestImperative, Convolution) {
  25. auto op = OprAttr::make("ConvolutionV2");
  26. auto&& attr = op->cast_final_safe<OprAttr>();
  27. using Param = opr::Convolution::Param;
  28. using Policy = opr::Convolution::ExecutionPolicy;
  29. Param param{Param::Mode::CONVOLUTION};
  30. Policy policy{Policy::Strategy::HEURISTIC};
  31. attr.param.write_pod(param);
  32. attr.param.write_pod(policy);
  33. size_t N = 4, IC = 3, OC = 8, FH = 3, FW = 3, IH = 16, IW = 16;
  34. OprChecker(op).run({TensorShape{N, IC, IH, IW}, TensorShape{OC, IC, FH, FW}});
  35. }
  36. TEST(TestImperative, Reduce) {
  37. auto op = OprAttr::make("ReduceV2");
  38. auto&& attr = op->cast_final_safe<OprAttr>();
  39. using Param = opr::Reduce::Param;
  40. Param param{Param::Mode::SUM_SQR};
  41. attr.param.write_pod(param);
  42. HostTensorND one{CompNode::load("xpu0"), {{1}, dtype::Int32()}};
  43. one.ptr<int>()[0] = 1;
  44. OprChecker(op).run({TensorShape{2, 3, 4}, one});
  45. }
  46. TEST(TestImperative, BatchNorm) {
  47. auto op = OprAttr::make("BatchNormV1");
  48. auto&& attr = op->cast_final_safe<OprAttr>();
  49. using Param = opr::BatchNorm::Param;
  50. Param param;
  51. param.param_dim = Param::ParamDim::DIM_1C11;
  52. param.avg_factor = 0.999;
  53. attr.param.write_pod(param);
  54. size_t N = 2, C = 3, H = 5, W = 5;
  55. OprChecker(op).run(
  56. {TensorShape{N, C, H, W}, TensorShape{1, C, 1, 1}, TensorShape{1, C, 1, 1},
  57. TensorShape{1, C, 1, 1}, TensorShape{1, C, 1, 1}},
  58. {4});
  59. }
  60. TEST(TestImperative, Concat) {
  61. REQUIRE_XPU(2);
  62. OprAttr::Param param;
  63. param.write_pod(megdnn::param::Axis(0));
  64. OperatorNodeConfig config{CompNode::load("xpu1")};
  65. OprChecker(OprAttr::make("Concat", param, config))
  66. .run({TensorShape{200, 300}, TensorShape{300, 300}});
  67. }
  68. TEST(TestImperative, Split) {
  69. OprAttr::Param param;
  70. param.write_pod(megdnn::param::Axis(0));
  71. auto op = OprAttr::make("Split", param, OperatorNodeConfig{});
  72. auto cn = CompNode::load("xpu0");
  73. HostTensorND s1{cn, {{1}, dtype::Int32()}};
  74. s1.ptr<int>()[0] = 20;
  75. HostTensorND s2{cn, {{1}, dtype::Int32()}};
  76. s2.ptr<int>()[0] = 80;
  77. OprChecker(op).run({TensorShape{100}, s1, s2});
  78. }
  79. #if MGB_CUDA && MGB_ENABLE_EXCEPTION
  80. void run_graph(size_t mem_reserved) {
  81. CompNode::try_coalesce_all_free_memory();
  82. CompNode::finalize();
  83. auto cn = CompNode::load("gpux");
  84. cn.sync(); // wait for async init to finish
  85. HostTensorGenerator<> gen;
  86. using TensorPtr = std::shared_ptr<Tensor>;
  87. TensorPtr ptr_a[100];
  88. size_t unit_size = mem_reserved / (100.5 * 4);
  89. auto host_a = gen({unit_size});
  90. for (int i = 0; i < 100; ++i) {
  91. ptr_a[i] = Tensor::make(*host_a);
  92. }
  93. // free half
  94. for (int i = 0; i < 100; i += 2) {
  95. ptr_a[i].reset();
  96. }
  97. auto op = OprAttr::make("Elemwise");
  98. auto&& attr = op->cast_final_safe<OprAttr>();
  99. using Param = opr::Elemwise::Param;
  100. Param param{Param::Mode::MUL};
  101. attr.param.write_pod(param);
  102. SmallVector<LogicalTensorDesc> output_descs;
  103. auto out = OpDef::apply_on_physical_tensor(
  104. *op, {ptr_a[1], ptr_a[99]}, output_descs, false)
  105. .at(0);
  106. // value before defrag
  107. HostTensorND host_out_before;
  108. host_out_before.copy_from(out->dev_tensor()).sync();
  109. // make defrag work
  110. auto e = Tensor::make(*gen({unit_size * 10}));
  111. // value after defrag
  112. HostTensorND host_out_after;
  113. host_out_after.copy_from(out->dev_tensor()).sync();
  114. // make sure defragment do not change the value
  115. for (size_t i = 0; i < unit_size; ++i) {
  116. ASSERT_EQ(host_out_before.ptr<float>()[i], host_out_after.ptr<float>()[i]);
  117. }
  118. }
  119. TEST(TestImperative, Defragment) {
  120. #if WIN32
  121. //! FIXME, finalize on CUDA windows will be strip as windows CUDA101 DLL
  122. //! issue
  123. return;
  124. #endif
  125. REQUIRE_GPU(1);
  126. CompNode::load("gpux").activate();
  127. size_t reserve;
  128. {
  129. size_t free, tot;
  130. MGB_CUDA_CHECK(cudaMemGetInfo(&free, &tot));
  131. reserve = free * 0.92;
  132. }
  133. auto reserve_setting = ssprintf("b:%zu", reserve);
  134. auto do_run = [reserve]() { run_graph(reserve); };
  135. // reserve memory explicitly to avoid uncontrollable factors
  136. constexpr const char* KEY = "MGB_CUDA_RESERVE_MEMORY";
  137. auto old_value = getenv(KEY);
  138. setenv(KEY, reserve_setting.c_str(), 1);
  139. MGB_TRY { do_run(); }
  140. MGB_FINALLY(
  141. if (old_value) { setenv(KEY, old_value, 1); } else {
  142. unsetenv(KEY);
  143. } CompNode::try_coalesce_all_free_memory();
  144. CompNode::finalize(););
  145. }
  146. #endif // MGB_CUDA && MGB_ENABLE_EXCEPTION
  147. TEST(TestImperative, MatrixMulApplyOnVarNode) {
  148. using Param = opr::MatrixMul::Param;
  149. Param param;
  150. std::vector<std::pair<TensorShape, TensorShape>> shapes;
  151. std::vector<TensorShape> target_shapes;
  152. std::vector<Param> params;
  153. //! testcase 0
  154. params.push_back(param);
  155. shapes.push_back({TensorShape{10, 5}, TensorShape{5, 10}});
  156. target_shapes.push_back(TensorShape{10, 10});
  157. //! testcase 1
  158. params.push_back(param);
  159. shapes.push_back({TensorShape{3, 10, 5}, TensorShape{5, 10}});
  160. target_shapes.push_back(TensorShape{3, 10, 10});
  161. //! testcase 2
  162. param.transposeA = true;
  163. param.transposeB = false;
  164. params.push_back(param);
  165. shapes.push_back({TensorShape{3, 7, 6}, TensorShape{7, 10}});
  166. target_shapes.push_back(TensorShape{3, 6, 10});
  167. //! testcase 3
  168. param.transposeA = true;
  169. param.transposeB = false;
  170. params.push_back(param);
  171. shapes.push_back({TensorShape{2, 3, 7, 6}, TensorShape{7, 10}});
  172. target_shapes.push_back(TensorShape{2, 3, 6, 10});
  173. //! testcase 4
  174. param.transposeA = false;
  175. param.transposeB = true;
  176. params.push_back(param);
  177. shapes.push_back({TensorShape{2, 3, 7, 6}, TensorShape{2, 3, 8, 6}});
  178. target_shapes.push_back(TensorShape{2, 3, 7, 8});
  179. //! testcase 5
  180. param.transposeA = false;
  181. param.transposeB = true;
  182. params.push_back(param);
  183. shapes.push_back({TensorShape{2, 3, 7, 6}, TensorShape{8, 6}});
  184. target_shapes.push_back(TensorShape{2, 3, 7, 8});
  185. for (size_t i = 0; i < params.size(); i++) {
  186. auto& shape = shapes[i];
  187. auto op = MatrixMul::make(
  188. params[i], ::megdnn::param::ExecutionPolicy{}, shape.first.ndim,
  189. shape.second.ndim);
  190. auto result = OprChecker(op).run_apply_on_var_node({shape.first, shape.second});
  191. ASSERT_GT(result.size(), 0);
  192. ASSERT_EQ(target_shapes[i].ndim, result[0]->shape().ndim);
  193. for (size_t id = 0; id < target_shapes[i].ndim; id++) {
  194. ASSERT_EQ(target_shapes[i][id], result[0]->shape()[id]);
  195. }
  196. }
  197. }
  198. // vim: syntax=cpp.doxygen foldmethod=marker foldmarker=f{{{,f}}}