1 //
2 // ReductionBufExecution.cpp
3 // MNN
4 //
5 // Created by MNN on 2019/10/25.
6 // Copyright © 2018, Alibaba Group Holding Limited
7 //
8
9 #ifndef MNN_OPENCL_BUFFER_CLOSED
10
11 #include "backend/opencl/execution/buffer/ReductionBufExecution.hpp"
12 #include "core/Macro.h"
13 #include "core/TensorUtils.hpp"
14
15 namespace MNN {
16 namespace OpenCL {
17
ReductionBufExecution(const MNN::Op * op,Backend * backend)18 ReductionBufExecution::ReductionBufExecution(const MNN::Op* op, Backend* backend) : CommonExecution(backend) {
19 #ifdef LOG_VERBOSE
20 MNN_PRINT("start ReductionBufExecution init !\n");
21 #endif
22 mOpenCLBackend = static_cast<OpenCLBackend *>(backend);
23 auto reduct = op->main_as_ReductionParam();
24 if (nullptr != reduct->dim()) {
25 for (int i = 0; i < reduct->dim()->size(); ++i) {
26 mAxis.push_back(reduct->dim()->data()[i]);
27 }
28 }
29 switch (op->main_as_ReductionParam()->operation()) {
30 case ReductionType_MEAN:
31 mReductType = 0;
32 break;
33 case ReductionType_MAXIMUM:
34 mReductType = 1;
35 break;
36 case ReductionType_MINIMUM:
37 mReductType = 2;
38 break;
39 case ReductionType_PROD:
40 mReductType = 3;
41 break;
42 case ReductionType_SUM:
43 mReductType = 4;
44 break;
45 default:
46 MNN_ASSERT(false);
47 break;
48 }
49 mOp = op;
50 #ifdef LOG_VERBOSE
51 MNN_PRINT("end ReductionBufExecution init !\n");
52 #endif
53 }
54
onResize(const std::vector<Tensor * > & inputs,const std::vector<Tensor * > & outputs)55 ErrorCode ReductionBufExecution::onResize(const std::vector<Tensor *> &inputs, const std::vector<Tensor *> &outputs) {
56
57 MNN_ASSERT(mAxis.size() == 1);
58 MNN_ASSERT(mAxis[0] == 1);
59
60 auto runtime = mOpenCLBackend->getOpenCLRuntime();
61 auto input = inputs[0];
62 auto output = outputs[0];
63 std::vector<int> inputShape = tensorShapeFormat(input);
64 //N=outside H=axis W=inside C=1
65 MNN_ASSERT(inputShape[3] == 1);
66
67 mGlobalWorkSize = {static_cast<uint32_t>(inputShape[0]), static_cast<uint32_t>(inputShape[2])};
68 mLocalWorkSize = {1, 1, 1};
69
70 std::set<std::string> buildOption;
71 switch (mReductType) {
72 case 0:
73 buildOption.emplace("-DOPERATE=num+in");
74 buildOption.emplace("-DGET_AVG");
75 break;
76 case 1:
77 buildOption.emplace("-DOPERATE=max(num,in)");
78 break;
79 case 2:
80 buildOption.emplace("-DOPERATE=min(num,in)");
81 break;
82 case 3:
83 buildOption.emplace("-DOPERATE=num*in");
84 break;
85 case 4:
86 buildOption.emplace("-DOPERATE=num+in");
87 break;
88 default:
89 MNN_ASSERT(false);
90 break;
91 }
92 mReduct1DKernel = runtime->buildKernel("reduction_buf", "reduct_buf", buildOption);
93
94 //printf("reduce axis:%d , %d %d %d %d, useLocal:%d\n", mAxis[0], inputShape[0], inputShape[1], inputShape[2], inputShape[3], mUseLocal);
95
96 mUnits.resize(1);
97 uint32_t idx = 0;
98
99 mReduct1DKernel.setArg(idx++, mGlobalWorkSize[0]);
100 mReduct1DKernel.setArg(idx++, mGlobalWorkSize[1]);
101 mReduct1DKernel.setArg(idx++, openCLBuffer(input));
102 mReduct1DKernel.setArg(idx++, openCLBuffer(output));
103 mReduct1DKernel.setArg(idx++, static_cast<int32_t>(inputShape[0]));
104 mReduct1DKernel.setArg(idx++, static_cast<int32_t>(inputShape[1]));
105 mReduct1DKernel.setArg(idx++, static_cast<int32_t>(inputShape[2]));
106
107 return NO_ERROR;
108 }
109
onExecute(const std::vector<Tensor * > & inputs,const std::vector<Tensor * > & outputs)110 ErrorCode ReductionBufExecution::onExecute(const std::vector<Tensor *> &inputs, const std::vector<Tensor *> &outputs) {
111 #ifdef LOG_VERBOSE
112 MNN_PRINT("start ReductionBufExecution onExecute !\n");
113 #endif
114
115 #ifdef ENABLE_OPENCL_TIME_PROFILER
116 cl::Event event;
117 runKernel2D(mReduct1DKernel, mGlobalWorkSize, mLocalWorkSize,
118 mOpenCLBackend->getOpenCLRuntime(), &event);
119 int costTime = (int)mOpenCLBackend->getOpenCLRuntime()->getCostTime(&event);
120 MNN_PRINT("kernel cost:%d us Reduct1D\n",costTime);
121 #else
122 runKernel2D(mReduct1DKernel, mGlobalWorkSize, mLocalWorkSize,
123 mOpenCLBackend->getOpenCLRuntime());
124 #endif
125
126 #ifdef LOG_VERBOSE
127 MNN_PRINT("end ReductionBufExecution onExecute !\n");
128 #endif
129 return NO_ERROR;
130 }
131
132 class ReductionBufCreator : public OpenCLBackend::Creator {
133 public:
134 virtual ~ReductionBufCreator() = default;
onCreate(const std::vector<Tensor * > & inputs,const std::vector<Tensor * > & outputs,const MNN::Op * op,Backend * backend) const135 virtual Execution *onCreate(const std::vector<Tensor *> &inputs, const std::vector<Tensor *> &outputs,
136 const MNN::Op *op, Backend *backend) const override {
137 if (inputs[0]->getDimensionType() == Tensor::TENSORFLOW) {
138 auto openCLBackend = static_cast<OpenCLBackend *>(backend);
139 auto reduct = op->main_as_ReductionParam();
140 if (nullptr == reduct->dim()) {
141 return NULL;
142 }
143 if(reduct->dim()->size() != 1) {
144 return NULL;
145 }
146 switch (op->main_as_ReductionParam()->operation()) {
147 case ReductionType_MEAN:
148 break;
149 case ReductionType_MAXIMUM:
150 break;
151 case ReductionType_MINIMUM:
152 break;
153 case ReductionType_PROD:
154 break;
155 case ReductionType_SUM:
156 break;
157 default:
158 return NULL;
159 break;
160 }
161 return new ReductionBufExecution(op, backend);
162 }
163 return NULL;
164 }
165 };
166
167 OpenCLCreatorRegister<ReductionBufCreator> __reductionBuf_op(OpType_Reduction, BUFFER);
168 } // namespace OpenCL
169 } // namespace MNN
170 #endif /* MNN_OPENCL_BUFFER_CLOSED */
171