MCPcopy Create free account
hub / github.com/DeepRec-AI/DeepRec / QuantizeOpInput

Function QuantizeOpInput

tensorflow/lite/tools/optimize/quantize_model.cc:364–448  ·  view source on GitHub ↗

Quantize the op input. Will increment op_idx if ops are added.

Source from the content-addressed store, hash-verified

362
363// Quantize the op input. Will increment op_idx if ops are added.
364TfLiteStatus QuantizeOpInput(
365 ModelT* model, int32_t subgraph_idx, size_t* op_idx,
366 operator_property::OperatorProperty property,
367 const std::pair<int32_t, operator_property::TensorProperty>& input,
368 ErrorReporter* error_reporter) {
369 int32_t input_idx = input.first;
370 operator_property::TensorProperty tensor_property = input.second;
371 SubGraphT* subgraph = model->subgraphs.at(subgraph_idx).get();
372 OperatorT* op = subgraph->operators[*op_idx].get();
373 const BuiltinOperator op_code =
374 model->operator_codes[op->opcode_index]->builtin_code;
375 if (input_idx >= op->inputs.size()) {
376 error_reporter->Report(
377 "Required input index %d is larger than the input length of op "
378 "%s at index %d in subgraph %d",
379 input_idx, op->inputs.size(), EnumNameBuiltinOperator(op_code), *op_idx,
380 subgraph_idx);
381 return kTfLiteError;
382 }
383 const int32_t tensor_idx = op->inputs[input_idx];
384 TensorT* tensor = subgraph->tensors[tensor_idx].get();
385 const bool is_input_quantized = utils::QuantizationParametersExist(tensor);
386 if (property.quantizable && !is_input_quantized) {
387 // The operation is quantizable, but the input isn't yet quantized.
388 if (utils::HasBuffer(model, subgraph, tensor_idx)) {
389 // TODO(suharshs): Look at consumers, throw error if one consumer is
390 // per-channel and one per-layer.
391 if (utils::QuantizeWeight(model, tensor, tensor_property.per_axis,
392 tensor_property.per_axis_index) ==
393 kTfLiteError) {
394 error_reporter->Report(
395 "Unable to quantize buffer or min/max value for input %d "
396 "in op %s in subgraph %d, node: %d",
397 input_idx, EnumNameBuiltinOperator(op_code), subgraph_idx, *op_idx);
398 return kTfLiteError;
399 }
400 } else if (utils::HasMinMax(tensor)) {
401 // TODO(suharshs): Handle per-channel dynamic tensor.
402 if (IsSubgraphInput(subgraph, tensor_idx)) {
403 utils::QuantizeActivation(tensor);
404 } else {
405 // If the tensor is not a model input, we need to add a Quantize
406 // operation since the preceding op may require a float output.
407 std::unique_ptr<TensorT> op_output;
408 utils::MakeTensor(tensor->name + "_int8", tensor->shape,
409 TensorType_INT8, &op_output);
410 op_output->quantization = absl::make_unique<QuantizationParametersT>();
411 op_output->quantization->min.push_back(tensor->quantization->min[0]);
412 op_output->quantization->max.push_back(tensor->quantization->max[0]);
413 utils::QuantizeActivation(op_output.get());
414 const int32_t quant_op_output_idx = subgraph->tensors.size();
415 subgraph->tensors.push_back(std::move(op_output));
416 std::unique_ptr<OperatorT> quant_op;
417 utils::MakeQuantizeOperator(model, &quant_op, tensor_idx,
418 quant_op_output_idx);
419 subgraph->operators.insert(subgraph->operators.begin() + *op_idx,
420 std::move(quant_op));
421 op->inputs[input_idx] = quant_op_output_idx;

Callers 1

Calls 15

EnumNameBuiltinOperatorFunction · 0.85
HasBufferFunction · 0.85
QuantizeWeightFunction · 0.85
HasMinMaxFunction · 0.85
IsSubgraphInputFunction · 0.85
QuantizeActivationFunction · 0.85
MakeQuantizeOperatorFunction · 0.85
MakeTensorFunction · 0.70
MakeDequantizeOperatorFunction · 0.70
getMethod · 0.45
atMethod · 0.45

Tested by

no test coverage detected