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.

opr_impl.cpp 12 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /**
  2. * \file dnn/src/cuda/convolution3d/opr_impl.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 "./opr_impl.h"
  12. #include "./backward_data/algo.h"
  13. #include "./backward_filter/algo.h"
  14. #include "./forward/algo.h"
  15. #include "./helper.h"
  16. #include "src/common/algo_chooser.h"
  17. #include "src/cuda/utils.h"
  18. using namespace megdnn;
  19. using namespace cuda;
  20. using namespace convolution3d;
  21. #define TO_STRING2(v) #v
  22. #define TO_STRING(v) TO_STRING2(v)
  23. #define CUDNN_VERSION_STR \
  24. TO_STRING(CUDNN_MAJOR) \
  25. "." TO_STRING(CUDNN_MINOR) "." TO_STRING(CUDNN_PATCHLEVEL)
  26. /* ============== Convolution3DForwardImpl ============== */
  27. Convolution3DForwardImpl::Algorithm* Convolution3DForwardImpl::get_algorithm_heuristic(
  28. const TensorLayout& src, const TensorLayout& filter, const TensorLayout& dst,
  29. size_t workspace_limit_in_bytes, const AlgoAttribute& positive_attr,
  30. const AlgoAttribute& negative_attr) {
  31. AlgoBase::SizeArgs args(this, src, filter, dst);
  32. #if CUDNN_MAJOR < 7 || (CUDNN_MAJOR == 7 && CUDNN_MINOR < 5)
  33. if (args.filter_meta.group > 1) {
  34. // prefer special chanwise impl since as the group conv of cudnn whose
  35. // version is lower than v7.5.0 is still slower than our implementation
  36. // in many channel-wise cases
  37. if (sm_algo_pack.chanwise.is_available_attribute(
  38. args, positive_attr, negative_attr, workspace_limit_in_bytes)) {
  39. return &sm_algo_pack.chanwise;
  40. }
  41. }
  42. #endif
  43. auto prefer_1x1x1 = [&args, positive_attr, negative_attr,
  44. workspace_limit_in_bytes]() {
  45. const size_t MAX_BATCH_SIZE_FOR_1x1x1_MAT_ALGO = 4;
  46. size_t batch_size = args.src_layout->shape[0];
  47. if (batch_size > MAX_BATCH_SIZE_FOR_1x1x1_MAT_ALGO) {
  48. return false;
  49. }
  50. return sm_algo_pack.a1x1x1.is_available_attribute(
  51. args, positive_attr, negative_attr, workspace_limit_in_bytes);
  52. };
  53. auto get_cudnn_algo = [this, &args, workspace_limit_in_bytes, positive_attr,
  54. negative_attr]() -> Convolution3DForwardImpl::AlgoBase* {
  55. auto cudnn_handle = cuda::cudnn_handle(this->handle());
  56. cudnnConvolutionFwdAlgo_t algo;
  57. CUDNNForwardDescs desc;
  58. args.init_desc(desc);
  59. bool got = cudnn_get_convolution_fwd_algo_helper(
  60. cudnn_handle, desc.src_desc.desc, desc.filter_desc.desc,
  61. desc.conv_desc.desc, desc.dst_desc.desc, workspace_limit_in_bytes,
  62. &algo, positive_attr, negative_attr);
  63. if (got) {
  64. return static_cast<AlgoBase*>(
  65. megdnn::get_algo_match_attribute<Convolution3DForwardImpl>(
  66. sm_algo_pack.cudnn_from_enum(algo), positive_attr,
  67. negative_attr));
  68. } else {
  69. return nullptr;
  70. }
  71. };
  72. if (prefer_1x1x1()) {
  73. return &sm_algo_pack.a1x1x1;
  74. }
  75. if (is_cudnn_supported(args)) {
  76. if (auto algo = get_cudnn_algo())
  77. return algo;
  78. }
  79. if (args.filter_meta.group > 1 &&
  80. sm_algo_pack.group.is_available_attribute(
  81. args, positive_attr, negative_attr, workspace_limit_in_bytes)) {
  82. return &sm_algo_pack.group;
  83. }
  84. return megdnn::get_algo_match_attribute<Convolution3DForwardImpl>(
  85. sm_algo_pack.non_cudnn_algos, args, workspace_limit_in_bytes,
  86. "cuda conv3d fwd", positive_attr, negative_attr);
  87. }
  88. std::vector<Convolution3DForwardImpl::Algorithm*> Convolution3DForwardImpl::
  89. get_all_algorithms(
  90. const TensorLayout& src, const TensorLayout& filter,
  91. const TensorLayout& dst) {
  92. return megdnn::get_all_algorithms<Convolution3DForwardImpl>(
  93. {this, src, filter, dst});
  94. }
  95. std::vector<Convolution3DForwardImpl::Algorithm*> Convolution3DForwardImpl::
  96. get_all_algorithms_safe(
  97. const TensorLayout& src, const TensorLayout& filter,
  98. const TensorLayout& dst) {
  99. return megdnn::get_all_algorithms_safe<Convolution3DForwardImpl>(
  100. {this, src, filter, dst});
  101. }
  102. size_t Convolution3DForwardImpl::get_workspace_in_bytes(
  103. const TensorLayout& src, const TensorLayout& filter, const TensorLayout& dst) {
  104. return get_dnn_workspace(this, src, filter, dst);
  105. }
  106. void Convolution3DForwardImpl::exec(
  107. _megdnn_tensor_in src, _megdnn_tensor_in filter, _megdnn_tensor_out dst,
  108. _megdnn_workspace workspace) {
  109. check_exec(src.layout, filter.layout, dst.layout, workspace.size);
  110. AlgoBase::ExecArgs args(this, src, filter, dst, workspace);
  111. auto algo = get_algorithm(this, src.layout, filter.layout, dst.layout);
  112. algo->exec(args);
  113. }
  114. const char* Convolution3DForwardImpl::get_algorithm_set_name() const {
  115. return "CUDACONV0+CUDNN" CUDNN_VERSION_STR;
  116. }
  117. void Convolution3DBackwardDataImpl::exec(
  118. _megdnn_tensor_in filter, _megdnn_tensor_in diff, _megdnn_tensor_out grad,
  119. _megdnn_workspace workspace) {
  120. check_exec(filter.layout, diff.layout, grad.layout, workspace.size);
  121. AlgoBase::ExecArgs args(this, filter, diff, grad, workspace);
  122. auto algo = get_algorithm(this, filter.layout, diff.layout, grad.layout);
  123. algo->exec(args);
  124. }
  125. std::vector<Convolution3DBackwardDataImpl::Algorithm*> Convolution3DBackwardDataImpl::
  126. get_all_algorithms(
  127. const TensorLayout& filter, const TensorLayout& diff,
  128. const TensorLayout& grad) {
  129. return megdnn::get_all_algorithms<Convolution3DBackwardDataImpl>(
  130. {this, filter, diff, grad});
  131. }
  132. std::vector<Convolution3DBackwardDataImpl::Algorithm*> Convolution3DBackwardDataImpl::
  133. get_all_algorithms_safe(
  134. const TensorLayout& filter, const TensorLayout& diff,
  135. const TensorLayout& grad) {
  136. return megdnn::get_all_algorithms_safe<Convolution3DBackwardDataImpl>(
  137. {this, filter, diff, grad});
  138. }
  139. Convolution3DBackwardDataImpl::Algorithm* Convolution3DBackwardDataImpl::
  140. get_algorithm_heuristic(
  141. const TensorLayout& filter, const TensorLayout& diff,
  142. const TensorLayout& grad, size_t workspace_limit_in_bytes,
  143. const AlgoAttribute& positive_attr,
  144. const AlgoAttribute& negative_attr) {
  145. AlgoBase::SizeArgs args(this, filter, diff, grad);
  146. if (args.filter_meta.group > 1 &&
  147. sm_algo_pack.chanwise.is_available_attribute(
  148. args, positive_attr, negative_attr, workspace_limit_in_bytes)) {
  149. return &sm_algo_pack.chanwise;
  150. }
  151. auto get_cudnn_algo =
  152. [this, &args, workspace_limit_in_bytes, positive_attr,
  153. negative_attr]() -> Convolution3DBackwardDataImpl::AlgoBase* {
  154. auto cudnn_handle = cuda::cudnn_handle(this->handle());
  155. cudnnConvolutionBwdDataAlgo_t algo;
  156. CUDNNBwdDataDescs desc;
  157. args.init_desc(desc);
  158. bool got = cudnn_get_convolution_bwd_data_algo_helper(
  159. cudnn_handle, desc.filter_desc.desc, desc.diff_desc.desc,
  160. desc.conv_desc.desc, desc.grad_desc.desc, workspace_limit_in_bytes,
  161. &algo, positive_attr, negative_attr);
  162. if (got) {
  163. return static_cast<AlgoBase*>(
  164. megdnn::get_algo_match_attribute<Convolution3DBackwardDataImpl>(
  165. sm_algo_pack.cudnn_from_enum(algo), positive_attr,
  166. negative_attr));
  167. } else {
  168. return nullptr;
  169. }
  170. };
  171. if (is_cudnn_supported(args.as_fwd_args())) {
  172. if (auto algo = get_cudnn_algo())
  173. return algo;
  174. }
  175. if (args.filter_meta.group > 1 &&
  176. sm_algo_pack.group.is_available_attribute(
  177. args, positive_attr, negative_attr, workspace_limit_in_bytes)) {
  178. return &sm_algo_pack.group;
  179. }
  180. return megdnn::get_algo_match_attribute<Convolution3DBackwardDataImpl>(
  181. sm_algo_pack.non_cudnn_algos, args, workspace_limit_in_bytes,
  182. "cuda conv3d bwd data", positive_attr, negative_attr);
  183. }
  184. size_t Convolution3DBackwardDataImpl::get_workspace_in_bytes(
  185. const TensorLayout& filter, const TensorLayout& diff,
  186. const TensorLayout& grad) {
  187. return get_dnn_workspace(this, filter, diff, grad);
  188. }
  189. const char* Convolution3DBackwardDataImpl::get_algorithm_set_name() const {
  190. return "CUDACONV0+CUDNN" CUDNN_VERSION_STR;
  191. }
  192. void Convolution3DBackwardFilterImpl::exec(
  193. _megdnn_tensor_in src, _megdnn_tensor_in diff, _megdnn_tensor_out grad,
  194. _megdnn_workspace workspace) {
  195. check_exec(src.layout, diff.layout, grad.layout, workspace.size);
  196. AlgoBase::ExecArgs args(this, src, diff, grad, workspace);
  197. auto algo = get_algorithm(this, src.layout, diff.layout, grad.layout);
  198. algo->exec(args);
  199. }
  200. std::vector<Convolution3DBackwardFilterImpl::Algorithm*>
  201. Convolution3DBackwardFilterImpl::get_all_algorithms(
  202. const TensorLayout& src, const TensorLayout& diff, const TensorLayout& grad) {
  203. return megdnn::get_all_algorithms<Convolution3DBackwardFilterImpl>(
  204. {this, src, diff, grad});
  205. }
  206. std::vector<Convolution3DBackwardFilterImpl::Algorithm*>
  207. Convolution3DBackwardFilterImpl::get_all_algorithms_safe(
  208. const TensorLayout& src, const TensorLayout& diff, const TensorLayout& grad) {
  209. return megdnn::get_all_algorithms_safe<Convolution3DBackwardFilterImpl>(
  210. {this, src, diff, grad});
  211. }
  212. Convolution3DBackwardFilterImpl::Algorithm* Convolution3DBackwardFilterImpl::
  213. get_algorithm_heuristic(
  214. const TensorLayout& src, const TensorLayout& diff,
  215. const TensorLayout& grad, size_t workspace_limit_in_bytes,
  216. const AlgoAttribute& positive_attr,
  217. const AlgoAttribute& negative_attr) {
  218. AlgoBase::SizeArgs args(this, src, diff, grad);
  219. if (args.grad_filter_meta.group > 1 &&
  220. sm_algo_pack.chanwise.is_available_attribute(
  221. args, positive_attr, negative_attr, workspace_limit_in_bytes)) {
  222. return &sm_algo_pack.chanwise;
  223. }
  224. auto get_cudnn_algo =
  225. [this, &args, workspace_limit_in_bytes, positive_attr,
  226. negative_attr]() -> Convolution3DBackwardFilterImpl::AlgoBase* {
  227. auto cudnn_handle = cuda::cudnn_handle(this->handle());
  228. cudnnConvolutionBwdFilterAlgo_t algo;
  229. CUDNNBwdFilterDescs desc;
  230. args.init_desc(desc);
  231. bool got = cudnn_get_convolution_bwd_filter_algo_helper(
  232. cudnn_handle, desc.src_desc.desc, desc.diff_desc.desc,
  233. desc.conv_desc.desc, desc.grad_desc.desc, workspace_limit_in_bytes,
  234. &algo, positive_attr, negative_attr);
  235. if (got) {
  236. return static_cast<AlgoBase*>(
  237. megdnn::get_algo_match_attribute<Convolution3DBackwardFilterImpl>(
  238. sm_algo_pack.cudnn_from_enum(algo), positive_attr,
  239. negative_attr));
  240. } else {
  241. return nullptr;
  242. }
  243. };
  244. if (is_cudnn_supported(args.as_fwd_args())) {
  245. if (auto algo = get_cudnn_algo())
  246. return algo;
  247. }
  248. if (args.grad_filter_meta.group > 1 &&
  249. sm_algo_pack.group.is_available_attribute(
  250. args, positive_attr, negative_attr, workspace_limit_in_bytes)) {
  251. return &sm_algo_pack.group;
  252. }
  253. return megdnn::get_algo_match_attribute<Convolution3DBackwardFilterImpl>(
  254. sm_algo_pack.non_cudnn_algos, args, workspace_limit_in_bytes,
  255. "cuda conv3d bwd filter", positive_attr, negative_attr);
  256. }
  257. size_t Convolution3DBackwardFilterImpl::get_workspace_in_bytes(
  258. const TensorLayout& src, const TensorLayout& diff, const TensorLayout& grad) {
  259. return get_dnn_workspace(this, src, diff, grad);
  260. }
  261. const char* Convolution3DBackwardFilterImpl::get_algorithm_set_name() const {
  262. return "CUDACONV0+CUDNN" CUDNN_VERSION_STR;
  263. }
  264. // vim: syntax=cpp.doxygen