| 119 | #endif //MNN_KLEIDIAI_ENABLED |
| 120 | |
| 121 | static Execution* _createUnit(const Tensor* input, const Tensor* output, Backend* backend, |
| 122 | const Op* op, const float* originWeight, size_t originWeightSize, const float* bias, size_t biasSize, std::shared_ptr<ConvolutionCommon::Int8Common> weightQuantInfo, bool supportSparse, bool lowMemory) { |
| 123 | auto cpuBackend = (CPUBackend*)backend; |
| 124 | auto conv2d = op->main_as_Convolution2D(); |
| 125 | auto common = conv2d->common(); |
| 126 | #ifdef MNN_USE_ONEDNN |
| 127 | return OneDNN::createConvolution(common, backend, originWeight, originWeightSize, bias, biasSize); |
| 128 | #endif |
| 129 | |
| 130 | #ifdef MNN_USE_SPARSE_COMPUTE |
| 131 | if (conv2d->sparseParameter() && nullptr != weightQuantInfo.get()) { |
| 132 | if (supportSparse && weightQuantInfo->quan->index() != nullptr) { |
| 133 | return new SparseConvolutionTiledExecutor(common, backend, weightQuantInfo->quan, |
| 134 | conv2d->sparseParameter(), bias, biasSize); |
| 135 | } |
| 136 | } |
| 137 | #endif |
| 138 | |
| 139 | #ifdef MNN_KLEIDIAI_ENABLED |
| 140 | if (cpuBackend->getRuntime()->hint().enableKleidiAI) { |
| 141 | auto execution = _createKleidiAIUnit(input, output, backend, op, originWeight, originWeightSize, bias, biasSize, |
| 142 | weightQuantInfo, supportSparse, lowMemory); |
| 143 | |
| 144 | if (execution) { |
| 145 | return execution; |
| 146 | } |
| 147 | } |
| 148 | #endif //MNN_KLEIDIAI_ENABLED |
| 149 | |
| 150 | bool fastWay = common->kernelY() == 1 && common->kernelX() == 1 |
| 151 | && output->width() == input->width() && output->height() == input->height() |
| 152 | && common->strideX() == 1 && common->strideY() == 1; |
| 153 | #ifdef MNN_LOW_MEMORY |
| 154 | if (lowMemory && nullptr != weightQuantInfo.get() && originWeightSize == 0) { |
| 155 | if (cpuBackend->memoryMode() == BackendConfig::Memory_Low) { |
| 156 | return new DenseConvInt8TiledExecutor(backend, op, weightQuantInfo, true); |
| 157 | } else { |
| 158 | return new DenseConvolutionTiledExecutor(common, backend, originWeight, originWeightSize, bias, biasSize, weightQuantInfo); |
| 159 | } |
| 160 | } |
| 161 | #else |
| 162 | if (cpuBackend->memoryMode() == BackendConfig::Memory_Low) { |
| 163 | return new DenseConvolutionTiledExecutor(common, backend, originWeight, originWeightSize, bias, biasSize, weightQuantInfo); |
| 164 | } |
| 165 | #endif |
| 166 | |
| 167 | #ifndef MNN_REDUCE_SIZE |
| 168 | if (fastWay && cpuBackend->functions()->matmulBytes == 0) { |
| 169 | return new Convolution1x1Strassen(common, backend, originWeight, originWeightSize, bias, biasSize); |
| 170 | } |
| 171 | #endif |
| 172 | |
| 173 | if (cpuBackend->getRuntime()->hint().winogradMemoryUsed == 0 || (!ConvolutionWinogradBridge::canUseWinograd(common))) { |
| 174 | return new DenseConvolutionTiledExecutor(common, backend, originWeight, originWeightSize, bias, biasSize, nullptr); |
| 175 | } |
| 176 | PerfConfig convPerfconfig = DenseConvolutionTiledExecutor::bestTileConvolutionConfig(common, input, output, cpuBackend->threadNumber(), backend); |
| 177 | auto winogradConfig = ConvolutionWinogradBridge::bestWinogradUnit(common, input, output, cpuBackend->threadNumber(), backend, convPerfconfig); |
| 178 | if (winogradConfig.unit <= 1) { |
no test coverage detected