未验证 提交 18c0a002 编写于 作者: H Hulek 提交者: GitHub

Scale Matmul Fuse pass rewritten (#49105)

上级 aa96ddc3
......@@ -429,10 +429,6 @@ if(WITH_MKLDNN)
test_conv_batch_norm_mkldnn_fuse_pass
SRCS mkldnn/mkldnn_conv_bn_fuse_pass_tester.cc
DEPS ${TEST_CONV_BN_PASS_DEPS})
cc_test(
test_scale_matmul_fuse_pass
SRCS mkldnn/scale_matmul_fuse_pass_tester.cc
DEPS scale_matmul_fuse_pass)
cc_test(
test_mkldnn_placement_pass
SRCS mkldnn/mkldnn_placement_pass_tester.cc
......
// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <gtest/gtest.h>
#include "paddle/fluid/framework/ir/mkldnn/scale_matmul_fuse_pass.h"
namespace paddle {
namespace framework {
namespace ir {
void SetOp(ProgramDesc* prog,
const std::string& type,
const std::vector<std::string>& inputs,
const std::vector<std::string>& outputs,
float scale = 1.0f,
float bias = 0.0f) {
auto* op = prog->MutableBlock(0)->AppendOp();
op->SetType(type);
if (type == "scale") {
op->SetInput("X", {inputs[0]});
op->SetAttr("scale", scale);
op->SetAttr("bias", bias);
} else if (type == "matmul") {
op->SetAttr("transpose_X", false);
op->SetAttr("transpose_Y", false);
op->SetInput("X", {inputs[0]});
if (inputs.size() > 1) op->SetInput("Y", {inputs[1]});
op->SetAttr("alpha", scale);
} else {
FAIL() << "Unexpected operator type.";
}
op->SetOutput("Out", {outputs[0]});
}
// a->scale->b
// (b,c)->matmul->d
ProgramDesc BuildProgramDesc(float scale, float bias, float alpha) {
ProgramDesc prog;
for (auto& v : std::vector<std::string>({"a", "b", "c", "d"})) {
prog.MutableBlock(0)->Var(v);
}
SetOp(&prog, "scale", {"a"}, {"b"}, scale, bias);
SetOp(&prog, "matmul", {"b", "c"}, {"d"}, alpha);
return prog;
}
void MainTest(const ProgramDesc& prog,
int removed_nodes_count,
const std::vector<std::string> scale_in_out,
const std::vector<std::string> matmul_in_out,
float alpha) {
std::unique_ptr<ir::Graph> graph(new ir::Graph(prog));
int original_nodes_num = graph->Nodes().size();
auto pass = PassRegistry::Instance().Get("scale_matmul_fuse_pass");
graph.reset(pass->Apply(graph.release()));
int current_nodes_num = graph->Nodes().size();
for (auto* node : graph->Nodes()) {
if (node->IsOp()) {
auto* op = node->Op();
if (op->Type() == "scale") {
EXPECT_EQ(op->Input("X")[0], scale_in_out[0]);
EXPECT_EQ(op->Output("Out")[0], scale_in_out[1]);
} else if (op->Type() == "matmul") {
EXPECT_EQ(op->Input("X")[0], matmul_in_out[0]);
EXPECT_EQ(op->Input("Y")[0], matmul_in_out[1]);
EXPECT_EQ(op->Output("Out")[0], matmul_in_out[2]);
EXPECT_EQ(op->GetAttrIfExists<float>("alpha"), alpha);
}
}
}
EXPECT_EQ(original_nodes_num - removed_nodes_count, current_nodes_num);
}
TEST(ScaleMatmulFusePass, scale_matmul_with_no_bias) {
auto bias = 0.0f;
auto scale = 2.34f;
auto alpha = 3.45f;
int removed_nodes_count = 2;
MainTest(BuildProgramDesc(scale, bias, alpha),
removed_nodes_count,
{},
{"a", "c", "d"},
scale * alpha);
}
TEST(ScaleMatmulFusePass, scale_matmul_with_bias) {
auto bias = 1.0f;
auto scale = 2.34f;
auto alpha = 3.45f;
int removed_nodes_count = 0;
MainTest(BuildProgramDesc(scale, bias, alpha),
removed_nodes_count,
{"a", "b"},
{"b", "c", "d"},
alpha);
}
} // namespace ir
} // namespace framework
} // namespace paddle
USE_PASS(scale_matmul_fuse_pass);
......@@ -37,74 +37,55 @@ class TestScaleMatmulMkldnnFusePass(PassAutoScanTest):
input_dim = draw(st.sampled_from([1, 32, 64]))
def generate_input(attrs, type):
if attrs[1]['transpose_X'] and attrs[1]['transpose_Y']:
shape_x = [
attrs[2]['batch_size'],
attrs[2]['channel'],
attrs[2]['input_dim'],
32,
]
shape_y = [
attrs[2]['batch_size'],
attrs[2]['channel'],
64,
attrs[2]['input_dim'],
]
elif attrs[1]['transpose_X']:
shape_x = [
attrs[2]['batch_size'],
attrs[2]['channel'],
attrs[2]['input_dim'],
32,
]
shape_y = [
attrs[2]['batch_size'],
attrs[2]['channel'],
attrs[2]['input_dim'],
64,
]
elif attrs[1]['transpose_Y']:
shape_x = [
attrs[2]['batch_size'],
attrs[2]['channel'],
32,
attrs[2]['input_dim'],
]
shape_y = [
attrs[2]['batch_size'],
attrs[2]['channel'],
8,
attrs[2]['input_dim'],
]
is_transpose_X = attrs[1]['transpose_X']
is_transpose_Y = attrs[1]['transpose_Y']
if is_transpose_X:
shape_x_3 = attrs[2]['input_dim']
shape_x_4 = 32
else:
shape_x_3 = 32
shape_x_4 = attrs[2]['input_dim']
if is_transpose_X and is_transpose_Y:
shape_y_3 = 64
shape_y_4 = attrs[2]['input_dim']
elif is_transpose_X:
shape_y_3 = attrs[2]['input_dim']
shape_y_4 = 64
elif is_transpose_Y:
shape_y_3 = 8
shape_y_4 = attrs[2]['input_dim']
else:
shape_y_3 = attrs[2]['input_dim']
shape_y_4 = 16
shape_x = [
attrs[2]['batch_size'],
attrs[2]['channel'],
32,
attrs[2]['input_dim'],
shape_x_3,
shape_x_4,
]
shape_y = [
attrs[2]['batch_size'],
attrs[2]['channel'],
attrs[2]['input_dim'],
16,
shape_y_3,
shape_y_4,
]
if type == "x":
return np.random.random(shape_x).astype(np.float32)
else:
return np.random.random(shape_y).astype(np.float32)
shape = shape_x if type == 'x' else shape_y
return np.random.random(shape).astype(np.float32)
attrs = [
{
"scale": scale,
"bias": bias,
"bias_after_scale": bias_after_scale,
'scale': scale,
'bias': bias,
'bias_after_scale': bias_after_scale,
},
{
"transpose_X": transpose_X,
"transpose_Y": transpose_Y,
"alpha": alpha,
'transpose_X': transpose_X,
'transpose_Y': transpose_Y,
'alpha': alpha,
},
{
'batch_size': batch_size,
......@@ -115,29 +96,29 @@ class TestScaleMatmulMkldnnFusePass(PassAutoScanTest):
ops_config = [
{
"op_type": "scale",
"op_inputs": {"X": ["input_data1"]},
"op_outputs": {"Out": ["scale_output"]},
"op_attrs": {
"scale": attrs[0]['scale'],
"bias": attrs[0]['bias'],
"bias_after_scale": attrs[0]['bias_after_scale'],
'op_type': 'scale',
'op_inputs': {'X': ['input_data1']},
'op_outputs': {'Out': ['scale_output']},
'op_attrs': {
'scale': attrs[0]['scale'],
'bias': attrs[0]['bias'],
'bias_after_scale': attrs[0]['bias_after_scale'],
},
},
{
"op_type": "matmul",
"op_inputs": {"X": ["scale_output"], "Y": ["input_data2"]},
"op_outputs": {"Out": ["matmul_output"]},
"op_attrs": {
'op_type': 'matmul',
'op_inputs': {'X': ['scale_output'], 'Y': ['input_data2']},
'op_outputs': {'Out': ['matmul_output']},
'op_attrs': {
'transpose_X': attrs[1]['transpose_X'],
'transpose_Y': attrs[1]['transpose_Y'],
'alpha': attrs[1]['alpha'],
"fused_reshape_X": [],
"fused_reshape_Y": [],
"fused_transpose_X": [],
"fused_transpose_Y": [],
"fused_reshape_Out": [],
"fused_transpose_Out": [],
'fused_reshape_X': [],
'fused_reshape_Y': [],
'fused_transpose_X': [],
'fused_transpose_Y': [],
'fused_reshape_Out': [],
'fused_transpose_Out': [],
},
},
]
......@@ -148,25 +129,27 @@ class TestScaleMatmulMkldnnFusePass(PassAutoScanTest):
ops=ops,
weights={},
inputs={
"input_data1": TensorConfig(
data_gen=partial(generate_input, attrs, "x")
'input_data1': TensorConfig(
data_gen=partial(generate_input, attrs, 'x')
),
"input_data2": TensorConfig(
data_gen=partial(generate_input, attrs, "y")
'input_data2': TensorConfig(
data_gen=partial(generate_input, attrs, 'y')
),
},
outputs=["matmul_output"],
outputs=['matmul_output'],
)
return program_config
def sample_predictor_configs(self, program_config):
config = self.create_inference_config(use_mkldnn=True)
config = self.create_inference_config(
use_mkldnn=True, passes=['scale_matmul_fuse_pass']
)
yield config, ['matmul'], (1e-5, 1e-5)
def test(self):
self.run_and_statis(quant=False, passes=["scale_matmul_fuse_pass"])
self.run_and_statis(quant=False, passes=['scale_matmul_fuse_pass'])
if __name__ == "__main__":
if __name__ == '__main__':
unittest.main()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册