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.

convolution.cpp 7.2 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /**
  2. * \file dnn/test/cpu/convolution.cpp
  3. * MegEngine is Licensed under the Apache License, Version 2.0 (the "License")
  4. *
  5. * Copyright (c) 2014-2020 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 "test/cpu/fixture.h"
  12. #include "test/common/convolution.h"
  13. #include "test/common/checker.h"
  14. #include "test/common/benchmarker.h"
  15. using namespace megdnn;
  16. using namespace test;
  17. namespace {
  18. Convolution::Param gconv_param(Convolution::Param p) {
  19. p.sparse = Convolution::Param::Sparse::GROUP;
  20. return p;
  21. }
  22. } // anonymous namespace
  23. TEST_F(CPU, CONVOLUTION)
  24. {
  25. using namespace convolution;
  26. std::vector<TestArg> args = get_args();
  27. Checker<Convolution> checker(handle());
  28. for (auto &&arg: args) {
  29. checker.set_param(arg.param).execs({arg.src, arg.filter, {}});
  30. }
  31. }
  32. TEST_F(CPU, CONV_CONFIG_COMBINATIONS) {
  33. convolution::test_conv_config_combinations(handle(), true, false, false);
  34. }
  35. #if MEGDNN_WITH_BENCHMARK
  36. TEST_F(CPU, BENCHMARK_CONVOLUTION)
  37. {
  38. using TestArg = convolution::TestArg;
  39. using Param = param::Convolution;
  40. std::vector<TestArg> args;
  41. // case 1: detection-like (padding x stride x kernel_size)
  42. // clang-format off
  43. for (size_t has_pad = 0; has_pad < 2; ++has_pad)
  44. for (uint32_t stride = 1; stride <= 2; ++stride)
  45. for (std::pair<size_t, size_t> kersize :
  46. std::vector<std::pair<size_t, size_t>>{
  47. {2, 2}, {3, 3}, {5, 5}, {7, 7}}) {
  48. uint32_t pad_h, pad_w;
  49. if (has_pad)
  50. pad_h = kersize.first / 2;
  51. else
  52. pad_h = 0;
  53. if (has_pad)
  54. pad_w = kersize.second / 2;
  55. else
  56. pad_w = 0;
  57. auto param = Param{Param::Mode::CROSS_CORRELATION, pad_h, pad_w,
  58. stride, stride};
  59. {
  60. auto arg = TestArg{param,
  61. {2, 3, 320, 240},
  62. {4, 3, kersize.first, kersize.second}};
  63. args.push_back(arg);
  64. }
  65. }
  66. // clang-format on
  67. Checker<Convolution> checker(handle());
  68. checker.set_perf_check(true).set_perf_check_threshold(2.0);
  69. for (auto &&arg: args) {
  70. checker.set_param(arg.param).execs({arg.src, arg.filter, {}});
  71. }
  72. }
  73. #endif
  74. TEST_F(CPU, CHANWISE_CONVOLUTION)
  75. {
  76. constexpr auto M = Convolution::Mode::CROSS_CORRELATION;
  77. Checker<Convolution> checker(handle());
  78. checker.set_param(gconv_param({M, 0, 0, 1, 1})).
  79. execs({{1, 1, 2, 2}, {1, 1, 1, 2, 2}, {}}).
  80. execs({{1, 1, 5, 5}, {1, 1, 1, 2, 2}, {}}).
  81. execs({{2, 2, 5, 5}, {2, 3, 1, 2, 2}, {2, 6, 4, 4}});
  82. checker.set_param(gconv_param({M, 1, 1, 1, 1})).
  83. execs({{2, 2, 5, 5}, {2, 1, 1, 2, 2}, {}});
  84. checker.set_param(gconv_param({M, 2, 3, 2, 1})).
  85. execs({{32, 12, 20, 10}, {12, 2, 1, 4, 5}, {}});
  86. // padding larger than kern
  87. checker.set_param(gconv_param({M, 20, 30, 4, 5})).
  88. execs({{32, 12, 20, 10}, {12, 2, 1, 4, 5}, {}});
  89. }
  90. TEST_F(CPU, CHANWISE_CONVOLUTION_INT8_INT8_INT16)
  91. {
  92. constexpr auto M = Convolution::Mode::CROSS_CORRELATION;
  93. Checker<Convolution> checker(handle());
  94. checker.set_dtype(0, dtype::Int8());
  95. checker.set_dtype(1, dtype::Int8());
  96. checker.set_dtype(2, dtype::Int16());
  97. checker.set_param(gconv_param({M, 0, 0, 1, 1, 1, 1})).
  98. execs({{1, 1, 2, 2}, {1, 1, 1, 2, 2}, {}}).
  99. execs({{1, 1, 5, 5}, {1, 1, 1, 2, 2}, {}}).
  100. execs({{2, 2, 5, 5}, {2, 3, 1, 2, 2}, {2, 6, 4, 4}});
  101. checker.set_param(gconv_param({M, 1, 1, 1, 1, 1, 1})).
  102. execs({{2, 2, 5, 5}, {2, 1, 1, 2, 2}, {}});
  103. checker.set_param(gconv_param({M, 2, 3, 2, 1, 1, 1})).
  104. execs({{32, 12, 20, 10}, {12, 2, 1, 4, 5}, {}});
  105. // padding larger than kern
  106. checker.set_param(gconv_param({M, 20, 30, 4, 5, 1, 1})).
  107. execs({{32, 12, 20, 10}, {12, 2, 1, 4, 5}, {}});
  108. // clang-format off
  109. for (uint32_t s : {1, 2})
  110. for (uint32_t p : {0, 1})
  111. for (size_t kh : {2, 3, 5})
  112. for (size_t kw : {kh, kh + 1})
  113. for (size_t ic : {5})
  114. for (size_t oc : {3})
  115. for (size_t h = 20; h <= 60; h += 7)
  116. for (size_t w : {h, h + 1}) {
  117. checker.set_param(gconv_param({M, p, p, s, s, 1, 1}))
  118. .execs({{2, ic, h, w}, {ic, oc, 1, kh, kw}, {}});
  119. }
  120. // clang-format on
  121. }
  122. TEST_F(CPU, GROUP_CONV)
  123. {
  124. auto run = [&](size_t N, size_t IC, size_t IH, size_t IW,
  125. size_t FH, size_t FW,
  126. size_t OC, size_t /* OH */, size_t /* OW */,
  127. size_t PH, size_t PW,
  128. size_t SH, size_t SW,
  129. size_t group)
  130. {
  131. Checker<Convolution> checker(handle());
  132. Convolution::Param param;
  133. param.pad_h = PH;
  134. param.pad_w = PW;
  135. param.stride_h = SH;
  136. param.stride_w = SW;
  137. auto ICg = IC / group;
  138. auto OCg = OC / group;
  139. checker.set_param(gconv_param(param)).exec({{N, IC, IH, IW},
  140. {group, OCg, ICg, FH, FW}, {}});
  141. };
  142. // normal case
  143. run(2, 64, 7, 7,
  144. 3, 3,
  145. 32, 5, 5,
  146. 0, 0,
  147. 1, 1,
  148. 1);
  149. // padded case
  150. run(2, 32, 7, 7,
  151. 3, 3,
  152. 64, 7, 7,
  153. 1, 1,
  154. 1, 1,
  155. 4);
  156. // strided case
  157. run(2, 32, 7, 7,
  158. 3, 3,
  159. 64, 3, 3,
  160. 0, 0,
  161. 2, 2,
  162. 8);
  163. }
  164. #if MEGDNN_WITH_BENCHMARK
  165. TEST_F(CPU, BENCHMARK_7X7_CONVOLUTION)
  166. {
  167. using Param = param::Convolution;
  168. auto run = [&](const TensorShapeArray& shapes, Param param) {
  169. auto handle_naive = create_cpu_handle(2);
  170. Benchmarker<Convolution> benchmarker_naive(handle_naive.get());
  171. Benchmarker<Convolution> benchmarker_float(handle());
  172. size_t RUN = 10;
  173. auto tfloat = benchmarker_float.set_display(false)
  174. .set_times(RUN)
  175. .set_param(param)
  176. .exec(shapes);
  177. auto tnaive = benchmarker_naive.set_display(false)
  178. .set_times(RUN)
  179. .set_param(param)
  180. .exec(shapes);
  181. printf("src: %s filter: %s dst: %s naive=%.3fms float=%.3fms\n",
  182. shapes[0].to_string().c_str(), shapes[1].to_string().c_str(),
  183. shapes[2].to_string().c_str(), tnaive / RUN, tfloat / RUN);
  184. };
  185. Param param;
  186. param.stride_h = 2;
  187. param.stride_w = 2;
  188. param.pad_h = 3;
  189. param.pad_w = 3;
  190. // clang-format off
  191. for (size_t ic : {1, 3, 8, 16, 24}) {
  192. for (size_t oc : {8, 16}) {
  193. for (size_t h : {128, 224, 256, 512}) {
  194. for (size_t w : {128, 224, 256, 512}) {
  195. run({{1, ic, h, w}, {oc, ic, 7, 7}, {1, oc, h / 2, w / 2}}, param);
  196. } } } }
  197. // clang-format on
  198. // Used in FaceModel
  199. //run({{2, 3, 512, 512}, {8, 3, 7, 7}, {2, 8, 256, 256}}, param);
  200. //run({{2, 3, 128, 128}, {16, 3, 7, 7}, {2, 16, 64, 64}}, param);
  201. //run({{2, 3, 224, 224}, {32, 3, 7, 7}, {2, 32, 112, 112}}, param);
  202. }
  203. #endif
  204. // vim: syntax=cpp.doxygen

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

Contributors (1)