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.

reduce.cpp 12 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /**
  2. * \file dnn/test/fallback/reduce.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 "test/fallback/fixture.h"
  12. #include "megdnn/oprs.h"
  13. #include "test/common/checker.h"
  14. #include "test/common/task_record_check.h"
  15. #include "test/common/tensor.h"
  16. #include "test/common/workspace_wrapper.h"
  17. using namespace megdnn;
  18. using namespace test;
  19. TEST_F(FALLBACK, REDUCE_FULL) {
  20. using Param = Reduce::Param;
  21. using Mode = Param::Mode;
  22. Checker<Reduce> checker(handle());
  23. UniformIntRNG rng{INT8_MIN >> 1, INT8_MAX >> 1};
  24. checker.set_rng(0, &rng);
  25. struct Config {
  26. Param param;
  27. DType dtype;
  28. TensorShape shape;
  29. Config(Param param, DType dtype, TensorShape shape)
  30. : param(param), dtype(dtype), shape(shape) {}
  31. };
  32. std::vector<Config> configs;
  33. for (auto mode : {Mode::MEAN, Mode::MAX, Mode::MIN})
  34. for (auto dtype : std::vector<DType>{
  35. dtype::Float32(), dtype::Float16(), dtype::QuantizedS8(1.3f),
  36. dtype::Quantized8Asymm(1.3f, static_cast<uint8_t>(3))})
  37. for (int32_t axis : {0, 1, 2}) {
  38. for (size_t A : {1, 3, 5}) {
  39. for (size_t B : {4, 6, 9, 16, 33, 45}) {
  40. for (size_t C : {4, 6, 9, 16, 33, 45}) {
  41. TensorShape shape{A, B, C};
  42. Param param(mode, axis);
  43. Config config(param, dtype, shape);
  44. configs.push_back(config);
  45. }
  46. }
  47. }
  48. }
  49. for (auto&& config : configs) {
  50. auto&& dtype = config.dtype;
  51. auto&& param = config.param;
  52. auto&& shape = config.shape;
  53. checker.set_dtype(0, dtype).set_param(param).execs({shape, {}});
  54. }
  55. configs.clear();
  56. for (auto mode : {Mode::SUM, Mode::PRODUCT, Mode::SUM_SQR})
  57. for (auto dtype : std::vector<DType>{dtype::Float32(), dtype::Float16()})
  58. for (int32_t axis : {0, 1, 2}) {
  59. for (size_t A : {1, 3, 5}) {
  60. for (size_t B : {4, 6, 9, 16, 33, 45}) {
  61. for (size_t C : {4, 6, 9, 16, 33, 45}) {
  62. TensorShape shape{A, B, C};
  63. Param param(mode, axis);
  64. Config config(param, dtype, shape);
  65. configs.push_back(config);
  66. }
  67. }
  68. }
  69. }
  70. UniformFloatRNG rng_float(-2, 2);
  71. checker.set_rng(0, &rng_float);
  72. checker.set_epsilon(1e-1);
  73. for (auto&& config : configs) {
  74. auto&& dtype = config.dtype;
  75. auto&& param = config.param;
  76. auto&& shape = config.shape;
  77. if (dtype == dtype::Float16())
  78. checker.set_epsilon(1e-1);
  79. else
  80. checker.set_epsilon(1e-3);
  81. checker.set_dtype(0, dtype).set_param(param).execs({shape, {}});
  82. }
  83. }
  84. TEST_F(FALLBACK, REDUCE) {
  85. using Param = Reduce::Param;
  86. using Mode = Param::Mode;
  87. using DataType = Param::DataType;
  88. Checker<Reduce> checker(handle());
  89. struct Config {
  90. Param param;
  91. DType dtype;
  92. TensorShape shape;
  93. Config(Param param, DType dtype, TensorShape shape)
  94. : param(param), dtype(dtype), shape(shape) {}
  95. };
  96. std::vector<Config> configs;
  97. // general
  98. for (auto mode :
  99. {Mode::SUM, Mode::MEAN, Mode::SUM_SQR, Mode::PRODUCT, Mode::MIN, Mode::MAX})
  100. for (auto dtype : std::vector<DType>{
  101. dtype::Float16(), dtype::Float32(), dtype::Int32(), dtype::Int16(),
  102. dtype::Int8(), dtype::Uint8()})
  103. for (int32_t axis : {0, 1, 2, 3}) {
  104. TensorShape shape{2, 3, 20, 5};
  105. Param param(mode, axis);
  106. Config config(param, dtype, shape);
  107. configs.push_back(config);
  108. if (dtype.category() == DTypeCategory::FLOAT) {
  109. Param param(mode, axis, DataType::FLOAT_O16xC32);
  110. Config config(param, dtype, shape);
  111. configs.push_back(config);
  112. param.data_type = DataType::FLOAT_O32xC32;
  113. config = Config(param, dtype, shape);
  114. configs.push_back(config);
  115. } else if (dtype == dtype::Int32()) {
  116. Param param(mode, axis, DataType::FLOAT_O32xC32);
  117. Config config(param, dtype, shape);
  118. configs.push_back(config);
  119. }
  120. }
  121. // large (ABC) -> (A1C) case
  122. for (auto mode : {Mode::SUM_SQR})
  123. for (auto dtype : std::vector<DType>{dtype::Int32()})
  124. for (int32_t axis : {0, 1, 2, 3}) {
  125. TensorShape shape{2, 3, 10000, 5};
  126. Param param(mode, axis);
  127. Config config(param, dtype, shape);
  128. configs.push_back(config);
  129. }
  130. // large (AB) -> (A1) case
  131. for (auto mode : {Mode::SUM_SQR})
  132. for (auto dtype : std::vector<DType>{dtype::Int32()})
  133. for (int32_t axis : {0, 1, 2, 3}) {
  134. TensorShape shape{2, 3, 5, 10000};
  135. Param param(mode, axis);
  136. Config config(param, dtype, shape);
  137. configs.push_back(config);
  138. }
  139. {
  140. // large reduce_mean for O16C32
  141. TensorShape shape{1, 65536, 5};
  142. Param param(Mode::MEAN, 1, DataType::FLOAT_O16xC32);
  143. Config config(param, dtype::Float16(), shape);
  144. configs.push_back(config);
  145. }
  146. for (auto&& config : configs) {
  147. auto&& dtype = config.dtype;
  148. auto&& param = config.param;
  149. auto&& mode = config.param.mode;
  150. auto&& shape = config.shape;
  151. auto&& data_type = config.param.data_type;
  152. // when input/output both float16, the internal compute is float16, mode
  153. // is SUM or SUM_SQR, need set epsilon to 1e-2 to pass test
  154. if (dtype == dtype::Float16() && data_type == DataType::DEFAULT &&
  155. (mode == Mode::SUM || mode == Mode::SUM_SQR)) {
  156. checker.set_epsilon(1e-2);
  157. }
  158. checker.set_dtype(0, dtype).set_param(param).execs({shape, {}});
  159. }
  160. {
  161. static size_t N = 1 << 26;
  162. {
  163. // cpu vs naive
  164. Checker<Reduce> checker(handle());
  165. Reduce::Param param;
  166. param.axis = 0;
  167. UniformFloatRNG rng(1, 1);
  168. checker.set_param(param);
  169. checker.set_rng(0, &rng);
  170. checker.execs({{N}, {}});
  171. }
  172. {
  173. // naive vs groundtruth
  174. TensorLayout layoutN(TensorShape{N}, dtype::Float32()),
  175. layout1(TensorShape{1}, dtype::Float32());
  176. auto handle = this->handle();
  177. Tensor<float> src(handle, layoutN), dst(handle, layout1);
  178. float* ptr = src.ptr();
  179. for (size_t i = 0; i < N; ++i)
  180. ptr[i] = 1;
  181. auto opr = handle->create_operator<Reduce>();
  182. opr->param().axis = 0;
  183. auto wsize = opr->get_workspace_in_bytes(layoutN, layout1);
  184. WorkspaceWrapper workspace(handle, wsize);
  185. opr->exec(src.tensornd(), dst.tensornd(), workspace.workspace());
  186. megdnn_sync(handle);
  187. ASSERT_EQ(N, dst.ptr()[0]);
  188. }
  189. }
  190. }
  191. TEST_F(FALLBACK, REDUCE_RECORD) {
  192. using Param = Reduce::Param;
  193. using Mode = Param::Mode;
  194. using DataType = Param::DataType;
  195. TaskRecordChecker<Reduce> checker(1);
  196. struct Config {
  197. Param param;
  198. DType dtype;
  199. TensorShape shape;
  200. Config(Param param, DType dtype, TensorShape shape)
  201. : param(param), dtype(dtype), shape(shape) {}
  202. };
  203. std::vector<Config> configs;
  204. // general
  205. for (auto mode :
  206. {Mode::SUM, Mode::MEAN, Mode::SUM_SQR, Mode::PRODUCT, Mode::MIN, Mode::MAX})
  207. for (auto dtype : std::vector<DType>{
  208. dtype::Float16(), dtype::Float32(), dtype::Int32(), dtype::Int16(),
  209. dtype::Int8(), dtype::Uint8()})
  210. for (int32_t axis : {0, 1, 2, 3}) {
  211. TensorShape shape{2, 3, 20, 5};
  212. Param param(mode, axis);
  213. Config config(param, dtype, shape);
  214. configs.push_back(config);
  215. if (dtype.category() == DTypeCategory::FLOAT) {
  216. Param param(mode, axis, DataType::FLOAT_O16xC32);
  217. Config config(param, dtype, shape);
  218. configs.push_back(config);
  219. param.data_type = DataType::FLOAT_O32xC32;
  220. config = Config(param, dtype, shape);
  221. configs.push_back(config);
  222. } else if (dtype == dtype::Int32()) {
  223. Param param(mode, axis, DataType::FLOAT_O32xC32);
  224. Config config(param, dtype, shape);
  225. configs.push_back(config);
  226. }
  227. }
  228. // large (ABC) -> (A1C) case
  229. for (auto mode : {Mode::SUM_SQR})
  230. for (auto dtype : std::vector<DType>{dtype::Int32()})
  231. for (int32_t axis : {0, 1, 2, 3}) {
  232. TensorShape shape{2, 3, 10000, 5};
  233. Param param(mode, axis);
  234. Config config(param, dtype, shape);
  235. configs.push_back(config);
  236. }
  237. // large (AB) -> (A1) case
  238. for (auto mode : {Mode::SUM_SQR})
  239. for (auto dtype : std::vector<DType>{dtype::Int32()})
  240. for (int32_t axis : {0, 1, 2, 3}) {
  241. TensorShape shape{2, 3, 5, 10000};
  242. Param param(mode, axis);
  243. Config config(param, dtype, shape);
  244. configs.push_back(config);
  245. }
  246. {
  247. // large reduce_mean for O16C32
  248. TensorShape shape{1, 65536, 5};
  249. Param param(Mode::MEAN, 1, DataType::FLOAT_O16xC32);
  250. Config config(param, dtype::Float16(), shape);
  251. configs.push_back(config);
  252. }
  253. for (auto&& config : configs) {
  254. auto&& dtype = config.dtype;
  255. auto&& param = config.param;
  256. auto&& mode = config.param.mode;
  257. auto&& shape = config.shape;
  258. auto&& data_type = config.param.data_type;
  259. // when input/output both float16, the internal compute is float16, mode
  260. // is SUM or SUM_SQR, need set epsilon to 1e-2 to pass test
  261. if (dtype == dtype::Float16() && data_type == DataType::DEFAULT &&
  262. (mode == Mode::SUM || mode == Mode::SUM_SQR)) {
  263. checker.set_epsilon(1e-2);
  264. }
  265. checker.set_dtype(0, dtype).set_param(param).execs({shape, {}});
  266. }
  267. {
  268. static size_t N = 1 << 26;
  269. {
  270. // cpu vs naive
  271. TaskRecordChecker<Reduce> checker(1);
  272. Reduce::Param param;
  273. param.axis = 0;
  274. UniformFloatRNG rng(1, 1);
  275. checker.set_param(param);
  276. checker.set_rng(0, &rng);
  277. checker.execs({{N}, {}});
  278. }
  279. {
  280. // naive vs groundtruth
  281. TensorLayout layoutN(TensorShape{N}, dtype::Float32()),
  282. layout1(TensorShape{1}, dtype::Float32());
  283. auto handle = this->handle();
  284. Tensor<float> src(handle, layoutN), dst(handle, layout1);
  285. float* ptr = src.ptr();
  286. for (size_t i = 0; i < N; ++i)
  287. ptr[i] = 1;
  288. auto opr = handle->create_operator<Reduce>();
  289. opr->param().axis = 0;
  290. auto wsize = opr->get_workspace_in_bytes(layoutN, layout1);
  291. WorkspaceWrapper workspace(handle, wsize);
  292. opr->exec(src.tensornd(), dst.tensornd(), workspace.workspace());
  293. megdnn_sync(handle);
  294. ASSERT_EQ(N, dst.ptr()[0]);
  295. }
  296. }
  297. }
  298. // vim: syntax=cpp.doxygen