revert-15207-remove_op_handle_lock_and_fix_var
commit
4743c9cd5d
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,222 @@
|
||||
// Copyright (c) 2018 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 "paddle/fluid/framework/ir/conv_affine_channel_fuse_pass.h"
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "paddle/fluid/framework/lod_tensor.h"
|
||||
#include "paddle/fluid/operators/math/cpu_vec.h"
|
||||
#include "paddle/fluid/platform/enforce.h"
|
||||
|
||||
namespace paddle {
|
||||
namespace framework {
|
||||
namespace ir {
|
||||
|
||||
#define GET_CONV_BN_NODES(pattern_name) \
|
||||
/* OPERATORS */ \
|
||||
GET_IR_NODE_FROM_SUBGRAPH(conv, conv, pattern_name); \
|
||||
GET_IR_NODE_FROM_SUBGRAPH(affine_channel, affine_channel, pattern_name); \
|
||||
/* CONV inputs */ \
|
||||
GET_IR_NODE_FROM_SUBGRAPH(conv_weight, conv_weight, pattern_name); \
|
||||
/* CONV outputs */ \
|
||||
GET_IR_NODE_FROM_SUBGRAPH(conv_out, conv_out, pattern_name); \
|
||||
/* Affine Channel inputs */ \
|
||||
GET_IR_NODE_FROM_SUBGRAPH(ac_scale, ac_scale, pattern_name); \
|
||||
GET_IR_NODE_FROM_SUBGRAPH(ac_bias, ac_bias, pattern_name); \
|
||||
/* Affine channel outputs */ \
|
||||
GET_IR_NODE_FROM_SUBGRAPH(ac_out, ac_out, pattern_name); /* Out */
|
||||
|
||||
void recompute_bias_and_weights(const Scope* scope, ir::Node* conv_weight,
|
||||
const ir::Node& ac_scale,
|
||||
const LoDTensor& ac_bias_tensor,
|
||||
LoDTensor* eltwise_y_in_tensor) {
|
||||
using EigenVectorArrayMap =
|
||||
Eigen::Map<Eigen::Array<float, Eigen::Dynamic, 1>>;
|
||||
using ConstEigenVectorArrayMap =
|
||||
Eigen::Map<const Eigen::Array<float, Eigen::Dynamic, 1>>;
|
||||
using EigenMatrixArrayMap = Eigen::Map<
|
||||
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>;
|
||||
|
||||
// Re-compute bias of conv2d from AffineChannel
|
||||
PADDLE_ENFORCE_EQ(eltwise_y_in_tensor->dims(), ac_bias_tensor.dims());
|
||||
|
||||
auto* scale_tensor = scope->FindVar(ac_scale.Name())->GetMutable<LoDTensor>();
|
||||
|
||||
ConstEigenVectorArrayMap scale_array(scale_tensor->data<float>(),
|
||||
scale_tensor->numel(), 1);
|
||||
ConstEigenVectorArrayMap ac_bias_array(ac_bias_tensor.data<float>(),
|
||||
ac_bias_tensor.numel(), 1);
|
||||
|
||||
EigenVectorArrayMap eltwise_y_in_array(
|
||||
eltwise_y_in_tensor->mutable_data<float>(platform::CPUPlace()),
|
||||
eltwise_y_in_tensor->numel(), 1);
|
||||
|
||||
eltwise_y_in_array = (eltwise_y_in_array * scale_array) + ac_bias_array;
|
||||
|
||||
// Re-compute weight of conv2d from AffineChannel
|
||||
auto* weights = scope->FindVar(conv_weight->Name())->GetMutable<LoDTensor>();
|
||||
auto weights_shape = weights->dims();
|
||||
auto weights_shape_2d = flatten_to_2d(weights_shape, 1);
|
||||
|
||||
EigenMatrixArrayMap weights_array_2d(
|
||||
weights->mutable_data<float>(platform::CPUPlace()), weights_shape_2d[0],
|
||||
weights_shape_2d[1]);
|
||||
|
||||
weights_array_2d.colwise() *= scale_array;
|
||||
}
|
||||
|
||||
std::unique_ptr<ir::Graph> ConvAffineChannelFusePass::ApplyImpl(
|
||||
std::unique_ptr<ir::Graph> graph) const {
|
||||
PADDLE_ENFORCE(graph.get());
|
||||
FusePassBase::Init(name_scope_, graph.get());
|
||||
|
||||
auto* scope = param_scope();
|
||||
PADDLE_ENFORCE(scope);
|
||||
|
||||
GraphPatternDetector gpd;
|
||||
auto* conv_input =
|
||||
gpd.mutable_pattern()
|
||||
->NewNode(patterns::PDNodeName(name_scope_, "conv_input"))
|
||||
->AsInput()
|
||||
->assert_is_op_input("conv2d", "Input");
|
||||
patterns::ConvAffineChannel conv_ac_pattern(gpd.mutable_pattern(),
|
||||
name_scope_);
|
||||
conv_ac_pattern(conv_input, false /*with_eltwise_add*/);
|
||||
|
||||
int found_conv_ac_count = 0;
|
||||
auto handler = [&](const GraphPatternDetector::subgraph_t& subgraph,
|
||||
Graph* g) {
|
||||
VLOG(4) << "handle ConvAffineChannel fuse";
|
||||
|
||||
GET_CONV_BN_NODES(conv_ac_pattern);
|
||||
|
||||
// check if fuse can be done and if MKL-DNN should be used
|
||||
FuseOptions fuse_option = FindFuseOption(*conv, *affine_channel);
|
||||
if (fuse_option == DO_NOT_FUSE) {
|
||||
VLOG(3) << "do not perform conv+affinechannel fuse";
|
||||
return;
|
||||
}
|
||||
|
||||
// Create eltwise_y (conv bias) variable
|
||||
VarDesc eltwise_y_in_desc(
|
||||
patterns::PDNodeName(name_scope_, "eltwise_y_in"));
|
||||
eltwise_y_in_desc.SetPersistable(true);
|
||||
auto* eltwise_y_in_node = g->CreateVarNode(&eltwise_y_in_desc);
|
||||
auto* eltwise_y_in_tensor =
|
||||
scope->Var(eltwise_y_in_node->Name())->GetMutable<LoDTensor>();
|
||||
|
||||
// Get affine_channel bias
|
||||
auto* ac_bias_tensor =
|
||||
scope->FindVar(ac_bias->Name())->GetMutable<LoDTensor>();
|
||||
|
||||
// Initialize eltwise_y
|
||||
eltwise_y_in_tensor->Resize(ac_bias_tensor->dims());
|
||||
std::fill_n(eltwise_y_in_tensor->mutable_data<float>(platform::CPUPlace()),
|
||||
eltwise_y_in_tensor->numel(), 0.0f);
|
||||
|
||||
// update weights and biases
|
||||
recompute_bias_and_weights(scope, conv_weight, *ac_scale, *ac_bias_tensor,
|
||||
eltwise_y_in_tensor);
|
||||
|
||||
// create an elementwise add node.
|
||||
OpDesc desc;
|
||||
desc.SetInput("X", std::vector<std::string>({conv_out->Name()}));
|
||||
desc.SetInput("Y", std::vector<std::string>({eltwise_y_in_node->Name()}));
|
||||
desc.SetOutput("Out", std::vector<std::string>({ac_out->Name()}));
|
||||
desc.SetType("elementwise_add");
|
||||
desc.SetAttr("axis", 1);
|
||||
auto eltwise_op = g->CreateOpNode(&desc); // OpDesc will be copied.
|
||||
|
||||
GraphSafeRemoveNodes(graph.get(), {ac_scale, ac_bias, affine_channel});
|
||||
|
||||
IR_NODE_LINK_TO(conv_out, eltwise_op);
|
||||
IR_NODE_LINK_TO(eltwise_y_in_node, eltwise_op);
|
||||
IR_NODE_LINK_TO(eltwise_op, ac_out);
|
||||
found_conv_ac_count++;
|
||||
};
|
||||
|
||||
gpd(graph.get(), handler);
|
||||
|
||||
AddStatis(found_conv_ac_count);
|
||||
return graph;
|
||||
}
|
||||
|
||||
std::unique_ptr<ir::Graph> ConvEltwiseAddAffineChannelFusePass::ApplyImpl(
|
||||
std::unique_ptr<ir::Graph> graph) const {
|
||||
PADDLE_ENFORCE(graph.get());
|
||||
FusePassBase::Init(name_scope_, graph.get());
|
||||
|
||||
auto* scope = param_scope();
|
||||
PADDLE_ENFORCE(scope);
|
||||
|
||||
GraphPatternDetector gpd;
|
||||
auto* conv_input =
|
||||
gpd.mutable_pattern()
|
||||
->NewNode(patterns::PDNodeName(name_scope_, "conv_input"))
|
||||
->AsInput()
|
||||
->assert_is_op_input("conv2d", "Input");
|
||||
patterns::ConvAffineChannel conv_ac_pattern(gpd.mutable_pattern(),
|
||||
name_scope_);
|
||||
conv_ac_pattern(conv_input, true /*with_eltwise_add*/);
|
||||
|
||||
int found_conv_ac_count = 0;
|
||||
auto handler = [&](const GraphPatternDetector::subgraph_t& subgraph,
|
||||
Graph* g) {
|
||||
VLOG(4) << "handle ConvBN fuse";
|
||||
|
||||
GET_CONV_BN_NODES(conv_ac_pattern);
|
||||
// OPERATORS
|
||||
GET_IR_NODE_FROM_SUBGRAPH(eltwise, eltwise, conv_ac_pattern);
|
||||
// BIAS inputs
|
||||
GET_IR_NODE_FROM_SUBGRAPH(eltwise_y_in, eltwise_y_in, conv_ac_pattern);
|
||||
// BIAS outputs
|
||||
GET_IR_NODE_FROM_SUBGRAPH(eltwise_out, eltwise_out, conv_ac_pattern);
|
||||
|
||||
// Get eltwise_y (conv bias) variable
|
||||
auto* eltwise_y_in_tensor =
|
||||
scope->FindVar(eltwise_y_in->Name())->GetMutable<LoDTensor>();
|
||||
|
||||
// Get batch norm bias
|
||||
auto* ac_bias_tensor =
|
||||
scope->FindVar(ac_bias->Name())->GetMutable<LoDTensor>();
|
||||
|
||||
recompute_bias_and_weights(scope, conv_weight, *ac_scale, *ac_bias_tensor,
|
||||
eltwise_y_in_tensor);
|
||||
|
||||
// Update the elementwise_add node
|
||||
eltwise->Op()->SetAttr("axis", 1);
|
||||
eltwise->Op()->SetOutput("Out", std::vector<std::string>({ac_out->Name()}));
|
||||
|
||||
GraphSafeRemoveNodes(graph.get(),
|
||||
{ac_scale, ac_bias, affine_channel, eltwise_out});
|
||||
|
||||
IR_NODE_LINK_TO(eltwise, ac_out);
|
||||
|
||||
found_conv_ac_count++;
|
||||
};
|
||||
|
||||
gpd(graph.get(), handler);
|
||||
AddStatis(found_conv_ac_count);
|
||||
return graph;
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace framework
|
||||
} // namespace paddle
|
||||
|
||||
REGISTER_PASS(conv_affine_channel_fuse_pass,
|
||||
paddle::framework::ir::ConvAffineChannelFusePass);
|
||||
REGISTER_PASS(conv_eltwiseadd_affine_channel_fuse_pass,
|
||||
paddle::framework::ir::ConvEltwiseAddAffineChannelFusePass);
|
@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2018 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "paddle/fluid/framework/ir/fuse_pass_base.h"
|
||||
#include "paddle/fluid/framework/ir/graph.h"
|
||||
#include "paddle/fluid/framework/ir/graph_pattern_detector.h"
|
||||
|
||||
namespace paddle {
|
||||
namespace framework {
|
||||
namespace ir {
|
||||
|
||||
/*
|
||||
* Fuse the Conv and ConvAffineChannel.
|
||||
*/
|
||||
class ConvAffineChannelFusePass : public FusePassBase {
|
||||
public:
|
||||
virtual ~ConvAffineChannelFusePass() {}
|
||||
|
||||
protected:
|
||||
std::unique_ptr<ir::Graph> ApplyImpl(std::unique_ptr<ir::Graph> graph) const;
|
||||
const std::string name_scope_{"conv_affine_channel_fuse"};
|
||||
};
|
||||
|
||||
class ConvEltwiseAddAffineChannelFusePass : public FusePassBase {
|
||||
public:
|
||||
virtual ~ConvEltwiseAddAffineChannelFusePass() {}
|
||||
|
||||
protected:
|
||||
std::unique_ptr<ir::Graph> ApplyImpl(std::unique_ptr<ir::Graph> graph) const;
|
||||
const std::string name_scope_{"conv_eltwiseadd_affine_channel_fuse"};
|
||||
};
|
||||
|
||||
} // namespace ir
|
||||
} // namespace framework
|
||||
} // namespace paddle
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue