#ifndef MNN_OPENCL_BUFFER_CLOSED #include #include "backend/opencl/execution/buffer/SharedGatherBufExecution.hpp" #include "core/Macro.h" #include "core/TensorUtils.hpp" namespace MNN { namespace OpenCL { SharedGatherBufExecution::SharedGatherBufExecution(std::shared_ptr resource, const Op* op, Backend* backend) : CommonExecution(backend, op), mOpenCLBackend(static_cast(backend)), mResource(std::move(resource)) {} bool SharedGatherBufExecution::validResource(const std::shared_ptr& resource) { if (!resource.get() || !resource->mConv1x1Opt) { return false; } if (!resource->mDequantScaleOffsetBuffer.get()) { return false; } if (resource->mUseImage) { if (!resource->mKernelImage.get()) { return false; } } else if (!resource->mKernelBuffer.get()) { return false; } return resource->mNumQuantBit == 4 || resource->mNumQuantBit == 8; } bool SharedGatherBufExecution::onClone(Backend* bn, const Op* op, Execution** dst) { if (!mValid) { return false; } if (nullptr == dst) { return true; } *dst = new SharedGatherBufExecution(mResource, op, bn); return true; } ErrorCode SharedGatherBufExecution::onEncode(const std::vector& inputs, const std::vector& outputs) { mUnits.resize(1); auto& unit = mUnits[0]; auto runtime = mOpenCLBackend->getOpenCLRuntime(); MNN_ASSERT(inputs.size() == 1); MNN_ASSERT(outputs.size() == 1); auto indices = inputs[0]; auto output = outputs[0]; if (!validResource(mResource)) { return NOT_SUPPORT; } const int selectSize = indices->elementSize(); const int ic = output->length(output->dimensions() - 1); const int oc = mResource->mOutputChannel; if (selectSize <= 0 || ic <= 0 || oc <= 0) { return NOT_SUPPORT; } const int blockSize = mResource->mBlockSize; if (blockSize <= 0) { return NOT_SUPPORT; } std::set buildOptions; if (mResource->mNumQuantBit == 8) { buildOptions.emplace("-DUSE_LOW_BIT_WEIGHT_INT8"); } else { buildOptions.emplace("-DUSE_LOW_BIT_WEIGHT_INT4"); } if (mResource->mBuildOptions.find("-DASYMMETRIC") != mResource->mBuildOptions.end()) { buildOptions.emplace("-DASYMMETRIC"); } const char* kernelName = mResource->mUseImage ? "shared_gather_quant_image" : "shared_gather_quant_buffer"; unit.kernel = runtime->buildKernel("shared_gather_buf", kernelName, buildOptions, mOpenCLBackend->getPrecision(), indices, output); OPENCL_CHECK_KERNEL(unit.kernel); mGWS = {(uint32_t)selectSize, (uint32_t)UP_DIV(ic, 4)}; mLWS = {16, 16}; uint32_t idx = 0; cl_int ret = CL_SUCCESS; ret |= unit.kernel->get().setArg(idx++, (int)mGWS[0]); ret |= unit.kernel->get().setArg(idx++, (int)mGWS[1]); ret |= unit.kernel->get().setArg(idx++, openCLBuffer(output)); if (mResource->mUseImage) { ret |= unit.kernel->get().setArg(idx++, *mResource->mKernelImage.get()); } else { ret |= unit.kernel->get().setArg(idx++, *mResource->mKernelBuffer.get()); } ret |= unit.kernel->get().setArg(idx++, openCLBuffer(indices)); ret |= unit.kernel->get().setArg(idx++, *mResource->mDequantScaleOffsetBuffer.get()); ret |= unit.kernel->get().setArg(idx++, ic); ret |= unit.kernel->get().setArg(idx++, oc); ret |= unit.kernel->get().setArg(idx++, ic / blockSize); ret |= unit.kernel->get().setArg(idx++, mResource->mCoef); MNN_CHECK_CL_SUCCESS(ret, "setArg SharedGatherBufExecution"); mOpenCLBackend->recordKernel2d(unit.kernel, mGWS, mLWS); unit.globalWorkSize = {mGWS[0], mGWS[1]}; unit.localWorkSize = {mLWS[0], mLWS[1]}; return NO_ERROR; } } // namespace OpenCL } // namespace MNN #endif /* MNN_OPENCL_BUFFER_CLOSED */