| 158 | return NO_ERROR; |
| 159 | } |
| 160 | virtual ErrorCode onExecute(const std::vector<Tensor *> &inputs, const std::vector<Tensor *> &outputs) override { |
| 161 | auto inputTensor = outputs[0]; |
| 162 | ::memset(inputTensor->host<uint8_t>(), 0, static_cast<CPUBackend*>(backend())->getTensorSize(inputTensor, false) * static_cast<CPUBackend*>(backend())->functions()->bytes); |
| 163 | auto gridTensor = inputs[1]; |
| 164 | auto outputTensor = inputs[0]; |
| 165 | auto inputPtr = inputTensor->host<uint8_t>(); |
| 166 | auto gridPtr = gridTensor->host<uint8_t>(); |
| 167 | auto outputPtr = outputTensor->host<uint8_t>(); |
| 168 | auto core = static_cast<CPUBackend*>(backend())->functions(); |
| 169 | auto batches = inputTensor->buffer().dim[0].extent; |
| 170 | auto channels = inputTensor->buffer().dim[1].extent; |
| 171 | auto channelC4 = UP_DIV(channels, core->pack); |
| 172 | if (outputTensor->dimensions() != 4) { |
| 173 | return NOT_SUPPORT; |
| 174 | } |
| 175 | auto inH = inputTensor->buffer().dim[2].extent; |
| 176 | auto inW = inputTensor->buffer().dim[3].extent; |
| 177 | auto outH = outputTensor->buffer().dim[2].extent; |
| 178 | auto outW = outputTensor->buffer().dim[3].extent; |
| 179 | auto threadCount = static_cast<CPUBackend*>(backend())->threadNumber(); |
| 180 | auto tileCount = outH; |
| 181 | auto inOffset = batches * inH * inW * core->pack; |
| 182 | auto outOffset = batches * outH * outW * core->pack; |
| 183 | auto cordPtr = mTempCordBuffer->host<uint8_t>(); |
| 184 | for (auto b = 0; b < batches; ++b) { |
| 185 | auto _inputPtr = inputPtr + b * inH * inW * core->pack * core->bytes; |
| 186 | auto _gridPtr = gridPtr + b * gridTensor->buffer().dim[0].stride * core->bytes; |
| 187 | auto _outputPtr = outputPtr + b * outH * outW * core->pack * core->bytes; |
| 188 | core->MNNGridSampleComputeCord((float *)cordPtr, (const float *)_gridPtr, inH, inW, outH, outW, mAlignCorners); |
| 189 | // Compute cord |
| 190 | for (int index=0; index < tileCount; index++) { |
| 191 | auto c = index / outH; |
| 192 | auto h = index % outH; |
| 193 | auto inputC = _inputPtr + c * inW * inH * batches * core->pack * core->bytes; |
| 194 | auto outputC = _outputPtr + c * outW * outH * batches * core->pack * core->bytes; |
| 195 | auto cordH = cordPtr + h * outW * 2 * core->bytes; |
| 196 | auto outputH = outputC + h * outW * core->pack * core->bytes; |
| 197 | core->MNNGridSampleInterpGrad((float *)outputH, (float *)inputC, (const float *)cordH, inH, inW, outW, channelC4, inOffset, outOffset, (mMode == SampleMode_NEAREST), (mPaddingMode == BorderMode_ZEROS)); |
| 198 | } |
| 199 | } |
| 200 | |
| 201 | return NO_ERROR; |
| 202 | } |
| 203 | }; |
| 204 | #endif |
| 205 | class CPUGridSampleCreator : public CPUBackend::Creator { |
nothing calls this directly
no test coverage detected