chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
# XPU IR Pass Tests
|
||||
|
||||
cc_test(
|
||||
test_cast_mixed_precision_op_fuse_pass
|
||||
SRCS cast_mixed_precision_op_fuse_pass_test.cc
|
||||
DEPS cast_mixed_precision_op_fuse_pass)
|
||||
|
||||
cc_test(
|
||||
test_delete_isolated_node_pass
|
||||
SRCS delete_isolated_node_pass_test.cc
|
||||
DEPS delete_isolated_node_pass)
|
||||
|
||||
cc_test(
|
||||
test_fused_multi_transformer_xpu_pass
|
||||
SRCS fused_multi_transformer_xpu_pass_test.cc
|
||||
DEPS fused_multi_transformer_xpu_pass)
|
||||
|
||||
cc_test(
|
||||
test_fused_multi_transformer_int8_xpu_quant_pass
|
||||
SRCS fused_multi_transformer_int8_xpu_quant_pass_test.cc
|
||||
DEPS fused_multi_transformer_int8_xpu_quant_pass)
|
||||
|
||||
cc_test(
|
||||
test_one_beam_size_fuse_pass
|
||||
SRCS one_beam_size_fuse_pass_test.cc
|
||||
DEPS one_beam_size_fuse_pass)
|
||||
|
||||
cc_test(
|
||||
test_stack_fuse_pass
|
||||
SRCS stack_fuse_pass_test.cc
|
||||
DEPS stack_fuse_pass)
|
||||
|
||||
cc_test(
|
||||
test_fused_multi_transformer_cachekv_layout_trans_pass
|
||||
SRCS fused_multi_transformer_cachekv_layout_trans_pass_test.cc
|
||||
DEPS fused_multi_transformer_cachekv_layout_trans_pass)
|
||||
|
||||
cc_test(
|
||||
test_fused_multi_transformer_int8_cachekv_layout_trans_pass
|
||||
SRCS fused_multi_transformer_int8_cachekv_layout_trans_pass_test.cc
|
||||
DEPS fused_multi_transformer_int8_cachekv_layout_trans_pass)
|
||||
|
||||
cc_test(
|
||||
test_multi_encoder_xpu_adaptive_seqlen_fuse_pass
|
||||
SRCS multi_encoder_xpu_adaptive_seqlen_fuse_pass_test.cc
|
||||
DEPS multi_encoder_xpu_adaptive_seqlen_fuse_pass)
|
||||
|
||||
cc_test(
|
||||
test_xpu_delete_cast_op_pass
|
||||
SRCS xpu_delete_cast_op_pass_test.cc
|
||||
DEPS xpu_delete_cast_op_pass)
|
||||
|
||||
cc_test(
|
||||
test_fold_interp_outsize_fuse_pass
|
||||
SRCS fold_interp_outsize_fuse_pass_test.cc
|
||||
DEPS fold_interp_outsize_fuse_pass)
|
||||
|
||||
cc_test(
|
||||
test_fold_two_squeeze2_fuse_pass
|
||||
SRCS fold_two_squeeze2_fuse_pass_test.cc
|
||||
DEPS fold_two_squeeze2_fuse_pass)
|
||||
|
||||
cc_test(
|
||||
test_matmul_weight_trans_pass
|
||||
SRCS matmul_weight_trans_pass_test.cc
|
||||
DEPS matmul_weight_trans_pass)
|
||||
|
||||
cc_test(
|
||||
test_reshape2_matmul_xpu_fuse_pass
|
||||
SRCS reshape2_matmul_xpu_fuse_pass_test.cc
|
||||
DEPS reshape2_matmul_xpu_fuse_pass)
|
||||
|
||||
cc_test(
|
||||
test_fast_where_xpu_fuse_pass
|
||||
SRCS fast_where_xpu_fuse_pass_test.cc
|
||||
DEPS fast_where_xpu_fuse_pass)
|
||||
|
||||
cc_test(
|
||||
test_squeeze_excitation_fuse_pass
|
||||
SRCS squeeze_excitation_fuse_pass_test.cc
|
||||
DEPS squeeze_excitation_fuse_pass)
|
||||
@@ -0,0 +1,71 @@
|
||||
// Copyright (c) 2023 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/pass.h"
|
||||
#include "paddle/fluid/framework/ir/pass_tester_helper.h"
|
||||
|
||||
namespace paddle {
|
||||
namespace framework {
|
||||
namespace ir {
|
||||
|
||||
TEST(CastMixedPrecisionOpFusePass, cast_before) {
|
||||
Layers layers;
|
||||
auto* block = layers.Block();
|
||||
|
||||
auto* cast_in = layers.data("cast_in");
|
||||
auto* cast_out = layers.cast(cast_in, 5, 4);
|
||||
OpDesc* conv2d_xpu = block->AppendOp();
|
||||
conv2d_xpu->SetType("conv2d_xpu");
|
||||
conv2d_xpu->SetInput("x", {cast_out->Name()});
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
auto pass = PassRegistry::Instance().Get("cast_mixed_precision_op_fuse_pass");
|
||||
pass->Apply(graph.get());
|
||||
auto num = GetNumOpNodes(graph, "cast");
|
||||
PADDLE_ENFORCE_EQ(
|
||||
num,
|
||||
0,
|
||||
common::errors::PreconditionNotMet(
|
||||
"cast op should be removed from graph, but graph still has %d ops.",
|
||||
num));
|
||||
}
|
||||
|
||||
TEST(CastMixedPrecisionOpFusePass, cast_after) {
|
||||
Layers layers;
|
||||
auto* block = layers.Block();
|
||||
|
||||
auto* cast_in = layers.data("cast_in");
|
||||
OpDesc* conv2d_xpu = block->AppendOp();
|
||||
conv2d_xpu->SetType("conv2d_xpu");
|
||||
conv2d_xpu->SetOutput("out", {cast_in->Name()});
|
||||
layers.cast(cast_in, 4, 5);
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
auto pass = PassRegistry::Instance().Get("cast_mixed_precision_op_fuse_pass");
|
||||
pass->Apply(graph.get());
|
||||
auto num = GetNumOpNodes(graph, "cast");
|
||||
PADDLE_ENFORCE_EQ(
|
||||
num,
|
||||
0,
|
||||
common::errors::PreconditionNotMet(
|
||||
"cast op should be removed from graph, but graph still has %d ops.",
|
||||
num));
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace framework
|
||||
} // namespace paddle
|
||||
|
||||
USE_PASS(cast_mixed_precision_op_fuse_pass);
|
||||
@@ -0,0 +1,181 @@
|
||||
// Copyright (c) 2023 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/pass.h"
|
||||
#include "paddle/fluid/framework/ir/pass_tester_helper.h"
|
||||
|
||||
namespace paddle {
|
||||
namespace framework {
|
||||
namespace ir {
|
||||
|
||||
VarDesc* Data(paddle::framework::BlockDesc* block,
|
||||
std::string name,
|
||||
std::vector<int64_t> shape = {},
|
||||
bool is_persistable = false,
|
||||
proto::VarType::Type data_type = proto::VarType::FP32) {
|
||||
auto* var = block->Var(name);
|
||||
var->SetType(proto::VarType::DENSE_TENSOR);
|
||||
var->SetDataType(data_type);
|
||||
var->SetShape(shape);
|
||||
var->SetPersistable(is_persistable);
|
||||
return var;
|
||||
}
|
||||
|
||||
void AddVarToScope(Scope* param_scope,
|
||||
const std::string& name,
|
||||
const DDim& dims) {
|
||||
auto* tensor = param_scope->Var(name)->GetMutable<phi::DenseTensor>();
|
||||
tensor->Resize(dims);
|
||||
auto* cpu_ctx = static_cast<phi::CPUContext*>(
|
||||
phi::DeviceContextPool::Instance().Get(phi::CPUPlace()));
|
||||
auto* data = cpu_ctx->Alloc<float>(tensor);
|
||||
int64_t numel = tensor->numel();
|
||||
for (int64_t i = 0; i < numel; ++i) {
|
||||
data[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
Scope* CreateParamScope() {
|
||||
auto param_scope = new Scope();
|
||||
AddVarToScope(param_scope, "matmul0_w", {128, 128});
|
||||
return param_scope;
|
||||
}
|
||||
|
||||
int WeightNodeNum(ir::Graph* graph) {
|
||||
int num = 0;
|
||||
for (auto node : graph->Nodes()) {
|
||||
if (node->IsVar() && node->Var()->Persistable()) {
|
||||
num++;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
int WeightTensorNum(Scope* scope) {
|
||||
int num = 0;
|
||||
auto vars = scope->LocalVars();
|
||||
for (auto* var : vars) {
|
||||
if (var->Get<phi::DenseTensor>().numel() > 0) {
|
||||
num++;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
TEST(delete_isolated_node_pass, basic) {
|
||||
paddle::framework::ProgramDesc program;
|
||||
auto* block0 = program.MutableBlock(0);
|
||||
auto* block1 = program.AppendBlock(*block0);
|
||||
|
||||
auto* matmul0_x = Data(block0, "matmul0_x", {1, 128});
|
||||
auto* matmul0_w = Data(block0, "matmul0_w", {128, 128}, true);
|
||||
auto* matmul0_out = Data(block0, "matmul0_out", {1, 128});
|
||||
OpDesc* matmul_op = block0->AppendOp();
|
||||
matmul_op->SetType("matmul_v2");
|
||||
matmul_op->SetInput("X", {matmul0_x->Name()});
|
||||
matmul_op->SetInput("Y", {matmul0_w->Name()});
|
||||
matmul_op->SetAttr("trans_x", false);
|
||||
matmul_op->SetAttr("trans_y", false);
|
||||
matmul_op->SetOutput("Out", {matmul0_out->Name()});
|
||||
|
||||
auto* while_out = Data(block0, "while_out", {1, 128});
|
||||
auto* while_step_scopes = Data(block0, "while_step_scopes");
|
||||
auto* while_cond = Data(block0, "while_cond");
|
||||
OpDesc* while_op = block0->AppendOp();
|
||||
while_op->SetType("while");
|
||||
while_op->SetInput("X", {matmul0_w->Name(), matmul0_out->Name()});
|
||||
while_op->SetInput("Condition", {while_cond->Name()});
|
||||
while_op->SetOutput("Out", {while_out->Name()});
|
||||
while_op->SetOutput("StepScopes", {while_step_scopes->Name()});
|
||||
while_op->SetAttr("sub_block", {block1});
|
||||
while_op->SetAttr("is_test", true);
|
||||
|
||||
auto* matmul1_x = Data(block1, matmul0_out->Name(), matmul0_out->GetShape());
|
||||
auto* matmul1_w =
|
||||
Data(block1, matmul0_w->Name(), matmul0_w->GetShape(), true);
|
||||
auto* matmul1_out = Data(block1, "matmul1_out", {1, 128});
|
||||
OpDesc* matmul1_op = block1->AppendOp();
|
||||
matmul1_op->SetType("matmul_v2");
|
||||
matmul1_op->SetInput("X", {matmul1_x->Name()});
|
||||
matmul1_op->SetInput("Y", {matmul1_w->Name()});
|
||||
matmul1_op->SetAttr("trans_x", false);
|
||||
matmul1_op->SetAttr("trans_y", false);
|
||||
matmul1_op->SetOutput("Out", {matmul1_out->Name()});
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(program));
|
||||
auto* scope = CreateParamScope();
|
||||
graph->Set("__param_scope__", scope);
|
||||
auto pass0 = PassRegistry::Instance().Get("fc_xpu_fuse_pass");
|
||||
pass0->Apply(graph.get());
|
||||
pass0->Apply(graph->GetSubGraph(1));
|
||||
int weight_node_num =
|
||||
WeightNodeNum(graph.get()) + WeightNodeNum(graph->GetSubGraph(1));
|
||||
PADDLE_ENFORCE_EQ(weight_node_num,
|
||||
6,
|
||||
common::errors::PreconditionNotMet(
|
||||
"Graph should have 6 weight node after "
|
||||
"fc_xpu_fuse_pass, but actually has %d.",
|
||||
weight_node_num));
|
||||
|
||||
auto pass1 = PassRegistry::Instance().Get("delete_isolated_node_pass");
|
||||
pass1->Apply(graph.get());
|
||||
weight_node_num =
|
||||
WeightNodeNum(graph.get()) + WeightNodeNum(graph->GetSubGraph(1));
|
||||
PADDLE_ENFORCE_EQ(weight_node_num,
|
||||
4,
|
||||
common::errors::PreconditionNotMet(
|
||||
"Graph should have 4 weight node after "
|
||||
"delete_isolated_node_pass, but actually has %d.",
|
||||
weight_node_num));
|
||||
int weight_tensor_num = WeightTensorNum(scope);
|
||||
PADDLE_ENFORCE_EQ(weight_tensor_num,
|
||||
2,
|
||||
common::errors::PreconditionNotMet(
|
||||
"Scope should have 2 weight tensor after "
|
||||
"delete_isolated_node_pass, but actually has %d.",
|
||||
weight_tensor_num));
|
||||
|
||||
for (auto* node : graph->Nodes()) {
|
||||
if (node->IsOp() && node->Op()->Type() == "while") {
|
||||
auto while_in_names = node->Op()->Inputs().at("X");
|
||||
PADDLE_ENFORCE_EQ(while_in_names.size(),
|
||||
3,
|
||||
common::errors::PreconditionNotMet(
|
||||
"While op should have 3 input after "
|
||||
"delete_isolated_node_pass, but actually has %d.",
|
||||
while_in_names.size()));
|
||||
}
|
||||
}
|
||||
|
||||
Scope& scope0 = graph->Get<framework::Scope>("__param_scope__");
|
||||
Scope& scope1 =
|
||||
graph->GetSubGraph(1)->Get<framework::Scope>("__param_scope__");
|
||||
std::vector<std::string> shared_weight_names{matmul0_w->Name() + "_int16",
|
||||
matmul0_w->Name() + "_max"};
|
||||
for (auto name : shared_weight_names) {
|
||||
auto* var0 = scope0.FindVar(name);
|
||||
auto* var1 = scope1.FindVar(name);
|
||||
PADDLE_ENFORCE(
|
||||
var0 == var1,
|
||||
common::errors::PreconditionNotMet(
|
||||
"Variables with the same name in two scopes is different."));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace framework
|
||||
} // namespace paddle
|
||||
|
||||
USE_PASS(delete_isolated_node_pass);
|
||||
@@ -0,0 +1,304 @@
|
||||
// Copyright (c) 2023 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/pass.h"
|
||||
#include "paddle/fluid/framework/ir/pass_tester_helper.h"
|
||||
|
||||
namespace paddle {
|
||||
namespace framework {
|
||||
namespace ir {
|
||||
|
||||
#define APPLY_PASS \
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program())); \
|
||||
auto pass = PassRegistry::Instance().Get("fast_where_xpu_fuse_pass"); \
|
||||
pass->Apply(graph.get());
|
||||
|
||||
#define VERIFY_GRAPH(x, y) \
|
||||
auto num_op_nodes = GetNumOpNodes(graph); \
|
||||
PADDLE_ENFORCE_EQ( \
|
||||
num_op_nodes, \
|
||||
1, \
|
||||
common::errors::PreconditionNotMet( \
|
||||
"The graph contains only one op node, but %d op nodes found.", \
|
||||
num_op_nodes)); \
|
||||
auto fast_where_xpu_op_nodes = GetOpNodes(graph, "fast_where_xpu"); \
|
||||
PADDLE_ENFORCE_EQ(fast_where_xpu_op_nodes.size(), \
|
||||
1, \
|
||||
common::errors::PreconditionNotMet( \
|
||||
"The graph contains only a fast_where_xpu op node, " \
|
||||
"but %d op nodes found.", \
|
||||
fast_where_xpu_op_nodes.size())); \
|
||||
const auto& x_name = fast_where_xpu_op_nodes[0]->Op()->Input("x")[0]; \
|
||||
PADDLE_ENFORCE_EQ(x_name, \
|
||||
#x, \
|
||||
common::errors::PreconditionNotMet( \
|
||||
"The input 'x' of fast_where_xpu op should be '%s', " \
|
||||
"but receive '%s'.", \
|
||||
#x, \
|
||||
x_name)); \
|
||||
const auto& y_name = fast_where_xpu_op_nodes[0]->Op()->Input("y")[0]; \
|
||||
PADDLE_ENFORCE_EQ(y_name, \
|
||||
#y, \
|
||||
common::errors::PreconditionNotMet( \
|
||||
"The input 'y' of fast_where_xpu op should be '%s', " \
|
||||
"but receive '%s'.", \
|
||||
#y, \
|
||||
y_name));
|
||||
|
||||
TEST(FastWhereXPUFusePass, one_case0) {
|
||||
Layers layers;
|
||||
auto* condition =
|
||||
layers.data("condition", {20, 1}, false, proto::VarType::BOOL);
|
||||
auto* x = layers.data("x", {20, 7});
|
||||
auto* y = layers.data("y", {20, 7});
|
||||
auto* cast_out = layers.cast(condition, 0, 5);
|
||||
cast_out->SetShape({20, 1});
|
||||
auto* scale_out = layers.scale(cast_out, -1.0f, 1.0f, true);
|
||||
scale_out->SetShape({20, 1});
|
||||
auto* mul0_out = layers.elementwise_mul(x, scale_out);
|
||||
mul0_out->SetShape({20, 7});
|
||||
auto* mul1_out = layers.elementwise_mul(y, cast_out);
|
||||
mul1_out->SetShape({20, 7});
|
||||
auto* add_out = layers.elementwise_add(mul0_out, mul1_out);
|
||||
add_out->SetShape({20, 7});
|
||||
|
||||
APPLY_PASS
|
||||
VERIFY_GRAPH(y, x)
|
||||
}
|
||||
|
||||
TEST(FastWhereXPUFusePass, one_case1) {
|
||||
Layers layers;
|
||||
auto* condition =
|
||||
layers.data("condition", {20, 1}, false, proto::VarType::BOOL);
|
||||
auto* x = layers.data("x", {20, 7});
|
||||
auto* y = layers.data("y", {20, 7});
|
||||
auto* cast_out = layers.cast(condition, 0, 5);
|
||||
cast_out->SetShape({20, 1});
|
||||
auto* mul0_out = layers.elementwise_mul(x, cast_out);
|
||||
mul0_out->SetShape({20, 7});
|
||||
auto* scale_out = layers.scale(cast_out, -1.0f, 1.0f, true);
|
||||
scale_out->SetShape({20, 1});
|
||||
auto* mul1_out = layers.elementwise_mul(y, scale_out);
|
||||
mul1_out->SetShape({20, 7});
|
||||
auto* add_out = layers.elementwise_add(mul0_out, mul1_out);
|
||||
add_out->SetShape({20, 7});
|
||||
|
||||
APPLY_PASS
|
||||
VERIFY_GRAPH(x, y)
|
||||
}
|
||||
|
||||
TEST(FastWhereXPUFusePass, one_case2) {
|
||||
Layers layers;
|
||||
auto* condition =
|
||||
layers.data("condition", {20, 1}, false, proto::VarType::BOOL);
|
||||
auto* x = layers.data("x", {20, 7});
|
||||
auto* y = layers.data("y", {20, 7});
|
||||
auto* cast_out = layers.cast(condition, 0, 5);
|
||||
cast_out->SetShape({20, 1});
|
||||
auto* scale_out = layers.scale(cast_out, -1.0f, 1.0f, true);
|
||||
scale_out->SetShape({20, 1});
|
||||
auto* mul0_out = layers.elementwise_mul(scale_out, x);
|
||||
mul0_out->SetShape({20, 7});
|
||||
auto* mul1_out = layers.elementwise_mul(cast_out, y);
|
||||
mul1_out->SetShape({20, 7});
|
||||
auto* add_out = layers.elementwise_add(mul0_out, mul1_out);
|
||||
add_out->SetShape({20, 7});
|
||||
|
||||
APPLY_PASS
|
||||
VERIFY_GRAPH(y, x)
|
||||
}
|
||||
|
||||
TEST(FastWhereXPUFusePass, one_case3) {
|
||||
Layers layers;
|
||||
auto* condition =
|
||||
layers.data("condition", {20, 1}, false, proto::VarType::BOOL);
|
||||
auto* x = layers.data("x", {20, 7});
|
||||
auto* y = layers.data("y", {20, 7});
|
||||
auto* cast_out = layers.cast(condition, 0, 5);
|
||||
cast_out->SetShape({20, 1});
|
||||
auto* mul0_out = layers.elementwise_mul(cast_out, x);
|
||||
mul0_out->SetShape({20, 7});
|
||||
auto* scale_out = layers.scale(cast_out, -1.0f, 1.0f, true);
|
||||
scale_out->SetShape({20, 1});
|
||||
auto* mul1_out = layers.elementwise_mul(scale_out, y);
|
||||
mul1_out->SetShape({20, 7});
|
||||
auto* add_out = layers.elementwise_add(mul0_out, mul1_out);
|
||||
add_out->SetShape({20, 7});
|
||||
|
||||
APPLY_PASS
|
||||
VERIFY_GRAPH(x, y)
|
||||
}
|
||||
|
||||
TEST(FastWhereXPUFusePass, one_case4) {
|
||||
Layers layers;
|
||||
auto* condition =
|
||||
layers.data("condition", {20, 1}, false, proto::VarType::BOOL);
|
||||
auto* x = layers.data("x", {20, 7});
|
||||
auto* y = layers.data("y", {20, 7});
|
||||
auto* cast_out = layers.cast(condition, 0, 5);
|
||||
cast_out->SetShape({20, 1});
|
||||
auto* scale_out = layers.scale(cast_out, -1.0f, 1.0f, true);
|
||||
scale_out->SetShape({20, 1});
|
||||
auto* mul0_out = layers.elementwise_mul(scale_out, x);
|
||||
mul0_out->SetShape({20, 7});
|
||||
auto* mul1_out = layers.elementwise_mul(y, cast_out);
|
||||
mul1_out->SetShape({20, 7});
|
||||
auto* add_out = layers.elementwise_add(mul0_out, mul1_out);
|
||||
add_out->SetShape({20, 7});
|
||||
|
||||
APPLY_PASS
|
||||
VERIFY_GRAPH(y, x)
|
||||
}
|
||||
|
||||
TEST(FastWhereXPUFusePass, one_case5) {
|
||||
Layers layers;
|
||||
auto* condition =
|
||||
layers.data("condition", {20, 1}, false, proto::VarType::BOOL);
|
||||
auto* x = layers.data("x", {20, 7});
|
||||
auto* y = layers.data("y", {20, 7});
|
||||
auto* cast_out = layers.cast(condition, 0, 5);
|
||||
cast_out->SetShape({20, 1});
|
||||
auto* mul0_out = layers.elementwise_mul(cast_out, x);
|
||||
mul0_out->SetShape({20, 7});
|
||||
auto* scale_out = layers.scale(cast_out, -1.0f, 1.0f, true);
|
||||
scale_out->SetShape({20, 1});
|
||||
auto* mul1_out = layers.elementwise_mul(y, scale_out);
|
||||
mul1_out->SetShape({20, 7});
|
||||
auto* add_out = layers.elementwise_add(mul0_out, mul1_out);
|
||||
add_out->SetShape({20, 7});
|
||||
|
||||
APPLY_PASS
|
||||
VERIFY_GRAPH(x, y)
|
||||
}
|
||||
|
||||
#undef VERIFY_GRAPH
|
||||
#define VERIFY_GRAPH(logical_op, x, y) \
|
||||
auto num_op_nodes = GetNumOpNodes(graph); \
|
||||
PADDLE_ENFORCE_EQ( \
|
||||
num_op_nodes, \
|
||||
2, \
|
||||
common::errors::PreconditionNotMet( \
|
||||
"The graph contains only two op nodes, but %d op nodes found.", \
|
||||
num_op_nodes)); \
|
||||
auto logical_op_nodes = GetOpNodes(graph, #logical_op); \
|
||||
PADDLE_ENFORCE_EQ( \
|
||||
logical_op_nodes.size(), \
|
||||
1, \
|
||||
common::errors::PreconditionNotMet( \
|
||||
"The graph contains only a '%s' op node, but %d op nodes found.", \
|
||||
#logical_op, \
|
||||
logical_op_nodes.size())); \
|
||||
auto fast_where_xpu_op_nodes = GetOpNodes(graph, "fast_where_xpu"); \
|
||||
PADDLE_ENFORCE_EQ(fast_where_xpu_op_nodes.size(), \
|
||||
1, \
|
||||
common::errors::PreconditionNotMet( \
|
||||
"The graph contains only a fast_where_xpu op node, " \
|
||||
"but %d op nodes found.", \
|
||||
fast_where_xpu_op_nodes.size())); \
|
||||
const auto& x_name = fast_where_xpu_op_nodes[0]->Op()->Input("x")[0]; \
|
||||
PADDLE_ENFORCE_EQ(x_name, \
|
||||
#x, \
|
||||
common::errors::PreconditionNotMet( \
|
||||
"The input 'x' of fast_where_xpu op should be '%s', " \
|
||||
"but receive '%s'.", \
|
||||
#x, \
|
||||
x_name)); \
|
||||
const auto& y_name = fast_where_xpu_op_nodes[0]->Op()->Input("y")[0]; \
|
||||
PADDLE_ENFORCE_EQ(y_name, \
|
||||
#y, \
|
||||
common::errors::PreconditionNotMet( \
|
||||
"The input 'y' of fast_where_xpu op should be '%s', " \
|
||||
"but receive '%s'.", \
|
||||
#y, \
|
||||
y_name));
|
||||
|
||||
TEST(FastWhereXPUFusePass, cascade_case0) {
|
||||
Layers layers;
|
||||
auto* condition0 =
|
||||
layers.data("condition0", {20, 1}, false, proto::VarType::BOOL);
|
||||
auto* condition1 =
|
||||
layers.data("condition1", {20, 1}, false, proto::VarType::BOOL);
|
||||
auto* x = layers.data("x", {20, 7});
|
||||
auto* y = layers.data("y", {20, 7});
|
||||
// fast_where_xpu0
|
||||
auto* cast0_out = layers.cast(condition0, 0, 5);
|
||||
cast0_out->SetShape({20, 1});
|
||||
auto* mul0_out = layers.elementwise_mul(cast0_out, x);
|
||||
mul0_out->SetShape({20, 7});
|
||||
auto* scale0_out = layers.scale(cast0_out, -1.0f, 1.0f, true);
|
||||
scale0_out->SetShape({20, 1});
|
||||
auto* mul1_out = layers.elementwise_mul(scale0_out, y);
|
||||
mul1_out->SetShape({20, 7});
|
||||
auto* add0_out = layers.elementwise_add(mul0_out, mul1_out);
|
||||
add0_out->SetShape({20, 7});
|
||||
// fast_where_xpu1
|
||||
auto* cast1_out = layers.cast(condition1, 0, 5);
|
||||
cast1_out->SetShape({20, 1});
|
||||
auto* mul2_out = layers.elementwise_mul(cast1_out, x);
|
||||
mul2_out->SetShape({20, 7});
|
||||
auto* scale1_out = layers.scale(cast1_out, -1.0f, 1.0f, true);
|
||||
scale1_out->SetShape({20, 1});
|
||||
auto* mul3_out = layers.elementwise_mul(scale1_out, add0_out);
|
||||
mul3_out->SetShape({20, 7});
|
||||
auto* add1_out = layers.elementwise_add(mul2_out, mul3_out);
|
||||
add1_out->SetShape({20, 7});
|
||||
|
||||
APPLY_PASS
|
||||
VERIFY_GRAPH(logical_or, x, y)
|
||||
}
|
||||
|
||||
TEST(FastWhereXPUFusePass, cascade_case1) {
|
||||
Layers layers;
|
||||
auto* condition0 =
|
||||
layers.data("condition0", {20, 1}, false, proto::VarType::BOOL);
|
||||
auto* condition1 =
|
||||
layers.data("condition1", {20, 1}, false, proto::VarType::BOOL);
|
||||
auto* x = layers.data("x", {20, 7});
|
||||
auto* y = layers.data("y", {20, 7});
|
||||
// fast_where_xpu0
|
||||
auto* cast0_out = layers.cast(condition0, 0, 5);
|
||||
cast0_out->SetShape({20, 1});
|
||||
auto* mul0_out = layers.elementwise_mul(cast0_out, x);
|
||||
mul0_out->SetShape({20, 7});
|
||||
auto* scale0_out = layers.scale(cast0_out, -1.0f, 1.0f, true);
|
||||
scale0_out->SetShape({20, 1});
|
||||
auto* mul1_out = layers.elementwise_mul(scale0_out, y);
|
||||
mul1_out->SetShape({20, 7});
|
||||
auto* add0_out = layers.elementwise_add(mul0_out, mul1_out);
|
||||
add0_out->SetShape({20, 7});
|
||||
// fast_where_xpu1
|
||||
auto* cast1_out = layers.cast(condition1, 0, 5);
|
||||
cast1_out->SetShape({20, 1});
|
||||
auto* mul2_out = layers.elementwise_mul(cast1_out, add0_out);
|
||||
mul2_out->SetShape({20, 7});
|
||||
auto* scale1_out = layers.scale(cast1_out, -1.0f, 1.0f, true);
|
||||
scale1_out->SetShape({20, 1});
|
||||
auto* mul3_out = layers.elementwise_mul(scale1_out, y);
|
||||
mul3_out->SetShape({20, 7});
|
||||
auto* add1_out = layers.elementwise_add(mul2_out, mul3_out);
|
||||
add1_out->SetShape({20, 7});
|
||||
|
||||
APPLY_PASS
|
||||
VERIFY_GRAPH(logical_and, x, y)
|
||||
}
|
||||
|
||||
#undef APPLY_PASS
|
||||
#undef VERIFY_GRAPH
|
||||
|
||||
} // namespace ir
|
||||
} // namespace framework
|
||||
} // namespace paddle
|
||||
|
||||
USE_PASS(fast_where_xpu_fuse_pass);
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) 2023 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/pass.h"
|
||||
#include "paddle/fluid/framework/ir/pass_tester_helper.h"
|
||||
|
||||
namespace paddle {
|
||||
namespace framework {
|
||||
namespace ir {
|
||||
|
||||
TEST(FoldInterpOutsizeFusePass, basic) {
|
||||
Layers layers;
|
||||
auto* block = layers.Block();
|
||||
|
||||
auto* shape_x = layers.data("shape_x", {1, 18, 288, 288});
|
||||
auto* concat_y =
|
||||
layers.data("concat_y", {576, 576}, true, proto::VarType::INT64);
|
||||
auto* shape_out = layers.shape(shape_x);
|
||||
auto* cast1_out = layers.cast(shape_out, 2, 3);
|
||||
auto* slice_out = layers.slice(cast1_out, {0}, {0}, {2});
|
||||
auto* concat_out = layers.concat({slice_out, concat_y}, 0);
|
||||
auto split_outs = layers.split(concat_out, 0, 0, {2, 2});
|
||||
auto* split_out_1 = split_outs[1];
|
||||
auto* cast2_out = layers.cast(split_out_1, 3, 2);
|
||||
|
||||
OpDesc* bilinear_interp_v2_op = block->AppendOp();
|
||||
bilinear_interp_v2_op->SetType("bilinear_interp_v2");
|
||||
bilinear_interp_v2_op->SetInput("X", {shape_x->Name()});
|
||||
bilinear_interp_v2_op->SetInput("OutSize", {cast2_out->Name()});
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
auto pass = PassRegistry::Instance().Get("fold_interp_outsize_fuse_pass");
|
||||
pass->Apply(graph.get());
|
||||
auto ops_num = GetNumOpNodes(graph);
|
||||
PADDLE_ENFORCE_EQ(
|
||||
ops_num,
|
||||
1,
|
||||
common::errors::PreconditionNotMet(
|
||||
"graph should only have 2 op nodes, but received %d.", ops_num));
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace framework
|
||||
} // namespace paddle
|
||||
|
||||
USE_PASS(fold_interp_outsize_fuse_pass);
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2023 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/pass.h"
|
||||
#include "paddle/fluid/framework/ir/pass_tester_helper.h"
|
||||
|
||||
namespace paddle {
|
||||
namespace framework {
|
||||
namespace ir {
|
||||
|
||||
TEST(FoldTwoSqueeze2FusePass, basic) {
|
||||
Layers layers;
|
||||
|
||||
auto* in_x = layers.data("in_x", {64, 1, 74, 1});
|
||||
auto* squeeze2_1_out = layers.squeeze2(in_x, std::vector<int>{3});
|
||||
layers.squeeze2(squeeze2_1_out, std::vector<int>{1});
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
auto pass = PassRegistry::Instance().Get("fold_two_squeeze2_fuse_pass");
|
||||
pass->Apply(graph.get());
|
||||
auto ops_num = GetNumOpNodes(graph);
|
||||
PADDLE_ENFORCE_EQ(
|
||||
ops_num,
|
||||
1,
|
||||
common::errors::PreconditionNotMet(
|
||||
"graph should only have 2 op nodes, but received %d.", ops_num));
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace framework
|
||||
} // namespace paddle
|
||||
|
||||
USE_PASS(fold_two_squeeze2_fuse_pass);
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
// Copyright (c) 2023 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/pass.h"
|
||||
#include "paddle/fluid/framework/ir/pass_tester_helper.h"
|
||||
|
||||
namespace paddle {
|
||||
namespace framework {
|
||||
namespace ir {
|
||||
|
||||
VarDesc* Data(paddle::framework::BlockDesc* block,
|
||||
std::string name,
|
||||
std::vector<int64_t> shape = {},
|
||||
bool is_persistable = false,
|
||||
proto::VarType::Type data_type = proto::VarType::FP32) {
|
||||
auto* var = block->Var(name);
|
||||
var->SetType(proto::VarType::DENSE_TENSOR);
|
||||
var->SetDataType(data_type);
|
||||
var->SetShape(shape);
|
||||
var->SetPersistable(is_persistable);
|
||||
return var;
|
||||
}
|
||||
|
||||
VarDesc* fill_constant(BlockDesc* block, std::vector<VarDesc*> shapes) {
|
||||
VarDesc* out = Data(block, shapes[0]->Name() + "_out");
|
||||
OpDesc* op = block->AppendOp();
|
||||
op->SetType("fill_constant");
|
||||
std::vector<std::string> shape_names;
|
||||
for (auto shape : shapes) {
|
||||
shape_names.push_back(shape->Name());
|
||||
}
|
||||
op->SetInput("ShapeTensorList", {shape_names});
|
||||
op->SetOutput("Out", {out->Name()});
|
||||
return out;
|
||||
}
|
||||
|
||||
TEST(FillConstantReshapePass, basic) {
|
||||
paddle::framework::ProgramDesc program;
|
||||
auto* block = program.MutableBlock(0);
|
||||
auto* shape0 = Data(block, "shape0");
|
||||
auto* shape1 = Data(block, "shape1");
|
||||
auto* shape2 = Data(block, "shape2");
|
||||
auto* shape3 = Data(block, "shape3");
|
||||
auto* shape4 = Data(block, "shape4");
|
||||
auto* shape5 = Data(block, "shape5");
|
||||
auto* shape6 = Data(block, "shape6");
|
||||
auto* shape7 = Data(block, "shape7");
|
||||
auto* shape8 = Data(block, "shape8");
|
||||
auto* shape9 = Data(block, "shape9");
|
||||
auto* fill0 = fill_constant(block, {shape0, shape1, shape2, shape3, shape4});
|
||||
fill0->SetShape({1, 2, 3, 4, 5});
|
||||
auto* fill1 = fill_constant(block, {shape5, shape6, shape7, shape8, shape9});
|
||||
fill1->SetShape({1, 2, 3, 4, 5});
|
||||
OpDesc* fused_multi_transformer = block->AppendOp();
|
||||
fused_multi_transformer->SetType("fused_multi_transformer");
|
||||
fused_multi_transformer->SetInput("CacheKV", {fill0->Name(), fill1->Name()});
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(program));
|
||||
auto pass = PassRegistry::Instance().Get(
|
||||
"fused_multi_transformer_cachekv_layout_trans_pass");
|
||||
pass->Apply(graph.get());
|
||||
auto fills = GetOpNodes(graph, "fill_constant");
|
||||
auto fill0_in_names = fills[0]->Op()->Input("ShapeTensorList");
|
||||
std::vector<std::string> expect_fill0_out_names{
|
||||
"shape5", "shape6", "shape7", "shape8", "shape9"};
|
||||
std::vector<std::string> expect_fill1_out_names{
|
||||
"shape0", "shape1", "shape2", "shape3", "shape4"};
|
||||
PADDLE_ENFORCE_EQ(fill0_in_names,
|
||||
expect_fill0_out_names,
|
||||
common::errors::PreconditionNotMet(
|
||||
"fill_constant name should not be updated."));
|
||||
auto fill1_in_names = fills[1]->Op()->Input("ShapeTensorList");
|
||||
PADDLE_ENFORCE_EQ(fill1_in_names,
|
||||
expect_fill1_out_names,
|
||||
common::errors::PreconditionNotMet(
|
||||
"fill_constant name should not be updated."));
|
||||
}
|
||||
|
||||
TEST(GatherReshapePass, basic) {
|
||||
Layers layers;
|
||||
auto* gather0_x = layers.data("gather0_x", {2, 1, 24, 512, 64});
|
||||
auto* gather0_index = layers.data("gather0_index", {1});
|
||||
auto* gather0_out = layers.gather(gather0_x, gather0_index, 1);
|
||||
gather0_out->SetShape({2, 1, 24, 512, 64});
|
||||
auto* gather1_x = layers.data("gather1_x", {2, 1, 24, 512, 64});
|
||||
auto* gather1_index = layers.data("gather1_index", {1});
|
||||
auto* gather1_out = layers.gather(gather1_x, gather1_index, 1);
|
||||
gather1_out->SetShape({2, 1, 24, 512, 64});
|
||||
auto* block = layers.Block();
|
||||
OpDesc* fused_multi_transformer = block->AppendOp();
|
||||
fused_multi_transformer->SetType("fused_multi_transformer");
|
||||
fused_multi_transformer->SetInput("CacheKV",
|
||||
{gather0_out->Name(), gather1_out->Name()});
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
auto pass = PassRegistry::Instance().Get(
|
||||
"fused_multi_transformer_cachekv_layout_trans_pass");
|
||||
pass->Apply(graph.get());
|
||||
auto gathers = GetOpNodes(graph, "gather");
|
||||
for (auto* gather : gathers) {
|
||||
PADDLE_ENFORCE_EQ(gather->Op()->GetAttrIfExists<int>("axis"),
|
||||
1,
|
||||
common::errors::PreconditionNotMet(
|
||||
"gather's axis attr should not be updated by pass."));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(FillConstantAndGatherReshapePass, basic) {
|
||||
Layers layers;
|
||||
auto* block = layers.Block();
|
||||
auto* shape0 = Data(block, "shape0");
|
||||
auto* shape1 = Data(block, "shape1");
|
||||
auto* shape2 = Data(block, "shape2");
|
||||
auto* shape3 = Data(block, "shape3");
|
||||
auto* shape4 = Data(block, "shape4");
|
||||
auto* shape5 = Data(block, "shape5");
|
||||
auto* shape6 = Data(block, "shape6");
|
||||
auto* shape7 = Data(block, "shape7");
|
||||
auto* shape8 = Data(block, "shape8");
|
||||
auto* shape9 = Data(block, "shape9");
|
||||
auto* fill0 = fill_constant(block, {shape0, shape1, shape2, shape3, shape4});
|
||||
fill0->SetShape({1, 2, 3, 4, 5});
|
||||
auto* fill1 = fill_constant(block, {shape5, shape6, shape7, shape8, shape9});
|
||||
fill1->SetShape({1, 2, 3, 4, 5});
|
||||
OpDesc* fused_multi_transformer = block->AppendOp();
|
||||
fused_multi_transformer->SetType("fused_multi_transformer");
|
||||
fused_multi_transformer->SetInput("CacheKV", {fill0->Name(), fill1->Name()});
|
||||
|
||||
auto* gather0_x = layers.data("gather0_x", {2, 1, 24, 512, 64});
|
||||
auto* gather0_index = layers.data("gather0_index", {1});
|
||||
auto* gather0_out = layers.gather(gather0_x, gather0_index, 1);
|
||||
gather0_out->SetShape({2, 1, 24, 512, 64});
|
||||
auto* gather1_x = layers.data("gather1_x", {2, 1, 24, 512, 64});
|
||||
auto* gather1_index = layers.data("gather1_index", {1});
|
||||
auto* gather1_out = layers.gather(gather1_x, gather1_index, 1);
|
||||
gather1_out->SetShape({2, 1, 24, 512, 64});
|
||||
OpDesc* fused_multi_transformer1 = block->AppendOp();
|
||||
fused_multi_transformer1->SetType("fused_multi_transformer");
|
||||
fused_multi_transformer1->SetInput(
|
||||
"CacheKV", {gather0_out->Name(), gather1_out->Name()});
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
auto pass = PassRegistry::Instance().Get(
|
||||
"fused_multi_transformer_cachekv_layout_trans_pass");
|
||||
pass->Apply(graph.get());
|
||||
|
||||
auto fills = GetOpNodes(graph, "fill_constant");
|
||||
auto fill0_in_names = fills[0]->Op()->Input("ShapeTensorList");
|
||||
std::vector<std::string> expect_fill0_out_names{
|
||||
"shape0", "shape3", "shape1", "shape2", "shape4"};
|
||||
std::vector<std::string> expect_fill1_out_names{
|
||||
"shape5", "shape8", "shape6", "shape7", "shape9"};
|
||||
PADDLE_ENFORCE_EQ(fill0_in_names,
|
||||
expect_fill0_out_names,
|
||||
common::errors::PreconditionNotMet(
|
||||
"fill_constant name should be updated."));
|
||||
auto fill1_in_names = fills[1]->Op()->Input("ShapeTensorList");
|
||||
PADDLE_ENFORCE_EQ(fill1_in_names,
|
||||
expect_fill1_out_names,
|
||||
common::errors::PreconditionNotMet(
|
||||
"fill_constant name should be updated."));
|
||||
auto gathers = GetOpNodes(graph, "gather");
|
||||
for (auto* gather : gathers) {
|
||||
PADDLE_ENFORCE_EQ(
|
||||
gather->Op()->GetAttrIfExists<int>("axis"),
|
||||
2,
|
||||
common::errors::PreconditionNotMet(
|
||||
"gather's axis attr should be updated to 2 by pass."));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace framework
|
||||
} // namespace paddle
|
||||
|
||||
USE_PASS(fused_multi_transformer_cachekv_layout_trans_pass);
|
||||
+190
@@ -0,0 +1,190 @@
|
||||
// Copyright (c) 2023 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/pass.h"
|
||||
#include "paddle/fluid/framework/ir/pass_tester_helper.h"
|
||||
|
||||
namespace paddle {
|
||||
namespace framework {
|
||||
namespace ir {
|
||||
|
||||
VarDesc* Data(paddle::framework::BlockDesc* block,
|
||||
std::string name,
|
||||
std::vector<int64_t> shape = {},
|
||||
bool is_persistable = false,
|
||||
proto::VarType::Type data_type = proto::VarType::FP32) {
|
||||
auto* var = block->Var(name);
|
||||
var->SetType(proto::VarType::DENSE_TENSOR);
|
||||
var->SetDataType(data_type);
|
||||
var->SetShape(shape);
|
||||
var->SetPersistable(is_persistable);
|
||||
return var;
|
||||
}
|
||||
|
||||
VarDesc* fill_constant(BlockDesc* block, std::vector<VarDesc*> shapes) {
|
||||
VarDesc* out = Data(block, shapes[0]->Name() + "_out");
|
||||
OpDesc* op = block->AppendOp();
|
||||
op->SetType("fill_constant");
|
||||
std::vector<std::string> shape_names;
|
||||
for (auto shape : shapes) {
|
||||
shape_names.push_back(shape->Name());
|
||||
}
|
||||
op->SetInput("ShapeTensorList", {shape_names});
|
||||
op->SetOutput("Out", {out->Name()});
|
||||
return out;
|
||||
}
|
||||
|
||||
TEST(FillConstantReshapePass, basic) {
|
||||
paddle::framework::ProgramDesc program;
|
||||
auto* block = program.MutableBlock(0);
|
||||
auto* shape0 = Data(block, "shape0");
|
||||
auto* shape1 = Data(block, "shape1");
|
||||
auto* shape2 = Data(block, "shape2");
|
||||
auto* shape3 = Data(block, "shape3");
|
||||
auto* shape4 = Data(block, "shape4");
|
||||
auto* shape5 = Data(block, "shape5");
|
||||
auto* shape6 = Data(block, "shape6");
|
||||
auto* shape7 = Data(block, "shape7");
|
||||
auto* shape8 = Data(block, "shape8");
|
||||
auto* shape9 = Data(block, "shape9");
|
||||
auto* fill0 = fill_constant(block, {shape0, shape1, shape2, shape3, shape4});
|
||||
fill0->SetShape({1, 2, 3, 4, 5});
|
||||
auto* fill1 = fill_constant(block, {shape5, shape6, shape7, shape8, shape9});
|
||||
fill1->SetShape({1, 2, 3, 4, 5});
|
||||
OpDesc* fused_multi_transformer_int8 = block->AppendOp();
|
||||
fused_multi_transformer_int8->SetType("fused_multi_transformer_int8");
|
||||
fused_multi_transformer_int8->SetInput("CacheKV",
|
||||
{fill0->Name(), fill1->Name()});
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(program));
|
||||
auto pass = PassRegistry::Instance().Get(
|
||||
"fused_multi_transformer_int8_cachekv_layout_trans_pass");
|
||||
pass->Apply(graph.get());
|
||||
auto fills = GetOpNodes(graph, "fill_constant");
|
||||
auto fill0_in_names = fills[0]->Op()->Input("ShapeTensorList");
|
||||
std::vector<std::string> expect_fill0_out_names{
|
||||
"shape5", "shape6", "shape7", "shape8", "shape9"};
|
||||
std::vector<std::string> expect_fill1_out_names{
|
||||
"shape0", "shape1", "shape2", "shape3", "shape4"};
|
||||
PADDLE_ENFORCE_EQ(fill0_in_names,
|
||||
expect_fill0_out_names,
|
||||
common::errors::PreconditionNotMet(
|
||||
"fill_constant name should not be updated."));
|
||||
auto fill1_in_names = fills[1]->Op()->Input("ShapeTensorList");
|
||||
PADDLE_ENFORCE_EQ(fill1_in_names,
|
||||
expect_fill1_out_names,
|
||||
common::errors::PreconditionNotMet(
|
||||
"fill_constant name should not be updated."));
|
||||
}
|
||||
|
||||
TEST(GatherReshapePass, basic) {
|
||||
Layers layers;
|
||||
auto* gather0_x = layers.data("gather0_x", {2, 1, 24, 512, 64});
|
||||
auto* gather0_index = layers.data("gather0_index", {1});
|
||||
auto* gather0_out = layers.gather(gather0_x, gather0_index, 1);
|
||||
gather0_out->SetShape({2, 1, 24, 512, 64});
|
||||
auto* gather1_x = layers.data("gather1_x", {2, 1, 24, 512, 64});
|
||||
auto* gather1_index = layers.data("gather1_index", {1});
|
||||
auto* gather1_out = layers.gather(gather1_x, gather1_index, 1);
|
||||
gather1_out->SetShape({2, 1, 24, 512, 64});
|
||||
auto* block = layers.Block();
|
||||
OpDesc* fused_multi_transformer_int8 = block->AppendOp();
|
||||
fused_multi_transformer_int8->SetType("fused_multi_transformer_int8");
|
||||
fused_multi_transformer_int8->SetInput(
|
||||
"CacheKV", {gather0_out->Name(), gather1_out->Name()});
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
auto pass = PassRegistry::Instance().Get(
|
||||
"fused_multi_transformer_int8_cachekv_layout_trans_pass");
|
||||
pass->Apply(graph.get());
|
||||
auto gathers = GetOpNodes(graph, "gather");
|
||||
for (auto* gather : gathers) {
|
||||
PADDLE_ENFORCE_EQ(gather->Op()->GetAttrIfExists<int>("axis"),
|
||||
1,
|
||||
common::errors::PreconditionNotMet(
|
||||
"gather's axis attr should not be updated by pass."));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(FillConstantAndGatherReshapePass, basic) {
|
||||
Layers layers;
|
||||
auto* block = layers.Block();
|
||||
auto* shape0 = Data(block, "shape0");
|
||||
auto* shape1 = Data(block, "shape1");
|
||||
auto* shape2 = Data(block, "shape2");
|
||||
auto* shape3 = Data(block, "shape3");
|
||||
auto* shape4 = Data(block, "shape4");
|
||||
auto* shape5 = Data(block, "shape5");
|
||||
auto* shape6 = Data(block, "shape6");
|
||||
auto* shape7 = Data(block, "shape7");
|
||||
auto* shape8 = Data(block, "shape8");
|
||||
auto* shape9 = Data(block, "shape9");
|
||||
auto* fill0 = fill_constant(block, {shape0, shape1, shape2, shape3, shape4});
|
||||
fill0->SetShape({1, 2, 3, 4, 5});
|
||||
auto* fill1 = fill_constant(block, {shape5, shape6, shape7, shape8, shape9});
|
||||
fill1->SetShape({1, 2, 3, 4, 5});
|
||||
OpDesc* fused_multi_transformer_int8 = block->AppendOp();
|
||||
fused_multi_transformer_int8->SetType("fused_multi_transformer_int8");
|
||||
fused_multi_transformer_int8->SetInput("CacheKV",
|
||||
{fill0->Name(), fill1->Name()});
|
||||
|
||||
auto* gather0_x = layers.data("gather0_x", {2, 1, 24, 512, 64});
|
||||
auto* gather0_index = layers.data("gather0_index", {1});
|
||||
auto* gather0_out = layers.gather(gather0_x, gather0_index, 1);
|
||||
gather0_out->SetShape({2, 1, 24, 512, 64});
|
||||
auto* gather1_x = layers.data("gather1_x", {2, 1, 24, 512, 64});
|
||||
auto* gather1_index = layers.data("gather1_index", {1});
|
||||
auto* gather1_out = layers.gather(gather1_x, gather1_index, 1);
|
||||
gather1_out->SetShape({2, 1, 24, 512, 64});
|
||||
OpDesc* fused_multi_transformer_int8_1 = block->AppendOp();
|
||||
fused_multi_transformer_int8_1->SetType("fused_multi_transformer_int8");
|
||||
fused_multi_transformer_int8_1->SetInput(
|
||||
"CacheKV", {gather0_out->Name(), gather1_out->Name()});
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
auto pass = PassRegistry::Instance().Get(
|
||||
"fused_multi_transformer_int8_cachekv_layout_trans_pass");
|
||||
pass->Apply(graph.get());
|
||||
|
||||
auto fills = GetOpNodes(graph, "fill_constant");
|
||||
auto fill0_in_names = fills[0]->Op()->Input("ShapeTensorList");
|
||||
std::vector<std::string> expect_fill0_out_names{
|
||||
"shape0", "shape3", "shape1", "shape2", "shape4"};
|
||||
std::vector<std::string> expect_fill1_out_names{
|
||||
"shape5", "shape8", "shape6", "shape7", "shape9"};
|
||||
PADDLE_ENFORCE_EQ(fill0_in_names,
|
||||
expect_fill0_out_names,
|
||||
common::errors::PreconditionNotMet(
|
||||
"fill_constant name should be updated."));
|
||||
auto fill1_in_names = fills[1]->Op()->Input("ShapeTensorList");
|
||||
PADDLE_ENFORCE_EQ(fill1_in_names,
|
||||
expect_fill1_out_names,
|
||||
common::errors::PreconditionNotMet(
|
||||
"fill_constant name should be updated."));
|
||||
auto gathers = GetOpNodes(graph, "gather");
|
||||
for (auto* gather : gathers) {
|
||||
PADDLE_ENFORCE_EQ(
|
||||
gather->Op()->GetAttrIfExists<int>("axis"),
|
||||
2,
|
||||
common::errors::PreconditionNotMet(
|
||||
"gather's axis attr should be updated to 2 by pass."));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace framework
|
||||
} // namespace paddle
|
||||
|
||||
USE_PASS(fused_multi_transformer_int8_cachekv_layout_trans_pass);
|
||||
+265
@@ -0,0 +1,265 @@
|
||||
/* Copyright (c) 2022 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 "glog/logging.h"
|
||||
|
||||
#include "paddle/fluid/framework/ir/pass.h"
|
||||
#include "paddle/fluid/framework/ir/pass_tester_helper.h"
|
||||
|
||||
#define DEF_INPUT_DATA \
|
||||
Layers layers; \
|
||||
auto* x = layers.data("x", {1, 128, 1024}); \
|
||||
auto* src_mask = layers.data("src_mask", {1, 16, 128, 128}); \
|
||||
auto* ln_scale = layers.data("ln_scale", {1024}, true); \
|
||||
auto* ln_bias = layers.data("ln_bias", {1024}, true); \
|
||||
auto* qkv_w = layers.data("qkv_w", {3, 16, 64, 1024}, true); \
|
||||
auto* qkv_bias = layers.data("qkv_bias", {3, 16, 64}, true); \
|
||||
auto* out_linear_w = layers.data("out_linear_w", {1024, 1024}, true); \
|
||||
auto* out_linear_bias = layers.data("out_linear_bias", {1024}, true); \
|
||||
auto* ffn_ln_scale = layers.data("ffn_ln_scale", {1024}, true); \
|
||||
auto* ffn_ln_bias = layers.data("ffn_ln_bias", {1024}, true); \
|
||||
auto* ffn1_w = layers.data("ffn1_w", {1024, 4096}, true); \
|
||||
auto* ffn1_bias = layers.data("ffn1_bias", {4096}, true); \
|
||||
auto* ffn2_w = layers.data("ffn2_w", {4096, 1024}, true); \
|
||||
auto* ffn2_bias = layers.data("ffn2_bias", {1024}, true); \
|
||||
auto* qkv_out_scale = layers.data("qkv_out_scale", {3, 16, 64}, true); \
|
||||
auto* out_linear_out_scale = \
|
||||
layers.data("out_linear_out_scale", {1024}, true); \
|
||||
auto* ffn1_out_scale = layers.data("ffn1_out_scale", {4096}, true); \
|
||||
auto* ffn2_out_scale = layers.data("ffn2_out_scale", {1024}, true); \
|
||||
std::vector<float> qkv_in_scale(48, 1.0); \
|
||||
std::vector<float> out_linear_in_scale(48, 1.0); \
|
||||
std::vector<float> ffn1_in_scale(48, 1.0); \
|
||||
std::vector<float> ffn2_in_scale(48, 1.0);
|
||||
|
||||
namespace paddle {
|
||||
namespace framework {
|
||||
namespace ir {
|
||||
|
||||
void AddVarToScope(Scope* param_scope,
|
||||
const std::string& name,
|
||||
const DDim& dims) {
|
||||
auto* tensor = param_scope->Var(name)->GetMutable<phi::DenseTensor>();
|
||||
tensor->Resize(dims);
|
||||
tensor->mutable_data<float>(phi::CPUPlace());
|
||||
}
|
||||
|
||||
Scope* CreateParamScope() {
|
||||
auto param_scope = new Scope();
|
||||
AddVarToScope(param_scope, "ln_scale", {1024});
|
||||
AddVarToScope(param_scope, "ln_bias", {1024});
|
||||
AddVarToScope(param_scope, "ffn_ln_scale", {1024});
|
||||
AddVarToScope(param_scope, "ffn_ln_bias", {1024});
|
||||
|
||||
AddVarToScope(param_scope, "qkv_w", {3, 16, 64, 1024});
|
||||
AddVarToScope(param_scope, "out_linear_w", {1024, 1024});
|
||||
AddVarToScope(param_scope, "ffn1_w", {1024, 4096});
|
||||
AddVarToScope(param_scope, "ffn2_w", {4096, 1024});
|
||||
AddVarToScope(param_scope, "qkv_bias", {3072});
|
||||
AddVarToScope(param_scope, "out_linear_bias", {1024});
|
||||
AddVarToScope(param_scope, "ffn1_bias", {4096});
|
||||
AddVarToScope(param_scope, "ffn2_bias", {1024});
|
||||
|
||||
AddVarToScope(param_scope, "qkv_out_scale", {3072});
|
||||
AddVarToScope(param_scope, "out_linear_out_scale", {1024});
|
||||
AddVarToScope(param_scope, "ffn1_out_scale", {4096});
|
||||
AddVarToScope(param_scope, "ffn2_out_scale", {1024});
|
||||
|
||||
return param_scope;
|
||||
}
|
||||
|
||||
VarDesc* Data(paddle::framework::BlockDesc* block,
|
||||
std::string name,
|
||||
std::vector<int64_t> shape = {},
|
||||
bool is_persistable = false,
|
||||
proto::VarType::Type data_type = proto::VarType::FP32) {
|
||||
auto* var = block->Var(name);
|
||||
var->SetType(proto::VarType::DENSE_TENSOR);
|
||||
var->SetDataType(data_type);
|
||||
var->SetShape(shape);
|
||||
var->SetPersistable(is_persistable);
|
||||
return var;
|
||||
}
|
||||
|
||||
TEST(RemoveAssignGather, basic) {
|
||||
paddle::framework::ProgramDesc program;
|
||||
auto* block = program.MutableBlock(0);
|
||||
|
||||
auto* x = Data(block, "fused_multi_transformer_x", {1, 1, 1536});
|
||||
auto* cache_kv =
|
||||
Data(block, "fused_multi_transformer_cache_kv", {2, 1, 24, 512, 64});
|
||||
OpDesc* fused_multi_transformer_op = block->AppendOp();
|
||||
fused_multi_transformer_op->SetType("fused_multi_transformer_int8");
|
||||
fused_multi_transformer_op->SetInput("X", {x->Name()});
|
||||
fused_multi_transformer_op->SetInput("CacheKV", {cache_kv->Name()});
|
||||
fused_multi_transformer_op->SetOutput("CacheKVOut", {cache_kv->Name()});
|
||||
|
||||
auto* assign_out = Data(block, "assign_out", cache_kv->GetShape());
|
||||
OpDesc* assign_op = block->AppendOp();
|
||||
assign_op->SetType("assign");
|
||||
assign_op->SetInput("X", {cache_kv->Name()});
|
||||
assign_op->SetOutput("Out", {assign_out->Name()});
|
||||
|
||||
OpDesc* gather_op = block->AppendOp();
|
||||
auto gather_index = Data(block, "gather_index", {10});
|
||||
gather_op->SetType("gather");
|
||||
gather_op->SetInput("X", {assign_out->Name()});
|
||||
gather_op->SetInput("Index", {gather_index->Name()});
|
||||
gather_op->SetAttr("axis", {1});
|
||||
gather_op->SetOutput("Out", {cache_kv->Name()});
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(program));
|
||||
auto pass = PassRegistry::Instance().Get(
|
||||
"fused_multi_transformer_int8_xpu_quant_pass");
|
||||
pass->Apply(graph.get());
|
||||
auto assign_num = GetNumOpNodes(graph, "assign");
|
||||
auto gather_num = GetNumOpNodes(graph, "gather");
|
||||
PADDLE_ENFORCE_EQ(assign_num,
|
||||
0,
|
||||
common::errors::PreconditionNotMet(
|
||||
"assign op should be removed from the graph."));
|
||||
PADDLE_ENFORCE_EQ(gather_num,
|
||||
0,
|
||||
common::errors::PreconditionNotMet(
|
||||
"gather op should be removed from the graph."));
|
||||
}
|
||||
|
||||
TEST(FusedMultiTransformerInt8XPUQuantPass, context_stage) {
|
||||
DEF_INPUT_DATA
|
||||
LOG(INFO) << "layers.fill_constant_batch_size_like start";
|
||||
auto* cache_kv = layers.fill_constant_batch_size_like(
|
||||
x,
|
||||
static_cast<int>(proto::VarType::FP16),
|
||||
0,
|
||||
1,
|
||||
{2, -1, 16, 1024, 64},
|
||||
0);
|
||||
LOG(INFO) << "layers.fill_constant_batch_size_like done";
|
||||
layers.fused_multi_transformer(x,
|
||||
cache_kv,
|
||||
src_mask,
|
||||
qkv_w,
|
||||
qkv_bias,
|
||||
out_linear_w,
|
||||
out_linear_bias,
|
||||
ffn1_w,
|
||||
ffn1_bias,
|
||||
ffn2_w,
|
||||
ffn2_bias,
|
||||
ln_scale,
|
||||
ln_bias,
|
||||
ffn_ln_scale,
|
||||
ffn_ln_bias,
|
||||
0.1,
|
||||
1e-12,
|
||||
nullptr,
|
||||
qkv_out_scale = qkv_out_scale,
|
||||
out_linear_out_scale = out_linear_out_scale,
|
||||
ffn1_out_scale = ffn1_out_scale,
|
||||
ffn2_out_scale = ffn2_out_scale,
|
||||
qkv_in_scale = qkv_in_scale,
|
||||
out_linear_in_scale = out_linear_in_scale,
|
||||
ffn1_in_scale = ffn1_in_scale,
|
||||
ffn2_in_scale = ffn2_in_scale);
|
||||
LOG(INFO) << "layers.fused_multi_transformer done";
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
graph->Set("__param_scope__", CreateParamScope());
|
||||
|
||||
auto pass = PassRegistry::Instance().Get(
|
||||
"fused_multi_transformer_int8_xpu_quant_pass");
|
||||
if (pass.get() == nullptr) {
|
||||
LOG(INFO) << "get fused_multi_transformer_int8_xpu_quant_pass failed";
|
||||
}
|
||||
LOG(INFO) << "get fused_multi_transformer_int8_xpu_quant_pass Done";
|
||||
VLOG(3) << DebugString(graph);
|
||||
graph.reset(pass->Apply(graph.release()));
|
||||
int num_nodes_after =
|
||||
GetNumOpNodes(graph, "fused_multi_transformer_int8_xpu");
|
||||
VLOG(3) << DebugString(graph);
|
||||
|
||||
PADDLE_ENFORCE_EQ(
|
||||
num_nodes_after,
|
||||
1,
|
||||
common::errors::InvalidArgument(
|
||||
"After the fused_multi_transformer_int8_xpu_quant_pass, "
|
||||
"The node num in graph should be 1, but the result is %d",
|
||||
num_nodes_after));
|
||||
}
|
||||
|
||||
TEST(FusedMultiTransformerInt8XPUQuantPass, decoder_stage) {
|
||||
DEF_INPUT_DATA
|
||||
|
||||
auto* cache_kv = layers.fill_constant_batch_size_like(
|
||||
x,
|
||||
static_cast<int>(proto::VarType::FP16),
|
||||
0,
|
||||
1,
|
||||
{2, -1, 16, 1024, 64},
|
||||
0);
|
||||
|
||||
auto* time_step = layers.data("time_step", {1});
|
||||
layers.fused_multi_transformer(x,
|
||||
cache_kv,
|
||||
src_mask,
|
||||
qkv_w,
|
||||
qkv_bias,
|
||||
out_linear_w,
|
||||
out_linear_bias,
|
||||
ffn1_w,
|
||||
ffn1_bias,
|
||||
ffn2_w,
|
||||
ffn2_bias,
|
||||
ln_scale,
|
||||
ln_bias,
|
||||
ffn_ln_scale,
|
||||
ffn_ln_bias,
|
||||
0.1,
|
||||
1e-12,
|
||||
time_step,
|
||||
qkv_out_scale = qkv_out_scale,
|
||||
out_linear_out_scale = out_linear_out_scale,
|
||||
ffn1_out_scale = ffn1_out_scale,
|
||||
ffn2_out_scale = ffn2_out_scale,
|
||||
qkv_in_scale = qkv_in_scale,
|
||||
out_linear_in_scale = out_linear_in_scale,
|
||||
ffn1_in_scale = ffn1_in_scale,
|
||||
ffn2_in_scale = ffn2_in_scale);
|
||||
LOG(INFO) << "layers.fused_multi_transformer done";
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
graph->Set("__param_scope__", CreateParamScope());
|
||||
|
||||
auto pass = PassRegistry::Instance().Get(
|
||||
"fused_multi_transformer_int8_xpu_quant_pass");
|
||||
if (pass.get() == nullptr) {
|
||||
LOG(INFO) << "get fused_multi_transformer_int8_xpu_quant_pass failed";
|
||||
}
|
||||
|
||||
graph.reset(pass->Apply(graph.release()));
|
||||
int num_nodes_after =
|
||||
GetNumOpNodes(graph, "fused_multi_transformer_int8_xpu");
|
||||
VLOG(3) << DebugString(graph);
|
||||
|
||||
PADDLE_ENFORCE_EQ(
|
||||
num_nodes_after,
|
||||
1,
|
||||
common::errors::InvalidArgument(
|
||||
"After the fused_multi_transformer_int8_xpu_quant_pass, "
|
||||
"The node num in graph should be 1, but the result is %d",
|
||||
num_nodes_after));
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace framework
|
||||
} // namespace paddle
|
||||
|
||||
USE_PASS(fused_multi_transformer_int8_xpu_quant_pass);
|
||||
@@ -0,0 +1,225 @@
|
||||
/* Copyright (c) 2022 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 "glog/logging.h"
|
||||
|
||||
#include "paddle/fluid/framework/ir/pass.h"
|
||||
#include "paddle/fluid/framework/ir/pass_tester_helper.h"
|
||||
|
||||
#define DEF_INPUT_DATA \
|
||||
Layers layers; \
|
||||
auto* x = layers.data("x", {1, 128, 1024}); \
|
||||
auto* src_mask = layers.data("src_mask", {1, 16, 128, 128}); \
|
||||
auto* ln_scale = layers.data("ln_scale", {1024}, true); \
|
||||
auto* ln_bias = layers.data("ln_bias", {1024}, true); \
|
||||
auto* qkv_w = layers.data("qkv_w", {3, 16, 64, 1024}, true); \
|
||||
auto* qkv_bias = layers.data("qkv_bias", {3, 16, 64}, true); \
|
||||
auto* out_linear_w = layers.data("out_linear_w", {1024, 1024}, true); \
|
||||
auto* out_linear_bias = layers.data("out_linear_bias", {1024}, true); \
|
||||
auto* ffn_ln_scale = layers.data("ffn_ln_scale", {1024}, true); \
|
||||
auto* ffn_ln_bias = layers.data("ffn_ln_bias", {1024}, true); \
|
||||
auto* ffn1_w = layers.data("ffn1_w", {1024, 4096}, true); \
|
||||
auto* ffn1_bias = layers.data("ffn1_bias", {4096}, true); \
|
||||
auto* ffn2_w = layers.data("ffn2_w", {4096, 1024}, true); \
|
||||
auto* ffn2_bias = layers.data("ffn2_bias", {1024}, true);
|
||||
|
||||
namespace paddle {
|
||||
namespace framework {
|
||||
namespace ir {
|
||||
|
||||
void AddVarToScope(Scope* param_scope,
|
||||
const std::string& name,
|
||||
const DDim& dims) {
|
||||
auto* tensor = param_scope->Var(name)->GetMutable<phi::DenseTensor>();
|
||||
tensor->Resize(dims);
|
||||
tensor->mutable_data<float>(phi::CPUPlace());
|
||||
}
|
||||
|
||||
Scope* CreateParamScope() {
|
||||
auto param_scope = new Scope();
|
||||
AddVarToScope(param_scope, "ln_scale", {1024});
|
||||
AddVarToScope(param_scope, "ln_bias", {1024});
|
||||
AddVarToScope(param_scope, "ffn_ln_scale", {1024});
|
||||
AddVarToScope(param_scope, "ffn_ln_bias", {1024});
|
||||
|
||||
AddVarToScope(param_scope, "qkv_w", {3, 16, 64, 1024});
|
||||
AddVarToScope(param_scope, "out_linear_w", {1024, 1024});
|
||||
AddVarToScope(param_scope, "ffn1_w", {1024, 4096});
|
||||
AddVarToScope(param_scope, "ffn2_w", {4096, 1024});
|
||||
AddVarToScope(param_scope, "qkv_bias", {3072});
|
||||
AddVarToScope(param_scope, "out_linear_bias", {1024});
|
||||
AddVarToScope(param_scope, "ffn1_bias", {4096});
|
||||
AddVarToScope(param_scope, "ffn2_bias", {1024});
|
||||
|
||||
return param_scope;
|
||||
}
|
||||
|
||||
VarDesc* Data(paddle::framework::BlockDesc* block,
|
||||
std::string name,
|
||||
std::vector<int64_t> shape = {},
|
||||
bool is_persistable = false,
|
||||
proto::VarType::Type data_type = proto::VarType::FP32) {
|
||||
auto* var = block->Var(name);
|
||||
var->SetType(proto::VarType::DENSE_TENSOR);
|
||||
var->SetDataType(data_type);
|
||||
var->SetShape(shape);
|
||||
var->SetPersistable(is_persistable);
|
||||
return var;
|
||||
}
|
||||
|
||||
TEST(RemoveAssignGather, basic) {
|
||||
paddle::framework::ProgramDesc program;
|
||||
auto* block = program.MutableBlock(0);
|
||||
|
||||
auto* x = Data(block, "fused_multi_transformer_x", {1, 1, 1536});
|
||||
auto* cache_kv =
|
||||
Data(block, "fused_multi_transformer_cache_kv", {2, 1, 24, 512, 64});
|
||||
OpDesc* fused_multi_transformer_op = block->AppendOp();
|
||||
fused_multi_transformer_op->SetType("fused_multi_transformer");
|
||||
fused_multi_transformer_op->SetInput("X", {x->Name()});
|
||||
fused_multi_transformer_op->SetInput("CacheKV", {cache_kv->Name()});
|
||||
fused_multi_transformer_op->SetOutput("CacheKVOut", {cache_kv->Name()});
|
||||
|
||||
auto* assign_out = Data(block, "assign_out", cache_kv->GetShape());
|
||||
OpDesc* assign_op = block->AppendOp();
|
||||
assign_op->SetType("assign");
|
||||
assign_op->SetInput("X", {cache_kv->Name()});
|
||||
assign_op->SetOutput("Out", {assign_out->Name()});
|
||||
|
||||
OpDesc* gather_op = block->AppendOp();
|
||||
auto gather_index = Data(block, "gather_index", {10});
|
||||
gather_op->SetType("gather");
|
||||
gather_op->SetInput("X", {assign_out->Name()});
|
||||
gather_op->SetInput("Index", {gather_index->Name()});
|
||||
gather_op->SetAttr("axis", {1});
|
||||
gather_op->SetOutput("Out", {cache_kv->Name()});
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(program));
|
||||
auto pass = PassRegistry::Instance().Get("fused_multi_transformer_xpu_pass");
|
||||
pass->Apply(graph.get());
|
||||
auto assign_num = GetNumOpNodes(graph, "assign");
|
||||
auto gather_num = GetNumOpNodes(graph, "gather");
|
||||
PADDLE_ENFORCE_EQ(assign_num,
|
||||
0,
|
||||
common::errors::PreconditionNotMet(
|
||||
"assign op should be removed from the graph."));
|
||||
PADDLE_ENFORCE_EQ(gather_num,
|
||||
0,
|
||||
common::errors::PreconditionNotMet(
|
||||
"gather op should be removed from the graph."));
|
||||
}
|
||||
|
||||
TEST(FusedMultiTransformerXPUPass, context_stage) {
|
||||
DEF_INPUT_DATA
|
||||
|
||||
auto* cache_kv = layers.fill_constant_batch_size_like(
|
||||
x,
|
||||
static_cast<int>(proto::VarType::FP32),
|
||||
0,
|
||||
1,
|
||||
{2, -1, 16, 1024, 64},
|
||||
0);
|
||||
|
||||
layers.fused_multi_transformer(x,
|
||||
cache_kv,
|
||||
src_mask,
|
||||
qkv_w,
|
||||
qkv_bias,
|
||||
out_linear_w,
|
||||
out_linear_bias,
|
||||
ffn1_w,
|
||||
ffn1_bias,
|
||||
ffn2_w,
|
||||
ffn2_bias,
|
||||
ln_scale,
|
||||
ln_bias,
|
||||
ffn_ln_scale,
|
||||
ffn_ln_bias,
|
||||
0.1,
|
||||
1e-12);
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
graph->Set("__param_scope__", CreateParamScope());
|
||||
|
||||
auto pass = PassRegistry::Instance().Get("fused_multi_transformer_xpu_pass");
|
||||
if (pass.get() == nullptr) {
|
||||
LOG(INFO) << "get fused_multi_transformer_xpu_pass failed";
|
||||
}
|
||||
|
||||
graph.reset(pass->Apply(graph.release()));
|
||||
int num_nodes_after = GetNumOpNodes(graph, "fused_multi_transformer_xpu");
|
||||
VLOG(3) << DebugString(graph);
|
||||
|
||||
PADDLE_ENFORCE_EQ(
|
||||
num_nodes_after,
|
||||
1,
|
||||
common::errors::InvalidArgument(
|
||||
"After the fuse_multi_transformer_layer_pass, "
|
||||
"The node num in graph should be 1, but the result is %d",
|
||||
num_nodes_after));
|
||||
}
|
||||
|
||||
TEST(FusedMultiTransformerXPUPass, decoder_stage) {
|
||||
DEF_INPUT_DATA
|
||||
|
||||
auto* cache_kv = layers.fill_constant_batch_size_like(
|
||||
x,
|
||||
static_cast<int>(proto::VarType::FP32),
|
||||
0,
|
||||
1,
|
||||
{2, -1, 16, 1024, 64},
|
||||
0);
|
||||
auto* time_step = layers.data("time_step", {1});
|
||||
layers.fused_multi_transformer(x,
|
||||
cache_kv,
|
||||
src_mask,
|
||||
qkv_w,
|
||||
qkv_bias,
|
||||
out_linear_w,
|
||||
out_linear_bias,
|
||||
ffn1_w,
|
||||
ffn1_bias,
|
||||
ffn2_w,
|
||||
ffn2_bias,
|
||||
ln_scale,
|
||||
ln_bias,
|
||||
ffn_ln_scale,
|
||||
ffn_ln_bias,
|
||||
0.1,
|
||||
1e-12,
|
||||
time_step);
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
graph->Set("__param_scope__", CreateParamScope());
|
||||
|
||||
auto pass = PassRegistry::Instance().Get("fused_multi_transformer_xpu_pass");
|
||||
if (pass.get() == nullptr) {
|
||||
LOG(INFO) << "get fused_multi_transformer_xpu_pass failed";
|
||||
}
|
||||
|
||||
graph.reset(pass->Apply(graph.release()));
|
||||
int num_nodes_after = GetNumOpNodes(graph, "fused_multi_transformer_xpu");
|
||||
VLOG(3) << DebugString(graph);
|
||||
|
||||
PADDLE_ENFORCE_EQ(
|
||||
num_nodes_after,
|
||||
1,
|
||||
common::errors::InvalidArgument(
|
||||
"After the fuse_multi_transformer_layer_pass, "
|
||||
"The node num in graph should be 1, but the result is %d",
|
||||
num_nodes_after));
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace framework
|
||||
} // namespace paddle
|
||||
|
||||
USE_PASS(fused_multi_transformer_xpu_pass);
|
||||
@@ -0,0 +1,56 @@
|
||||
// Copyright (c) 2023 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/pass.h"
|
||||
#include "paddle/fluid/framework/ir/pass_tester_helper.h"
|
||||
#include "paddle/fluid/platform/enforce.h"
|
||||
|
||||
namespace paddle {
|
||||
namespace framework {
|
||||
namespace ir {
|
||||
|
||||
TEST(MatMulWeightTransPass, basic) {
|
||||
Layers layers;
|
||||
|
||||
auto* reshape2_in = layers.data("reshape2_in", {64, 256, 1, 1});
|
||||
auto* reshape2_out = layers.reshape2(reshape2_in, std::vector<int>{-1, 256});
|
||||
auto* matmul_y = layers.data("matmul_y", {8, 256}, true);
|
||||
layers.matmul_v2(reshape2_out, matmul_y, nullptr, false, true);
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
auto pass = PassRegistry::Instance().Get("matmul_weight_trans_pass");
|
||||
VLOG(3) << DebugString(graph);
|
||||
pass->Apply(graph.get());
|
||||
VLOG(3) << DebugString(graph);
|
||||
|
||||
bool trans_y = true;
|
||||
for (auto* node : graph->Nodes()) {
|
||||
if (node->IsOp() && node->Op()->Type() == "matmul_v2") {
|
||||
trans_y = PADDLE_GET_CONST(bool, node->Op()->GetAttr("trans_y"));
|
||||
}
|
||||
}
|
||||
PADDLE_ENFORCE_EQ(
|
||||
trans_y,
|
||||
false,
|
||||
common::errors::PreconditionNotMet(
|
||||
"The attribute of matmul_v2 trans_y should be false after pass"));
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace framework
|
||||
} // namespace paddle
|
||||
|
||||
USE_PASS(matmul_weight_trans_pass);
|
||||
@@ -0,0 +1,105 @@
|
||||
// Copyright (c) 2023 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/pass.h"
|
||||
#include "paddle/fluid/framework/ir/pass_tester_helper.h"
|
||||
|
||||
namespace paddle {
|
||||
namespace framework {
|
||||
namespace ir {
|
||||
|
||||
TEST(MultiEncoderXPUAdaptiveSeqlenFusePass, V1) {
|
||||
Layers layers;
|
||||
auto* block = layers.Block();
|
||||
|
||||
auto* embedding_xpu_out = layers.data("embedding_xpu_out");
|
||||
OpDesc* embedding_xpu = block->AppendOp();
|
||||
embedding_xpu->SetType("embedding_with_eltwise_add_xpu");
|
||||
embedding_xpu->SetOutput("out", {embedding_xpu_out->Name()});
|
||||
auto* layer_norm_out = layers.layer_norm(embedding_xpu_out)[0];
|
||||
|
||||
auto* mask = layers.data("mask");
|
||||
auto* matmul_out = layers.matmul(mask, mask);
|
||||
auto* scale_out = layers.scale(matmul_out);
|
||||
auto* stack_out = layers.stack({scale_out, scale_out});
|
||||
|
||||
OpDesc* multi_encoder_xpu = block->AppendOp();
|
||||
multi_encoder_xpu->SetType("multi_encoder_xpu");
|
||||
multi_encoder_xpu->SetInput("x", {layer_norm_out->Name()});
|
||||
multi_encoder_xpu->SetInput("mask", {stack_out->Name()});
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
auto pass = PassRegistry::Instance().Get(
|
||||
"multi_encoder_xpu_adaptive_seqlen_fuse_pass");
|
||||
pass->Apply(graph.get());
|
||||
auto num = GetNumOpNodes(graph, "matmul") + GetNumOpNodes(graph, "scale") +
|
||||
GetNumOpNodes(graph, "stack");
|
||||
PADDLE_ENFORCE_EQ(
|
||||
num,
|
||||
0,
|
||||
common::errors::PreconditionNotMet(
|
||||
"matmul/scale/stack ops should be removed from graph, but graph "
|
||||
"still has %d ops.",
|
||||
num));
|
||||
}
|
||||
|
||||
TEST(MultiEncoderXPUAdaptiveSeqlenFusePass, V2) {
|
||||
Layers layers;
|
||||
auto* block = layers.Block();
|
||||
|
||||
auto* embedding_xpu_out = layers.data("embedding_xpu_out");
|
||||
OpDesc* embedding_xpu = block->AppendOp();
|
||||
embedding_xpu->SetType("embedding_with_eltwise_add_xpu");
|
||||
embedding_xpu->SetOutput("out", {embedding_xpu_out->Name()});
|
||||
auto* layer_norm_out = layers.layer_norm(embedding_xpu_out)[0];
|
||||
|
||||
auto* mask = layers.data("mask");
|
||||
auto* not_equal_y = layers.data("not_equal_y");
|
||||
auto* not_equal_out = layers.not_equal(mask, not_equal_y);
|
||||
auto* cast_out = layers.cast(not_equal_out);
|
||||
auto* unsqueeze_0_out = layers.unsqueeze2(cast_out);
|
||||
auto* matmul_out = layers.matmul_v2(unsqueeze_0_out, unsqueeze_0_out);
|
||||
auto* scale_0_out = layers.scale(matmul_out);
|
||||
auto* scale_1_out = layers.scale(scale_0_out);
|
||||
auto* unsqueeze_1_out = layers.unsqueeze2(scale_1_out);
|
||||
auto* tile_out = layers.tile(unsqueeze_1_out);
|
||||
|
||||
OpDesc* multi_encoder_xpu = block->AppendOp();
|
||||
multi_encoder_xpu->SetType("multi_encoder_xpu");
|
||||
multi_encoder_xpu->SetInput("x", {layer_norm_out->Name()});
|
||||
multi_encoder_xpu->SetInput("mask", {tile_out->Name()});
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
auto pass = PassRegistry::Instance().Get(
|
||||
"multi_encoder_xpu_adaptive_seqlen_fuse_pass");
|
||||
pass->Apply(graph.get());
|
||||
auto num = GetNumOpNodes(graph, "not_equal") + GetNumOpNodes(graph, "cast") +
|
||||
GetNumOpNodes(graph, "unsqueeze2") +
|
||||
GetNumOpNodes(graph, "matmul_v2") + GetNumOpNodes(graph, "scale") +
|
||||
GetNumOpNodes(graph, "tile");
|
||||
PADDLE_ENFORCE_EQ(num,
|
||||
0,
|
||||
common::errors::PreconditionNotMet(
|
||||
"not_equal/cast/unsqueeze2/matmul_v2/scale ops should "
|
||||
"be removed from graph, but graph "
|
||||
"still has %d ops.",
|
||||
num));
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace framework
|
||||
} // namespace paddle
|
||||
|
||||
USE_PASS(multi_encoder_xpu_adaptive_seqlen_fuse_pass);
|
||||
@@ -0,0 +1,221 @@
|
||||
// Copyright (c) 2023 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/pass.h"
|
||||
#include "paddle/fluid/framework/ir/pass_tester_helper.h"
|
||||
|
||||
namespace paddle {
|
||||
namespace framework {
|
||||
namespace ir {
|
||||
|
||||
template <typename T = float>
|
||||
void AddVarToScope(Scope* param_scope,
|
||||
const std::string& name,
|
||||
const DDim& dims,
|
||||
T value = 0) {
|
||||
auto* tensor = param_scope->Var(name)->GetMutable<phi::DenseTensor>();
|
||||
tensor->Resize(dims);
|
||||
auto* cpu_ctx = static_cast<phi::CPUContext*>(
|
||||
phi::DeviceContextPool::Instance().Get(phi::CPUPlace()));
|
||||
auto* data = cpu_ctx->Alloc<T>(tensor);
|
||||
for (int64_t i = 0; i < tensor->numel(); i++) {
|
||||
data[i] = value;
|
||||
}
|
||||
}
|
||||
|
||||
VarDesc* Data(paddle::framework::BlockDesc* block,
|
||||
std::string name,
|
||||
std::vector<int64_t> shape = {},
|
||||
bool is_persistable = false,
|
||||
proto::VarType::Type data_type = proto::VarType::FP32) {
|
||||
auto* var = block->Var(name);
|
||||
var->SetType(proto::VarType::DENSE_TENSOR);
|
||||
var->SetDataType(data_type);
|
||||
var->SetShape(shape);
|
||||
var->SetPersistable(is_persistable);
|
||||
return var;
|
||||
}
|
||||
|
||||
TEST(RemoveAssignGather, basic) {
|
||||
paddle::framework::ProgramDesc program;
|
||||
auto* block = program.MutableBlock(0);
|
||||
|
||||
OpDesc* beam_search_op = block->AppendOp();
|
||||
beam_search_op->SetType("beam_search");
|
||||
beam_search_op->SetAttr("beam_size", 1);
|
||||
|
||||
auto* x = Data(block, "fused_multi_transformer_x", {1, 1, 1536});
|
||||
auto* cache_kv =
|
||||
Data(block, "fused_multi_transformer_cache_kv", {2, 1, 24, 512, 64});
|
||||
OpDesc* fused_multi_transformer_op = block->AppendOp();
|
||||
fused_multi_transformer_op->SetType("fused_multi_transformer");
|
||||
fused_multi_transformer_op->SetInput("X", {x->Name()});
|
||||
fused_multi_transformer_op->SetInput("CacheKV", {cache_kv->Name()});
|
||||
fused_multi_transformer_op->SetOutput("CacheKVOut", {cache_kv->Name()});
|
||||
|
||||
auto* assign_out = Data(block, "assign_out", cache_kv->GetShape());
|
||||
OpDesc* assign_op = block->AppendOp();
|
||||
assign_op->SetType("assign");
|
||||
assign_op->SetInput("X", {cache_kv->Name()});
|
||||
assign_op->SetOutput("Out", {assign_out->Name()});
|
||||
|
||||
OpDesc* gather_op = block->AppendOp();
|
||||
gather_op->SetType("gather");
|
||||
gather_op->SetInput("X", {assign_out->Name()});
|
||||
gather_op->SetOutput("Out", {cache_kv->Name()});
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(program));
|
||||
auto pass = PassRegistry::Instance().Get("one_beam_size_fuse_pass");
|
||||
pass->Apply(graph.get());
|
||||
auto assign_num = GetNumOpNodes(graph, "assign");
|
||||
auto gather_num = GetNumOpNodes(graph, "gather");
|
||||
PADDLE_ENFORCE_EQ(assign_num,
|
||||
0,
|
||||
common::errors::PreconditionNotMet(
|
||||
"assign op should be removed from the graph."));
|
||||
PADDLE_ENFORCE_EQ(gather_num,
|
||||
0,
|
||||
common::errors::PreconditionNotMet(
|
||||
"gather op should be removed from the graph."));
|
||||
}
|
||||
|
||||
TEST(FoldShapeAssociatedOps, basic) {
|
||||
Layers layers;
|
||||
auto* block = layers.Block();
|
||||
|
||||
OpDesc* beam_search_op = block->AppendOp();
|
||||
beam_search_op->SetType("beam_search");
|
||||
beam_search_op->SetAttr("beam_size", 1);
|
||||
|
||||
auto* shape_x = layers.data("shape_x", {1, 46256});
|
||||
auto* shape_out = layers.shape(shape_x);
|
||||
auto* slice_out = layers.slice(shape_out, {0}, {0}, {1});
|
||||
auto* div_out = layers.elementwise_div(slice_out, slice_out);
|
||||
auto* cast0_out = layers.cast(div_out);
|
||||
auto* cast1_out = layers.cast(slice_out);
|
||||
auto* scale0_out = layers.scale(slice_out);
|
||||
auto* cast2_out = layers.cast(scale0_out);
|
||||
auto* range_out = layers.range(cast2_out, cast1_out, cast0_out);
|
||||
auto* unsqueeze2_out = layers.unsqueeze2(range_out);
|
||||
auto* scale1_out = layers.scale(unsqueeze2_out);
|
||||
auto* add_x = layers.data("add_x", {1, 2});
|
||||
auto* add_out = layers.elementwise_add(add_x, scale1_out);
|
||||
layers.flatten_contiguous_range(add_out);
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
auto pass = PassRegistry::Instance().Get("one_beam_size_fuse_pass");
|
||||
pass->Apply(graph.get());
|
||||
auto ops_num = GetNumOpNodes(graph);
|
||||
PADDLE_ENFORCE_EQ(
|
||||
ops_num,
|
||||
2,
|
||||
common::errors::PreconditionNotMet(
|
||||
"graph should only have 2 op nodes, but received %d.", ops_num));
|
||||
}
|
||||
|
||||
TEST(RemoveBeamSearchAssociatedOps, basic) {
|
||||
Layers layers;
|
||||
auto* lod_reset_0_x = layers.data("lod_reset_0_x");
|
||||
auto* lod_reset_0_y = layers.data("lod_reset_0_y");
|
||||
auto* lod_reset_0_out = layers.lod_reset(lod_reset_0_x, lod_reset_0_y);
|
||||
auto* lod_reset_1_x = layers.data("lod_reset_1_x");
|
||||
auto* lod_reset_1_y = layers.data("lod_reset_1_y");
|
||||
auto* lod_reset_1_out = layers.lod_reset(lod_reset_1_x, lod_reset_1_y);
|
||||
|
||||
auto* pre_ids = layers.data("pre_ids");
|
||||
auto* pre_scores = layers.data("pre_scores");
|
||||
auto beam_search_outs =
|
||||
layers.beam_search(lod_reset_0_out, lod_reset_1_out, pre_ids, pre_scores);
|
||||
auto* parent_idx = beam_search_outs[0];
|
||||
auto* selected_ids = beam_search_outs[1];
|
||||
auto* selected_scores = beam_search_outs[2];
|
||||
|
||||
auto* write_to_array_0_i = layers.data("write_to_array_0_i");
|
||||
layers.write_to_array(selected_ids, write_to_array_0_i);
|
||||
auto* write_to_array_1_i = layers.data("write_to_array_1_i");
|
||||
layers.write_to_array(selected_scores, write_to_array_1_i);
|
||||
auto* is_empty_out = layers.is_empty(selected_ids);
|
||||
layers.logical_not(is_empty_out);
|
||||
layers.cast(parent_idx);
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
auto* param_scope = new Scope();
|
||||
graph->Set("__param_scope__", param_scope);
|
||||
auto pass = PassRegistry::Instance().Get("one_beam_size_fuse_pass");
|
||||
pass->Apply(graph.get());
|
||||
auto beam_search_num = GetNumOpNodes(graph, "beam_search");
|
||||
PADDLE_ENFORCE_EQ(beam_search_num,
|
||||
0,
|
||||
common::errors::PreconditionNotMet(
|
||||
"beam_search op should be removed from the graph."));
|
||||
}
|
||||
|
||||
TEST(RemoveWriteReadArrayOps, basic) {
|
||||
Layers layers;
|
||||
auto* block = layers.Block();
|
||||
OpDesc* beam_search_op = block->AppendOp();
|
||||
beam_search_op->SetType("beam_search");
|
||||
beam_search_op->SetAttr("beam_size", 1);
|
||||
|
||||
auto* write_x = layers.data("write_x", {1}, true);
|
||||
auto* write_i = layers.data("write_i");
|
||||
auto* write_out = layers.write_to_array(write_x, write_i);
|
||||
auto* read_i = layers.data("read_i");
|
||||
layers.read_from_array(write_out, read_i);
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
auto* param_scope = new Scope();
|
||||
graph->Set("__param_scope__", param_scope);
|
||||
AddVarToScope(param_scope, write_x->Name(), {1});
|
||||
auto pass = PassRegistry::Instance().Get("one_beam_size_fuse_pass");
|
||||
pass->Apply(graph.get());
|
||||
auto write_read_num = GetNumOpNodes(graph, "write_to_array") +
|
||||
GetNumOpNodes(graph, "read_from_array");
|
||||
PADDLE_ENFORCE_EQ(write_read_num,
|
||||
0,
|
||||
common::errors::PreconditionNotMet(
|
||||
"write_to_array and read_from_array ops should be "
|
||||
"removed from the graph."));
|
||||
}
|
||||
|
||||
TEST(RemoveGatherOps, basic) {
|
||||
Layers layers;
|
||||
auto* block = layers.Block();
|
||||
OpDesc* beam_search_op = block->AppendOp();
|
||||
beam_search_op->SetType("beam_search");
|
||||
beam_search_op->SetAttr("beam_size", 1);
|
||||
|
||||
auto* gather_x = layers.data("gather_x");
|
||||
auto* gather_i = layers.data("gather_i", {1}, true);
|
||||
layers.gather(gather_x, gather_i, 0);
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
auto* param_scope = new Scope();
|
||||
graph->Set("__param_scope__", param_scope);
|
||||
AddVarToScope<int>(param_scope, gather_i->Name(), {1}, 0);
|
||||
auto pass = PassRegistry::Instance().Get("one_beam_size_fuse_pass");
|
||||
pass->Apply(graph.get());
|
||||
auto gather_num = GetNumOpNodes(graph, "gather");
|
||||
PADDLE_ENFORCE_EQ(gather_num,
|
||||
0,
|
||||
common::errors::PreconditionNotMet(
|
||||
"gather op should be removed from the graph."));
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace framework
|
||||
} // namespace paddle
|
||||
|
||||
USE_PASS(one_beam_size_fuse_pass);
|
||||
@@ -0,0 +1,105 @@
|
||||
// Copyright (c) 2023 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/pass.h"
|
||||
#include "paddle/fluid/framework/ir/pass_tester_helper.h"
|
||||
#include "paddle/fluid/platform/enforce.h"
|
||||
|
||||
namespace paddle {
|
||||
namespace framework {
|
||||
namespace ir {
|
||||
|
||||
TEST(Squeeze2MatmulXPUFusePass, basic) {
|
||||
Layers layers;
|
||||
|
||||
auto* squeeze2_in = layers.data("squeeze2_in", {64, 1, 74, 1});
|
||||
auto* squeeze2_out = layers.squeeze2(squeeze2_in, std::vector<int>{1, 3});
|
||||
auto* matmul_y = layers.data("matmul_y", {74, 64}, true);
|
||||
auto* matmul_out =
|
||||
layers.matmul(squeeze2_out, matmul_y, nullptr, false, false);
|
||||
auto* ele_y = layers.data("ele_y", {64}, true);
|
||||
layers.elementwise_add(matmul_out, ele_y);
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
auto pass = PassRegistry::Instance().Get("squeeze2_matmul_xpu_fuse_pass");
|
||||
VLOG(3) << DebugString(graph);
|
||||
|
||||
pass->Apply(graph.get());
|
||||
VLOG(3) << DebugString(graph);
|
||||
|
||||
auto ops_num = GetNumOpNodes(graph);
|
||||
PADDLE_ENFORCE_EQ(
|
||||
ops_num,
|
||||
3,
|
||||
common::errors::PreconditionNotMet(
|
||||
"graph should only have 2 op nodes, but received %d.", ops_num));
|
||||
}
|
||||
|
||||
TEST(ReShape2MatmulXPUFusePass, basic) {
|
||||
Layers layers;
|
||||
|
||||
auto* reshape2_in = layers.data("reshape2_in", {64, 1, 74, 1});
|
||||
auto* reshape2_out = layers.reshape2(reshape2_in, std::vector<int>{-1, 74});
|
||||
auto* matmul_y = layers.data("matmul_y", {74, 64}, true);
|
||||
auto* matmul_out =
|
||||
layers.matmul(reshape2_out, matmul_y, nullptr, false, false);
|
||||
auto* ele_y = layers.data("ele_y", {64}, true);
|
||||
layers.elementwise_add(matmul_out, ele_y);
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
auto pass = PassRegistry::Instance().Get("reshape2_matmul_xpu_fuse_pass");
|
||||
VLOG(3) << DebugString(graph);
|
||||
|
||||
pass->Apply(graph.get());
|
||||
VLOG(3) << DebugString(graph);
|
||||
|
||||
auto ops_num = GetNumOpNodes(graph);
|
||||
PADDLE_ENFORCE_EQ(
|
||||
ops_num,
|
||||
3,
|
||||
common::errors::PreconditionNotMet(
|
||||
"graph should only have 2 op nodes, but received %d.", ops_num));
|
||||
}
|
||||
|
||||
TEST(MapMatmulV2ToMatmulXPUPass, basic) {
|
||||
Layers layers;
|
||||
|
||||
auto* matmul_x = layers.data("matmul_x", {64, 74});
|
||||
auto* matmul_y = layers.data("matmul_y", {74, 64}, true);
|
||||
layers.matmul_v2(matmul_x, matmul_y, nullptr, false, false);
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
auto pass = PassRegistry::Instance().Get("map_matmulv2_to_matmul_xpu_pass");
|
||||
VLOG(3) << DebugString(graph);
|
||||
|
||||
pass->Apply(graph.get());
|
||||
VLOG(3) << DebugString(graph);
|
||||
|
||||
auto matmuls = GetOpNodes(graph, "matmul");
|
||||
for (auto* matmul : matmuls) {
|
||||
PADDLE_ENFORCE_EQ(
|
||||
std::abs(matmul->Op()->GetAttrIfExists<float>("alpha") - 1.f) < 1e-5f,
|
||||
true,
|
||||
common::errors::PreconditionNotMet(
|
||||
"matmul_v2 is mapped to matmul by pass."));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace framework
|
||||
} // namespace paddle
|
||||
|
||||
USE_PASS(reshape2_matmul_xpu_fuse_pass);
|
||||
@@ -0,0 +1,63 @@
|
||||
// Copyright (c) 2023 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/pass.h"
|
||||
#include "paddle/fluid/framework/ir/pass_tester_helper.h"
|
||||
|
||||
namespace paddle {
|
||||
namespace framework {
|
||||
namespace ir {
|
||||
|
||||
TEST(SqueezeExcitationFusePass, V1) {
|
||||
Layers layers;
|
||||
auto* block = layers.Block();
|
||||
|
||||
auto* pool2d_inp = layers.data("pool2d_inp", {1, 24, 14, 14});
|
||||
auto* pool2d_out = layers.pool2d(pool2d_inp, false);
|
||||
|
||||
auto* conv2d_xpu_op1_out = layers.data("conv2d_xpu_op1_out");
|
||||
OpDesc* conv2d_xpu_op1 = block->AppendOp();
|
||||
conv2d_xpu_op1->SetType("conv2d_xpu");
|
||||
conv2d_xpu_op1->SetInput("x", {pool2d_out->Name()});
|
||||
conv2d_xpu_op1->SetOutput("out", {conv2d_xpu_op1_out->Name()});
|
||||
|
||||
auto* conv2d_xpu_op2_out = layers.data("conv2d_xpu_op2_out");
|
||||
OpDesc* conv2d_xpu_op2 = block->AppendOp();
|
||||
conv2d_xpu_op2->SetType("conv2d_xpu");
|
||||
conv2d_xpu_op2->SetInput("x", {conv2d_xpu_op1_out->Name()});
|
||||
conv2d_xpu_op2->SetOutput("out", {conv2d_xpu_op2_out->Name()});
|
||||
|
||||
layers.elementwise_mul(pool2d_inp, conv2d_xpu_op2_out);
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
auto pass = PassRegistry::Instance().Get("squeeze_excitation_fuse_pass");
|
||||
pass->Apply(graph.get());
|
||||
auto num = GetNumOpNodes(graph, "pool2d") +
|
||||
GetNumOpNodes(graph, "conv2d_xpu") +
|
||||
GetNumOpNodes(graph, "elementwise_mul");
|
||||
PADDLE_ENFORCE_EQ(num,
|
||||
0,
|
||||
common::errors::PreconditionNotMet(
|
||||
"pool2d/conv2d_xpu/elementwise_mul ops should be "
|
||||
"removed from graph, but graph "
|
||||
"still has %d ops. ",
|
||||
num));
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace framework
|
||||
} // namespace paddle
|
||||
|
||||
USE_PASS(squeeze_excitation_fuse_pass);
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright (c) 2023 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/pass.h"
|
||||
#include "paddle/fluid/framework/ir/pass_tester_helper.h"
|
||||
|
||||
namespace paddle {
|
||||
namespace framework {
|
||||
namespace ir {
|
||||
|
||||
TEST(StackFusePass, basic) {
|
||||
Layers layers;
|
||||
auto* block = layers.Block();
|
||||
|
||||
auto* stack_x = layers.data("stack_x", {-1, 64, 64});
|
||||
auto* stack_out = layers.stack({stack_x, stack_x, stack_x}, 1);
|
||||
stack_out->SetShape({-1, 3, 64, 64});
|
||||
auto* add_x = layers.data("add_x", {-1, 24, 64, 64});
|
||||
layers.elementwise_add(add_x, stack_out);
|
||||
|
||||
OpDesc* fused_multi_transformer_op = block->AppendOp();
|
||||
fused_multi_transformer_op->SetType("fused_multi_transformer");
|
||||
fused_multi_transformer_op->SetInput("SrcMask", {stack_out->Name()});
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(layers.main_program()));
|
||||
auto pass = PassRegistry::Instance().Get("stack_fuse_pass");
|
||||
pass->Apply(graph.get());
|
||||
auto stack_num = GetNumOpNodes(graph, "stack");
|
||||
PADDLE_ENFORCE_EQ(stack_num,
|
||||
0,
|
||||
common::errors::PreconditionNotMet(
|
||||
"stack op should be removed from graph, but graph "
|
||||
"still has %d stack op.",
|
||||
stack_num));
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace framework
|
||||
} // namespace paddle
|
||||
|
||||
USE_PASS(stack_fuse_pass);
|
||||
@@ -0,0 +1,209 @@
|
||||
// Copyright (c) 2023 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/pass.h"
|
||||
#include "paddle/fluid/framework/ir/pass_tester_helper.h"
|
||||
|
||||
namespace paddle {
|
||||
namespace framework {
|
||||
namespace ir {
|
||||
|
||||
VarDesc* Data(paddle::framework::BlockDesc* block,
|
||||
std::string name,
|
||||
std::vector<int64_t> shape = {},
|
||||
bool is_persistable = false,
|
||||
proto::VarType::Type data_type = proto::VarType::FP32) {
|
||||
auto* var = block->Var(name);
|
||||
var->SetType(proto::VarType::DENSE_TENSOR);
|
||||
var->SetDataType(data_type);
|
||||
var->SetShape(shape);
|
||||
var->SetPersistable(is_persistable);
|
||||
return var;
|
||||
}
|
||||
|
||||
VarDesc* AddCast(BlockDesc* block,
|
||||
VarDesc* input,
|
||||
int in_dtype = 5,
|
||||
int out_dtype = 5) {
|
||||
VarDesc* out = Data(block, input->Name() + "_out");
|
||||
OpDesc* op = block->AppendOp();
|
||||
op->SetType("cast");
|
||||
op->SetInput("X", {input->Name()});
|
||||
op->SetOutput("Out", {out->Name()});
|
||||
op->SetAttr("in_dtype", in_dtype);
|
||||
op->SetAttr("out_dtype", out_dtype);
|
||||
return out;
|
||||
}
|
||||
|
||||
int GetOpNum(Graph* graph, std::string op_type = "") {
|
||||
int num_nodes = 0;
|
||||
for (auto* node : graph->Nodes()) {
|
||||
if (node->IsOp() && node->Op() &&
|
||||
(node->Op()->Type() == op_type || op_type.empty())) {
|
||||
num_nodes++;
|
||||
}
|
||||
}
|
||||
return num_nodes;
|
||||
}
|
||||
|
||||
TEST(ApplyCastSoftmaxPass, basic) {
|
||||
paddle::framework::ProgramDesc program;
|
||||
auto* block = program.MutableBlock(0);
|
||||
auto* cast0_in = Data(block, "cast0_in", {1});
|
||||
auto* cast0_out = AddCast(block, cast0_in, 4, 5);
|
||||
auto* softmax_out = Data(block, "softmax_out", {1});
|
||||
OpDesc* softmax = block->AppendOp();
|
||||
softmax->SetType("softmax");
|
||||
softmax->SetInput("X", {cast0_out->Name()});
|
||||
softmax->SetOutput("Out", {softmax_out->Name()});
|
||||
AddCast(block, softmax_out, 5, 4);
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(program));
|
||||
auto scope = new Scope();
|
||||
graph->Set("__param_scope__", scope);
|
||||
auto pass = PassRegistry::Instance().Get("xpu_delete_cast_op_pass");
|
||||
pass->Apply(graph.get());
|
||||
int cast_num_in_graph = GetOpNum(graph->GetSubGraph(0), "cast");
|
||||
PADDLE_ENFORCE_EQ(
|
||||
GetOpNum(graph->GetSubGraph(0), "cast"),
|
||||
0,
|
||||
common::errors::PreconditionNotMet(
|
||||
"graph should have 0 cast after xpu_delete_cast_op_pass, "
|
||||
"but actually has %d.",
|
||||
cast_num_in_graph));
|
||||
}
|
||||
|
||||
TEST(ApplyCastLayerNormPass, basic) {
|
||||
paddle::framework::ProgramDesc program;
|
||||
auto* block = program.MutableBlock(0);
|
||||
auto* cast0_in = Data(block, "cast0_in", {1});
|
||||
auto* cast0_out = AddCast(block, cast0_in, 4, 5);
|
||||
auto* layer_norm_out = Data(block, "layer_norm_out", {1});
|
||||
OpDesc* layer_norm = block->AppendOp();
|
||||
layer_norm->SetType("layer_norm");
|
||||
layer_norm->SetInput("X", {cast0_out->Name()});
|
||||
layer_norm->SetOutput("Y", {layer_norm_out->Name()});
|
||||
AddCast(block, layer_norm_out, 5, 4);
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(program));
|
||||
auto scope = new Scope();
|
||||
graph->Set("__param_scope__", scope);
|
||||
auto pass = PassRegistry::Instance().Get("xpu_delete_cast_op_pass");
|
||||
pass->Apply(graph.get());
|
||||
int cast_num_in_graph = GetOpNum(graph->GetSubGraph(0), "cast");
|
||||
PADDLE_ENFORCE_EQ(
|
||||
GetOpNum(graph->GetSubGraph(0), "cast"),
|
||||
0,
|
||||
common::errors::PreconditionNotMet(
|
||||
"graph should have 0 cast after xpu_delete_cast_op_pass, "
|
||||
"but actually has %d.",
|
||||
cast_num_in_graph));
|
||||
}
|
||||
|
||||
TEST(ApplyCastCacheKVInitializationPass, basic) {
|
||||
paddle::framework::ProgramDesc program;
|
||||
auto* block = program.MutableBlock(0);
|
||||
auto* shape_in =
|
||||
Data(block, "shape_in", {64, 128}, false, proto::VarType::INT64);
|
||||
auto* shape0_out =
|
||||
Data(block, "shape0_out", {2}, false, proto::VarType::INT32);
|
||||
auto* shape1_out =
|
||||
Data(block, "shape1_out", {2}, false, proto::VarType::INT32);
|
||||
auto* slice0_out =
|
||||
Data(block, "slice0_out", {1}, false, proto::VarType::INT32);
|
||||
auto* slice1_out =
|
||||
Data(block, "slice1_out", {1}, false, proto::VarType::INT32);
|
||||
auto* elementwise_add_in0 =
|
||||
Data(block, "elementwise_add_in0", {1}, false, proto::VarType::INT64);
|
||||
auto* elementwise_add_out =
|
||||
Data(block, "elementwise_add_out", {1}, false, proto::VarType::INT64);
|
||||
auto* scale_out = Data(block, "scale_out", {1}, false, proto::VarType::INT64);
|
||||
|
||||
OpDesc* shape0 = block->AppendOp();
|
||||
shape0->SetType("shape");
|
||||
shape0->SetInput("X", {shape_in->Name()});
|
||||
shape0->SetOutput("Out", {shape0_out->Name()});
|
||||
|
||||
OpDesc* shape1 = block->AppendOp();
|
||||
shape1->SetType("shape");
|
||||
shape1->SetInput("X", {shape_in->Name()});
|
||||
shape1->SetOutput("Out", {shape1_out->Name()});
|
||||
|
||||
OpDesc* slice0 = block->AppendOp();
|
||||
slice0->SetType("slice");
|
||||
slice0->SetInput("X", {shape0_out->Name()});
|
||||
slice0->SetOutput("Out", {slice0_out->Name()});
|
||||
|
||||
OpDesc* slice1 = block->AppendOp();
|
||||
slice1->SetType("slice");
|
||||
slice1->SetInput("X", {shape1_out->Name()});
|
||||
slice1->SetOutput("Out", {slice1_out->Name()});
|
||||
|
||||
auto cast0_out = AddCast(block,
|
||||
slice1_out,
|
||||
static_cast<int>(proto::VarType::INT32),
|
||||
static_cast<int>(proto::VarType::INT64));
|
||||
|
||||
OpDesc* elementwise_add = block->AppendOp();
|
||||
elementwise_add->SetType("elementwise_add");
|
||||
elementwise_add->SetInput("X", {elementwise_add_in0->Name()});
|
||||
elementwise_add->SetInput("Y", {cast0_out->Name()});
|
||||
elementwise_add->SetOutput("Out", {elementwise_add_out->Name()});
|
||||
|
||||
OpDesc* scale = block->AppendOp();
|
||||
scale->SetType("scale");
|
||||
scale->SetInput("X", {elementwise_add_out->Name()});
|
||||
scale->SetOutput("Out", {scale_out->Name()});
|
||||
scale->SetAttr("scale", 1.0f);
|
||||
scale->SetAttr("bias", 64.0f);
|
||||
|
||||
auto* cast1_out = AddCast(block,
|
||||
scale_out,
|
||||
static_cast<int>(proto::VarType::INT64),
|
||||
static_cast<int>(proto::VarType::INT32));
|
||||
|
||||
OpDesc* fill_constant = block->AppendOp();
|
||||
fill_constant->SetType("fill_constant");
|
||||
fill_constant->SetInput("X", {slice0_out->Name()});
|
||||
fill_constant->SetInput("Y", {cast1_out->Name()});
|
||||
|
||||
std::unique_ptr<ir::Graph> graph(new ir::Graph(program));
|
||||
auto scope = new Scope();
|
||||
graph->Set("__param_scope__", scope);
|
||||
auto pass = PassRegistry::Instance().Get("xpu_delete_cast_op_pass");
|
||||
pass->Apply(graph.get());
|
||||
int shape_num_in_graph = GetOpNum(graph->GetSubGraph(0), "shape");
|
||||
PADDLE_ENFORCE_EQ(
|
||||
GetOpNum(graph->GetSubGraph(0), "shape"),
|
||||
1,
|
||||
common::errors::PreconditionNotMet("graph should have 1 shape after "
|
||||
"xpu_delete_cast_op_pass, "
|
||||
"but actually has %d.",
|
||||
shape_num_in_graph));
|
||||
int cast_num_in_graph = GetOpNum(graph->GetSubGraph(0), "cast");
|
||||
PADDLE_ENFORCE_EQ(
|
||||
GetOpNum(graph->GetSubGraph(0), "cast"),
|
||||
1,
|
||||
common::errors::PreconditionNotMet("graph should have 1 cast after "
|
||||
"xpu_delete_cast_op_pass, "
|
||||
"but actually has %d.",
|
||||
cast_num_in_graph));
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace framework
|
||||
} // namespace paddle
|
||||
|
||||
USE_PASS(xpu_delete_cast_op_pass);
|
||||
Reference in New Issue
Block a user