// // RangeBufExecution.cpp // MNN // // Created by MNN on 2023/12/1. // Copyright © 2018, Alibaba Group Holding Limited // #include "backend/opencl/execution/image/RangeExecution.hpp" #include "core/Macro.h" #include "core/TensorUtils.hpp" #include "backend/opencl/core/OpenCLBackend.hpp" namespace MNN { namespace OpenCL { RangeExecution::RangeExecution(const std::string &compute, const MNN::Op *op, Backend* backend) : CommonExecution(backend, op) { mBuildOptions.emplace(compute); // Do nothing } ErrorCode RangeExecution::onEncode(const std::vector& inputs, const std::vector& outputs) { mUnits.resize(1); auto &unit = mUnits[0]; auto openCLBackend = static_cast(backend()); auto runtime = openCLBackend->getOpenCLRuntime(); unit.kernel = runtime->buildKernel("range", "range", mBuildOptions, openCLBackend->getPrecision(), inputs[0], outputs[0]); mMaxWorkGroupSize = static_cast(runtime->getMaxWorkGroupSize(unit.kernel)); std::vector outputShape = tensorShapeFormat(outputs[0]); int batch = outputShape.at(0); int outputHeight = outputShape.at(1); int outputWidth = outputShape.at(2); int channels = outputShape.at(3); int channelBlocks = (channels + 3) / 4; std::vector mGlobalWorkSize = {1, 1, 1}; std::vector mLocalSize = {1, 1, 1}; mGlobalWorkSize = { static_cast(outputWidth), static_cast(outputHeight), static_cast(batch * channelBlocks) }; uint32_t idx = 0; cl_int ret = CL_SUCCESS; ret |= unit.kernel->get().setArg(idx++, mGlobalWorkSize[0]); ret |= unit.kernel->get().setArg(idx++, mGlobalWorkSize[1]); ret |= unit.kernel->get().setArg(idx++, mGlobalWorkSize[2]); ret |= unit.kernel->get().setArg(idx++, openCLImage(inputs[0])); ret |= unit.kernel->get().setArg(idx++, openCLImage(inputs[2])); ret |= unit.kernel->get().setArg(idx++, openCLImage(outputs[0])); ret |= unit.kernel->get().setArg(idx++, outputWidth); ret |= unit.kernel->get().setArg(idx++, outputHeight); ret |= unit.kernel->get().setArg(idx++, channels); ret |= unit.kernel->get().setArg(idx++, channelBlocks); MNN_CHECK_CL_SUCCESS(ret, "setArg RangeExecution"); std::string kernelName = "range"; mLocalSize = localWS3DDefault(mGlobalWorkSize, mMaxWorkGroupSize, openCLBackend->getOpenCLRuntime(), kernelName, unit.kernel, openCLBackend->getCLTuneLevel(), "range").first; openCLBackend->recordKernel3d(unit.kernel, mGlobalWorkSize, mLocalSize); unit.globalWorkSize = {mGlobalWorkSize[0], mGlobalWorkSize[1], mGlobalWorkSize[2]}; unit.localWorkSize = {mLocalSize[0], mLocalSize[1], mLocalSize[2]}; return NO_ERROR; } class RangeCreator : public OpenCLBackend::Creator { public: virtual Execution* onCreate(const std::vector& inputs, const std::vector& outputs, const MNN::Op* op, Backend* backend) const override { auto code = inputs[0]->getType().code; switch (code) { case halide_type_int: OPENCL_CREATOR_CHECK(new RangeExecution("-DUSE_INT", op, backend)); case halide_type_float: OPENCL_CREATOR_CHECK(new RangeExecution("-DUSE_FLOAT", op, backend)); default: return nullptr; } } }; REGISTER_OPENCL_OP_CREATOR(RangeCreator, OpType_Range, IMAGE); } // namespace OpenCL } // namespace MNN