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

Function HoistFakeQuants

tensorflow/tools/graph_transforms/quantize_nodes.cc:533–584  ·  view source on GitHub ↗

Sometimes FakeQuantWithMinMaxVars ops are added at the end of a chain of linear ops like Relu, MaxPool, etc, several steps from the Conv2D or BiasAdd op that we want to apply the trained constant conversions to. This pass tries to move FakeQuant ops up the input chain, so they're as close as possible to the 32-bit conversion, and so can be easily merged into the automatic dynamic Requantizes.

Source from the content-addressed store, hash-verified

531// the 32-bit conversion, and so can be easily merged into the automatic dynamic
532// Requantizes.
533Status HoistFakeQuants(const GraphDef& input_graph_def,
534 const TransformFuncContext& context,
535 GraphDef* output_graph_def) {
536 GraphDef current_graph_def = input_graph_def;
537 const int max_depth = 3;
538 for (int depth = max_depth; depth > 0; --depth) {
539 OpTypePattern pattern = {"*"};
540 for (int i = 0; i < depth; ++i) {
541 pattern = {"*", {pattern}};
542 }
543 pattern = {"FakeQuantWithMinMaxVars", {pattern, {"Const"}, {"Const"}}};
544 GraphDef hoisted_graph_def;
545 TF_RETURN_IF_ERROR(ReplaceMatchingOpTypes(
546 current_graph_def, pattern,
547 [depth](const NodeMatch& match, const std::set<string>& input_nodes,
548 const std::set<string>& output_nodes,
549 std::vector<NodeDef>* new_nodes) {
550 const NodeDef& fake_quant_node = match.node;
551 const NodeDef& fake_quant_min_node = match.inputs[1].node;
552 const NodeDef& fake_quant_max_node = match.inputs[2].node;
553 std::vector<NodeDef> linear_nodes;
554 NodeMatch current_match = match;
555 for (int i = 0; i <= depth; ++i) {
556 linear_nodes.push_back(current_match.inputs[0].node);
557 current_match = current_match.inputs[0];
558 }
559 NodeDef new_fake_quant_node;
560 new_fake_quant_node = fake_quant_node;
561 new_fake_quant_node.set_name(fake_quant_node.name() + "_hoisted");
562 new_fake_quant_node.set_input(
563 0, linear_nodes[linear_nodes.size() - 2].input(0));
564 new_nodes->push_back(new_fake_quant_node);
565
566 new_nodes->push_back(fake_quant_min_node);
567 new_nodes->push_back(fake_quant_max_node);
568
569 linear_nodes[linear_nodes.size() - 2].set_input(
570 0, new_fake_quant_node.name());
571 linear_nodes.front().set_name(fake_quant_node.name());
572 for (const NodeDef& linear_node : linear_nodes) {
573 new_nodes->push_back(linear_node);
574 }
575
576 return Status::OK();
577 },
578 {}, &hoisted_graph_def));
579 current_graph_def = hoisted_graph_def;
580 }
581 *output_graph_def = current_graph_def;
582
583 return Status::OK();
584}
585
586// Converts any float ops that have eight-bit equivalents into their quantized
587// forms, so that as much calculation as possible is done in the lower-precision

Callers 1

QuantizeNodesFunction · 0.85

Calls 8

ReplaceMatchingOpTypesFunction · 0.85
set_inputMethod · 0.80
nameMethod · 0.65
push_backMethod · 0.45
set_nameMethod · 0.45
inputMethod · 0.45
sizeMethod · 0.45
frontMethod · 0.45

Tested by

no test coverage detected