|  |  | @ -14,6 +14,7 @@ | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "paddle/fluid/framework/ir/mkldnn/cpu_quantize_pass.h" |  |  |  | #include "paddle/fluid/framework/ir/mkldnn/cpu_quantize_pass.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | #include <gtest/gtest.h> |  |  |  | #include <gtest/gtest.h> | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "paddle/fluid/framework/naive_executor.h" |  |  |  | #include "paddle/fluid/framework/naive_executor.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "paddle/fluid/imperative/type_defs.h" |  |  |  | #include "paddle/fluid/imperative/type_defs.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "paddle/fluid/platform/place.h" |  |  |  | #include "paddle/fluid/platform/place.h" | 
			
		
	
	
		
		
			
				
					|  |  | @ -82,6 +83,14 @@ void SetOp(ProgramDesc* prog, const std::string& type, const std::string& name, | 
			
		
	
		
		
			
				
					
					|  |  |  |     op->SetAttr("Scale_x", 1.0f); |  |  |  |     op->SetAttr("Scale_x", 1.0f); | 
			
		
	
		
		
			
				
					
					|  |  |  |     op->SetAttr("Scale_y", 1.0f); |  |  |  |     op->SetAttr("Scale_y", 1.0f); | 
			
		
	
		
		
			
				
					
					|  |  |  |     op->SetAttr("Scale_out", 1.0f); |  |  |  |     op->SetAttr("Scale_out", 1.0f); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } else if (type == "elementwise_add") { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     op->SetInput("X", {inputs[0]}); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (inputs.size() > 1) op->SetInput("Y", {inputs[1]}); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     op->SetOutput("Out", {outputs[0]}); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     op->SetAttr("use_quantizer", use_quantizer); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     op->SetAttr("Scale_x", 1.0f); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     op->SetAttr("Scale_y", 1.0f); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     op->SetAttr("Scale_out", 1.0f); | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -95,7 +104,8 @@ void InitTensorHolder(Scope* scope, const paddle::platform::Place& place, | 
			
		
	
		
		
			
				
					
					|  |  |  | void PreparePass(std::unique_ptr<ir::Graph>* graph, const ProgramDesc& prog, |  |  |  | void PreparePass(std::unique_ptr<ir::Graph>* graph, const ProgramDesc& prog, | 
			
		
	
		
		
			
				
					
					|  |  |  |                  const std::initializer_list<std::string> variable_names, |  |  |  |                  const std::initializer_list<std::string> variable_names, | 
			
		
	
		
		
			
				
					
					|  |  |  |                  int* original_nodes_num, int* current_nodes_num, |  |  |  |                  int* original_nodes_num, int* current_nodes_num, | 
			
		
	
		
		
			
				
					
					|  |  |  |                  std::string var_without_scale = "") { |  |  |  |                  std::string var_without_scale = "", | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                  std::string var_signed = "") { | 
			
		
	
		
		
			
				
					
					|  |  |  |   auto place = paddle::platform::CPUPlace(); |  |  |  |   auto place = paddle::platform::CPUPlace(); | 
			
		
	
		
		
			
				
					
					|  |  |  |   NaiveExecutor exe{place}; |  |  |  |   NaiveExecutor exe{place}; | 
			
		
	
		
		
			
				
					
					|  |  |  |   Scope scope; |  |  |  |   Scope scope; | 
			
		
	
	
		
		
			
				
					|  |  | @ -108,8 +118,7 @@ void PreparePass(std::unique_ptr<ir::Graph>* graph, const ProgramDesc& prog, | 
			
		
	
		
		
			
				
					
					|  |  |  |     tensor.Resize({1}); |  |  |  |     tensor.Resize({1}); | 
			
		
	
		
		
			
				
					
					|  |  |  |     auto* ptr = tensor.mutable_data<double>(place); |  |  |  |     auto* ptr = tensor.mutable_data<double>(place); | 
			
		
	
		
		
			
				
					
					|  |  |  |     ptr[0] = 2.0; |  |  |  |     ptr[0] = 2.0; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |     (*scales)[v] = std::make_pair(v == var_signed, std::move(tensor)); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     (*scales)[v] = std::make_pair(false, std::move(tensor)); |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   (*graph)->SetNotOwned(kParamScopeAttr, &scope); |  |  |  |   (*graph)->SetNotOwned(kParamScopeAttr, &scope); | 
			
		
	
	
		
		
			
				
					|  |  | @ -387,7 +396,7 @@ static const std::initializer_list<std::string> variable_names_reshape = { | 
			
		
	
		
		
			
				
					
					|  |  |  | // c->Dropout->d
 |  |  |  | // c->Dropout->d
 | 
			
		
	
		
		
			
				
					
					|  |  |  | ProgramDesc BuildProgramDescReshape() { |  |  |  | ProgramDesc BuildProgramDescReshape() { | 
			
		
	
		
		
			
				
					
					|  |  |  |   ProgramDesc prog; |  |  |  |   ProgramDesc prog; | 
			
		
	
		
		
			
				
					
					|  |  |  |   for (auto& v : variable_names_transpose) { |  |  |  |   for (auto& v : variable_names_reshape) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     prog.MutableBlock(0)->Var(v); |  |  |  |     prog.MutableBlock(0)->Var(v); | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |   SetOp(&prog, "dequantize", "Dequantize1", {"a"}, {"b"}, true); |  |  |  |   SetOp(&prog, "dequantize", "Dequantize1", {"a"}, {"b"}, true); | 
			
		
	
	
		
		
			
				
					|  |  | @ -402,7 +411,7 @@ ProgramDesc BuildProgramDescReshape() { | 
			
		
	
		
		
			
				
					
					|  |  |  | // c->Dropout->d
 |  |  |  | // c->Dropout->d
 | 
			
		
	
		
		
			
				
					
					|  |  |  | ProgramDesc BuildProgramDescReshapeBetweenNonQuantizedOp() { |  |  |  | ProgramDesc BuildProgramDescReshapeBetweenNonQuantizedOp() { | 
			
		
	
		
		
			
				
					
					|  |  |  |   ProgramDesc prog; |  |  |  |   ProgramDesc prog; | 
			
		
	
		
		
			
				
					
					|  |  |  |   for (auto& v : variable_names_transpose) { |  |  |  |   for (auto& v : variable_names_reshape) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     prog.MutableBlock(0)->Var(v); |  |  |  |     prog.MutableBlock(0)->Var(v); | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -491,7 +500,7 @@ static const std::initializer_list<std::string> variable_names_matmul = { | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | ProgramDesc BuildProgramDescMatmul() { |  |  |  | ProgramDesc BuildProgramDescMatmul() { | 
			
		
	
		
		
			
				
					
					|  |  |  |   ProgramDesc prog; |  |  |  |   ProgramDesc prog; | 
			
		
	
		
		
			
				
					
					|  |  |  |   for (auto& v : variable_names_transpose) { |  |  |  |   for (auto& v : variable_names_matmul) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     prog.MutableBlock(0)->Var(v); |  |  |  |     prog.MutableBlock(0)->Var(v); | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |   SetOp(&prog, "dequantize", "Dequantize1", {"a"}, {"b"}, true); |  |  |  |   SetOp(&prog, "dequantize", "Dequantize1", {"a"}, {"b"}, true); | 
			
		
	
	
		
		
			
				
					|  |  | @ -504,7 +513,7 @@ ProgramDesc BuildProgramDescMatmul() { | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | ProgramDesc BuildProgramDescMatmulNotQuantized() { |  |  |  | ProgramDesc BuildProgramDescMatmulNotQuantized() { | 
			
		
	
		
		
			
				
					
					|  |  |  |   ProgramDesc prog; |  |  |  |   ProgramDesc prog; | 
			
		
	
		
		
			
				
					
					|  |  |  |   for (auto& v : variable_names_transpose) { |  |  |  |   for (auto& v : variable_names_matmul) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     prog.MutableBlock(0)->Var(v); |  |  |  |     prog.MutableBlock(0)->Var(v); | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |   SetOp(&prog, "dropout", "Dropout", {"a"}, {"b"}, false); |  |  |  |   SetOp(&prog, "dropout", "Dropout", {"a"}, {"b"}, false); | 
			
		
	
	
		
		
			
				
					|  |  | @ -569,6 +578,97 @@ TEST(CpuQuantizePass, matmul_not_quantized) { | 
			
		
	
		
		
			
				
					
					|  |  |  |   MainTestMatmul(BuildProgramDescMatmulNotQuantized(), matmul_count, |  |  |  |   MainTestMatmul(BuildProgramDescMatmulNotQuantized(), matmul_count, | 
			
		
	
		
		
			
				
					
					|  |  |  |                  quant_count, dequant_count, added_nodes_count, 1.0f); |  |  |  |                  quant_count, dequant_count, added_nodes_count, 1.0f); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | static const std::initializer_list<std::string> variable_names_elementwise_add = | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     {"a", "b", "c", "d", "e", "f"}; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | ProgramDesc BuildProgramDescElementwiseAdd() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   ProgramDesc prog; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   for (auto& v : variable_names_elementwise_add) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     prog.MutableBlock(0)->Var(v); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   SetOp(&prog, "dequantize", "Dequantize1", {"a"}, {"b"}, true); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   SetOp(&prog, "dequantize", "Dequantize2", {"c"}, {"d"}, true); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   SetOp(&prog, "elementwise_add", "ElementwiseAdd", {"b", "d"}, {"e"}, true, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         true); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   SetOp(&prog, "dropout", "Dropout", {"e"}, {"f"}, true, false); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   return prog; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | void MainTestElementwiseAdd(const ProgramDesc& prog, int elementwise_add_count, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                             int quant_count, int dequant_count, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                             int added_nodes_count, float scale, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                             bool output_scale_missing = false, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                             bool unsigned_and_signed_input = false) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   std::unique_ptr<ir::Graph> graph(new ir::Graph(prog)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int original_nodes_num, current_nodes_num; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   PreparePass(&graph, prog, variable_names_elementwise_add, &original_nodes_num, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |               ¤t_nodes_num, output_scale_missing ? "e" : "", | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |               unsigned_and_signed_input ? "b" : ""); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int quantize_nodes_count = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int dequantize_nodes_count = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int elementwise_add_nodes_count = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   for (auto* node : graph->Nodes()) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (node->IsOp()) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       auto* op = node->Op(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       if (op->Type() == "elementwise_add") { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         elementwise_add_nodes_count++; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (unsigned_and_signed_input) scale = 1.0f; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         auto op_name = BOOST_GET_CONST(std::string, op->GetAttr("name")); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         EXPECT_EQ(BOOST_GET_CONST(float, op->GetAttr("Scale_x")), scale) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             << "Scale_x for node '" + op_name + "'."; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         EXPECT_EQ(BOOST_GET_CONST(float, op->GetAttr("Scale_y")), scale) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             << "Scale_y for node '" + op_name + "'."; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (output_scale_missing) scale = 1.0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         EXPECT_EQ(BOOST_GET_CONST(float, op->GetAttr("Scale_out")), scale) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             << "Scale_out for node '" + op_name + "'."; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       } else if (op->Type() == "quantize") { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         quantize_nodes_count++; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       } else if (op->Type() == "dequantize") { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         dequantize_nodes_count++; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   EXPECT_EQ(elementwise_add_nodes_count, elementwise_add_count); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   EXPECT_EQ(quantize_nodes_count, quant_count); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   EXPECT_EQ(dequantize_nodes_count, dequant_count); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   EXPECT_EQ(original_nodes_num + added_nodes_count, current_nodes_num); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | TEST(CpuQuantizePass, elementwise_add) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int elementwise_add_count = 1; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int quant_count = 2; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int dequant_count = 3; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // 2 Quant + 2 IN + 1 DeQuant + 1 OUT
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int added_nodes_count = 6; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   MainTestElementwiseAdd(BuildProgramDescElementwiseAdd(), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                          elementwise_add_count, quant_count, dequant_count, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                          added_nodes_count, 2.0f * 127); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | TEST(CpuQuantizePass, elementwise_add_output_scale_missing) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int elementwise_add_count = 1; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int quant_count = 2; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int dequant_count = 2; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // 2 Quant + 2 IN
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int added_nodes_count = 4; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   MainTestElementwiseAdd(BuildProgramDescElementwiseAdd(), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                          elementwise_add_count, quant_count, dequant_count, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                          added_nodes_count, 2.0f * 127, true); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | TEST(CpuQuantizePass, elementwise_add_unsigned_and_signed_input) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int elementwise_add_count = 1; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int quant_count = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int dequant_count = 2; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int added_nodes_count = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   MainTestElementwiseAdd(BuildProgramDescElementwiseAdd(), | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                          elementwise_add_count, quant_count, dequant_count, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                          added_nodes_count, 2.0f * 127, false, true); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | }  // namespace
 |  |  |  | }  // namespace
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | }  // namespace ir
 |  |  |  | }  // namespace ir
 | 
			
		
	
	
		
		
			
				
					|  |  | 
 |