Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into fix_bug_for_lstmp
test=developrevert-15774-anakin_subgraph_engine
commit
dff7461ea8
@ -0,0 +1,80 @@
|
||||
// Copyright (c) 2019 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 <algorithm>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include "glog/logging.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "paddle/fluid/framework/ir/graph.h"
|
||||
#include "paddle/fluid/framework/ir/graph_helper.h"
|
||||
#include "paddle/fluid/framework/op_registry.h"
|
||||
#include "paddle/fluid/framework/program_desc.h"
|
||||
|
||||
namespace paddle {
|
||||
namespace framework {
|
||||
|
||||
class DummyOp : public OperatorBase {
|
||||
public:
|
||||
DummyOp(const std::string& type, const VariableNameMap& inputs,
|
||||
const VariableNameMap& outputs, const AttributeMap& attrs)
|
||||
: OperatorBase(type, inputs, outputs, attrs) {}
|
||||
|
||||
private:
|
||||
void RunImpl(const Scope& scope,
|
||||
const platform::Place& place) const override {}
|
||||
};
|
||||
|
||||
class SumOpMaker : public OpProtoAndCheckerMaker {
|
||||
public:
|
||||
void Make() {
|
||||
AddInput("X", "").AsDuplicable();
|
||||
AddOutput("Out", "");
|
||||
AddComment("");
|
||||
}
|
||||
};
|
||||
|
||||
class AssignOpMaker : public OpProtoAndCheckerMaker {
|
||||
public:
|
||||
void Make() {
|
||||
AddInput("X", "").AsDuplicable();
|
||||
AddOutput("Out", "");
|
||||
AddComment("");
|
||||
}
|
||||
};
|
||||
|
||||
class SplitOpMaker : public OpProtoAndCheckerMaker {
|
||||
public:
|
||||
void Make() {
|
||||
AddInput("X", "");
|
||||
AddOutput("Out", "").AsDuplicable();
|
||||
AddComment("");
|
||||
}
|
||||
};
|
||||
|
||||
class DummyVarTypeInference : public VarTypeInference {
|
||||
public:
|
||||
void operator()(const OpDesc& op_desc, BlockDesc* block) const override {
|
||||
auto& inputs = op_desc.Input("X");
|
||||
auto type = block->Var(inputs.front())->GetType();
|
||||
auto out_var_name = op_desc.Output("Out").front();
|
||||
block->Var(out_var_name)->SetType(type);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace framework
|
||||
} // namespace paddle
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,93 @@
|
||||
// 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 abtain 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 <map>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "paddle/fluid/framework/details/memory_optimize_helper.h"
|
||||
#include "paddle/fluid/framework/ir/graph.h"
|
||||
#include "paddle/fluid/framework/ir/pass.h"
|
||||
|
||||
namespace paddle {
|
||||
namespace framework {
|
||||
namespace details {
|
||||
|
||||
class GraphView {
|
||||
public:
|
||||
GraphView() = default;
|
||||
|
||||
void Build(ir::Graph* g);
|
||||
|
||||
const std::vector<ir::Node*>& AllOps();
|
||||
|
||||
ir::Node* GetNodeByName(const std::string& name,
|
||||
const std::vector<ir::Node*>& nodes) const;
|
||||
|
||||
std::vector<ir::Node*> PendingOpsOnVar(ir::Node* var);
|
||||
|
||||
// Will Deperated in the future.
|
||||
// NOTE(dzhwinter) :
|
||||
// 1. Python memory optimize will reuse
|
||||
// memory based var name, so different op output may
|
||||
// have the same variable name. enable inplace on such node
|
||||
// will generate a circle in ssa graph.
|
||||
// 2. DistributeTranspiler will use unique name to
|
||||
// map the parameter and gradient, must be skipped.
|
||||
bool InSkipSet(const std::string& var) const;
|
||||
|
||||
private:
|
||||
std::vector<ir::Node*> ops_;
|
||||
std::unordered_set<std::string> dup_nodes_; // mem opt affect nodes
|
||||
std::map<ir::Node*, std::unordered_set<ir::Node*>> adj_list_;
|
||||
};
|
||||
|
||||
typedef std::vector<std::pair<ir::Node*, ir::Node*>> SSANodePair;
|
||||
class InplacePass : public ir::Pass {
|
||||
public:
|
||||
InplacePass();
|
||||
|
||||
protected:
|
||||
std::unique_ptr<ir::Graph> ApplyImpl(
|
||||
std::unique_ptr<ir::Graph> graph) const override;
|
||||
|
||||
void InitSSAGraphNodes() const;
|
||||
|
||||
private:
|
||||
const SSANodePair TryInplaceModifyVar(const std::string& var,
|
||||
const std::string& cache_var,
|
||||
const size_t& idx,
|
||||
ir::Graph* graph) const;
|
||||
|
||||
void CommitModify(const SSANodePair&, ir::Graph* graph) const;
|
||||
|
||||
void WithdrawModify(const SSANodePair& nodes, ir::Graph* graph) const;
|
||||
|
||||
void InplaceModifyDesc(const std::string& in_var, const std::string& out_var,
|
||||
const size_t& idx) const;
|
||||
|
||||
void TryInplaceOpInputOutput(ir::Node* op, ir::Graph* graph) const;
|
||||
|
||||
mutable std::map<std::string, std::vector<ir::Node*>> var_nodes_;
|
||||
|
||||
mutable std::unordered_set<std::string> whitelist_;
|
||||
mutable GraphView view_;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
} // namespace framework
|
||||
} // namespace paddle
|
@ -0,0 +1,115 @@
|
||||
// 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 <functional>
|
||||
#include <numeric>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include "glog/logging.h"
|
||||
#include "paddle/fluid/framework/block_desc.h"
|
||||
#include "paddle/fluid/framework/details/memory_optimize_helper.h"
|
||||
#include "paddle/fluid/framework/op_desc.h"
|
||||
#include "paddle/fluid/framework/type_defs.h"
|
||||
|
||||
namespace paddle {
|
||||
namespace framework {
|
||||
|
||||
/*
|
||||
Inplace Inference for create In->Out pairs for inplaced operator.
|
||||
If we specify a pair of corresponding names. For example, X->Out.
|
||||
then Out will inplaced use X's memory. The base class will do
|
||||
legality validation for both variables.
|
||||
*/
|
||||
class InplaceOpInference {
|
||||
public:
|
||||
virtual ~InplaceOpInference() {}
|
||||
virtual std::unordered_map<std::string, std::string> operator()(
|
||||
const OpDesc& op_desc, BlockDesc* block) const = 0;
|
||||
};
|
||||
|
||||
class InplaceInToOut : public InplaceOpInference {
|
||||
public:
|
||||
std::unordered_map<std::string, std::string> operator()(
|
||||
const OpDesc& op_desc, BlockDesc* block) const {
|
||||
std::unordered_map<std::string, std::string> ret;
|
||||
auto in_out_var_names_pair = this->Apply(op_desc, block);
|
||||
for (auto& pair : in_out_var_names_pair) {
|
||||
PADDLE_ENFORCE(!op_desc.Input(pair.first).empty(),
|
||||
string::Sprintf("op %s do not have input of %s!",
|
||||
op_desc.Type(), pair.first));
|
||||
PADDLE_ENFORCE(!op_desc.Output(pair.second).empty(),
|
||||
string::Sprintf("op %s do not have output of %s!",
|
||||
op_desc.Type(), pair.second));
|
||||
auto& in_name = op_desc.Input(pair.first).at(0);
|
||||
auto& out_name = op_desc.Output(pair.second).at(0);
|
||||
|
||||
auto in = block->FindRecursiveOrCreateVar(in_name);
|
||||
auto out = block->FindRecursiveOrCreateVar(out_name);
|
||||
if (TryInplaceInputOutput(in, out)) ret.insert({in_name, out_name});
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual std::unordered_map<std::string, std::string> Apply(
|
||||
const OpDesc& op_desc, BlockDesc* block) const = 0;
|
||||
|
||||
bool TryInplaceInputOutput(const VarDesc& in, const VarDesc& out) const {
|
||||
return in.Name() != out.Name() && details::NodeCanReused(in) &&
|
||||
details::NodeCanReused(out) &&
|
||||
details::NodeSizeInBytes(out) <= details::NodeSizeInBytes(in);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Inplace In and Out for operator only have an Input and an Output.
|
||||
For example, activation op.
|
||||
*/
|
||||
class SingleOpInplaceInToOut : public InplaceInToOut {
|
||||
protected:
|
||||
std::unordered_map<std::string, std::string> Apply(
|
||||
const OpDesc& op_desc, BlockDesc* block) const override {
|
||||
PADDLE_ENFORCE(!op_desc.InputNames().empty(),
|
||||
"Op inputs must not be empty");
|
||||
PADDLE_ENFORCE(!op_desc.OutputNames().empty(),
|
||||
"Op outputs must not be empty");
|
||||
auto x_name = op_desc.InputNames().at(0);
|
||||
auto out_name = op_desc.OutputNames().at(0);
|
||||
return std::unordered_map<std::string, std::string>{{x_name, out_name}};
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Gradient op. Inplace output use it's Input.
|
||||
For example, Input@Grad->Input reuse strategy.
|
||||
*/
|
||||
class GradOpInplaceInToOut : public InplaceInToOut {
|
||||
protected:
|
||||
std::unordered_map<std::string, std::string> Apply(
|
||||
const OpDesc& op_desc, BlockDesc* block) const override {
|
||||
std::unordered_map<std::string, std::string> ret;
|
||||
std::unordered_set<std::string> output_names(op_desc.OutputNames().begin(),
|
||||
op_desc.OutputNames().end());
|
||||
for (auto& input_name : op_desc.InputNames()) {
|
||||
if (output_names.count(GradVarName(input_name))) {
|
||||
ret.insert({input_name, GradVarName(input_name)});
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace framework
|
||||
} // namespace paddle
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue