| 183 | } |
| 184 | |
| 185 | Execution* ConvolutionFloatFactory::create(const std::vector<Tensor*>& inputs, const std::vector<Tensor*>& outputs, |
| 186 | const MNN::Op* op, Backend* backend) { |
| 187 | auto conv2d = op->main_as_Convolution2D(); |
| 188 | if (inputs.size() > 1) { |
| 189 | // Multi Input |
| 190 | return new ConvolutionTiledExecutorMultiInput(conv2d->common(), backend); |
| 191 | } |
| 192 | #ifdef MNN_LOW_MEMORY |
| 193 | bool lowMemory = static_cast<CPUBackend*>(backend)->memoryMode() == BackendConfig::Memory_Low; |
| 194 | if (lowMemory && static_cast<CPUBackend*>(backend)->functions()->bytes == 2 && static_cast<CPUBackend*>(backend)->int8Functions()->MNNGemmInt8AddBiasScale_Unit_FP16 == nullptr) { |
| 195 | // Fall back to fp32 |
| 196 | return nullptr; |
| 197 | } |
| 198 | #else |
| 199 | bool lowMemory = false; |
| 200 | #endif |
| 201 | |
| 202 | const float* originWeight = nullptr; |
| 203 | const float* originBias = nullptr; |
| 204 | int originWeightSize = 0; |
| 205 | int originBiasSize = 0; |
| 206 | std::shared_ptr<ConvolutionCommon::Int8Common> quanCommon; |
| 207 | std::unique_ptr<Tensor> externalWeightTensor, externalBiasTensor; |
| 208 | bool supportSparse = false; |
| 209 | auto core = static_cast<CPUBackend*>(backend)->functions(); |
| 210 | int bytes = core->bytes; |
| 211 | #ifdef MNN_USE_SPARSE_COMPUTE |
| 212 | #ifdef MNN_USE_SSE |
| 213 | const bool onlySSENotAVX = core->pack == 4; // no backend of only sse without avx2 or avx512 |
| 214 | #else |
| 215 | const bool onlySSENotAVX = false; |
| 216 | #endif |
| 217 | supportSparse = !onlySSENotAVX && bytes == 4; |
| 218 | #endif |
| 219 | if (nullptr != conv2d->quanParameter()) { |
| 220 | bool forceFloat = false; |
| 221 | if (!supportSparse && conv2d->quanParameter()->index() != nullptr) { |
| 222 | // The weight is storage as float sparse, but the backend don't support sparse compute, expand it |
| 223 | forceFloat = true; |
| 224 | } |
| 225 | quanCommon = ConvolutionCommon::load(op, backend, forceFloat, lowMemory); |
| 226 | if (nullptr == quanCommon) { |
| 227 | MNN_ERROR("Memory not Enough, can't extract IDST Convolution: %s \n", op->name()->c_str()); |
| 228 | return nullptr; |
| 229 | } |
| 230 | |
| 231 | if (conv2d->quanParameter()->has_scaleInt()) { |
| 232 | if (bytes < 4) { |
| 233 | // From BF16 / FP16 |
| 234 | return nullptr; |
| 235 | } |
| 236 | return ConvolutionIntFactory::create(inputs[0], outputs[0], op, backend, quanCommon.get()); |
| 237 | } |
| 238 | // Back to float |
| 239 | originWeight = quanCommon->weightFloat.get(); |
| 240 | originWeightSize = quanCommon->weightFloat.size(); |
| 241 | } else if (nullptr == conv2d->weight() || nullptr == conv2d->bias()) { |
| 242 | MNN_ERROR("%s has no weight or bias. The model may be benchmark model, please revert the weight/bias firstly\n", op->name()->c_str()); |
nothing calls this directly
no test coverage detected