Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
e51e7ba
Save local file for merge
zhhsplendid May 27, 2019
8a6db0e
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
zhhsplendid May 27, 2019
e9da08a
Support memory eager deletion on recurrent OP
zhhsplendid May 29, 2019
ba5ea07
Remove debug log in rnn_memory_helper_op.cc
zhhsplendid May 29, 2019
90e1519
Add comments for functions
zhhsplendid May 29, 2019
38ba259
Merge branch 'rnn_op' of https://github.com/zhhsplendid/Paddle into r…
zhhsplendid May 29, 2019
dd9d940
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
zhhsplendid May 30, 2019
10746cf
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
zhhsplendid Jun 17, 2019
e98f566
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
zhhsplendid Jul 11, 2019
8f7373d
Modify based on reviewer's comments
zhhsplendid Jul 17, 2019
ce52e80
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
zhhsplendid Jul 17, 2019
446bc9f
Add ParallelExecutor test for eager deletion
zhhsplendid Jul 17, 2019
eb8efa5
Add unit test that one forward only rnn with one backward rnn
zhhsplendid Jul 17, 2019
afb8c3e
Remove a useless comment
zhhsplendid Jul 17, 2019
cd1c2eb
Fix commit history
zhhsplendid Jul 18, 2019
8a54181
Try constexpr declaration
zhhsplendid Jul 18, 2019
fc3dd8e
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
zhhsplendid Jul 18, 2019
c4fb071
Remove the duplicated definition
zhhsplendid Jul 18, 2019
ba43599
Try to change constexpr to const in recurrent_op
zhhsplendid Jul 18, 2019
bff0367
Add CMakeLists deps to fix CI
zhhsplendid Jul 18, 2019
5e9d853
Change fluid.core to core to fix CI
zhhsplendid Jul 18, 2019
4c9537e
Remove get_cuda_device_count to pass Mac CI
zhhsplendid Jul 18, 2019
fb905a2
Add if branch for using get_cuda_device_count
zhhsplendid Jul 18, 2019
36df9b1
Add if condition for CUDA / CPU places for test
zhhsplendid Jul 18, 2019
5dd6470
Use 1 batch to avoid CI tests which doesn't have cuda devices
zhhsplendid Jul 18, 2019
57a9fca
Change constexpr in a class to const because msvc15 doesn't support
zhhsplendid Jul 19, 2019
0b89ada
Trigger CI...
zhhsplendid Jul 19, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion paddle/fluid/framework/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ else()
cc_test(test_naive_executor SRCS naive_executor_test.cc DEPS naive_executor elementwise_add_op)
endif()

target_link_libraries(executor while_op_helper executor_gc_helper)
target_link_libraries(executor while_op_helper executor_gc_helper recurrent_op_helper)

cc_library(parallel_executor SRCS parallel_executor.cc DEPS
threaded_ssa_graph_executor scope_buffered_ssa_graph_executor parallel_ssa_graph_executor async_ssa_graph_executor
Expand Down
3 changes: 3 additions & 0 deletions paddle/fluid/framework/executor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ limitations under the License. */
#include "paddle/fluid/framework/trainer_factory.h"
#include "paddle/fluid/framework/transfer_scope_cache.h"
#include "paddle/fluid/framework/variable_helper.h"
#include "paddle/fluid/operators/controlflow/recurrent_op_helper.h"
#include "paddle/fluid/operators/controlflow/while_op_helper.h"
#include "paddle/fluid/operators/distributed/distributed.h"
#include "paddle/fluid/platform/place.h"
Expand Down Expand Up @@ -410,6 +411,8 @@ void Executor::RunPreparedContext(ExecutorPrepareContext* ctx, Scope* scope,
if (gc && ctx->prog_.Size() > 1) {
operators::PrepareSafeEagerDeletionOnWhileOpAndWhileGradOp(ctx->block_id_,
ctx->ops_);
operators::PrepareSafeEagerDeletionOnRecurrentOpAndRecurrentGradOp(
ctx->block_id_, ctx->ops_);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
cc_library(op_graph_view SRCS op_graph_view.cc DEPS op_handle_base)
cc_library(while_op_eager_deletion_pass SRCS while_op_eager_deletion_pass.cc DEPS while_op_helper graph_helper pass computation_op_handle)
cc_library(recurrent_op_eager_deletion_pass SRCS recurrent_op_eager_deletion_pass.cc DEPS recurrent_op_helper graph_helper pass computation_op_handle)
cc_library(reference_count_pass_helper SRCS reference_count_pass_helper.cc DEPS garbage_collector computation_op_handle var_handle)
cc_library(reference_count_pass SRCS reference_count_pass.cc DEPS computation_op_handle graph graph_helper pass op_graph_view reference_count_pass_helper)

Expand All @@ -14,7 +15,8 @@ cc_library(inplace_op_pass SRCS inplace_op_pass.cc DEPS memory_optimize_pass op_

cc_test(memory_optimize_helper_test SRCS memory_optimize_helper_test.cc memory_optimize_helper.cc DEPS framework_proto graph graph_helper op_registry)

cc_library(eager_deletion_pass SRCS eager_deletion_pass.cc DEPS computation_op_handle eager_deletion_op_handle graph graph_helper pass while_op_eager_deletion_pass reference_count_pass_helper)
cc_library(eager_deletion_pass SRCS eager_deletion_pass.cc DEPS computation_op_handle
Copy link
Collaborator

@sneaxiy sneaxiy Jul 9, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add dependency of recurrent_op_eager_deletion_pass. What's more important, you should apply recurrent_op_eager_deletion_pass inside eager_deletion_pass. See here. Please add unittests using ParallelExecutor to verify it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

eager_deletion_op_handle graph graph_helper pass while_op_eager_deletion_pass recurrent_op_eager_deletion_pass reference_count_pass_helper)
cc_library(record_skip_memory_opt_vars_pass SRCS record_skip_memory_opt_vars_pass.cc DEPS graph graph_helper)

cc_library(memory_reuse_pass SRCS memory_reuse_pass.cc DEPS computation_op_handle reference_count_pass_helper share_tensor_buffer_op_handle multi_devices_helper graph pass)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,10 @@ void EagerDeletionPass::ApplyImpl(ir::Graph *graph) const {
auto while_op_eager_deletion_pass =
ir::PassRegistry::Instance().Get("while_op_eager_deletion_pass");
while_op_eager_deletion_pass->Apply(graph);

auto recurrent_op_eager_deletion_pass =
ir::PassRegistry::Instance().Get("recurrent_op_eager_deletion_pass");
recurrent_op_eager_deletion_pass->Apply(graph);
}

} // namespace ir
Expand All @@ -285,3 +289,4 @@ REGISTER_PASS(eager_deletion_pass, paddle::framework::ir::EagerDeletionPass)
.RequirePassAttr(paddle::framework::ir::kGarbageCollector);

USE_PASS(while_op_eager_deletion_pass);
USE_PASS(recurrent_op_eager_deletion_pass);
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// 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.

#include "paddle/fluid/framework/ir/memory_optimize_pass/recurrent_op_eager_deletion_pass.h"

#include <unordered_map>
#include <vector>

#include "paddle/fluid/framework/details/computation_op_handle.h"
#include "paddle/fluid/framework/details/multi_devices_helper.h"
#include "paddle/fluid/framework/ir/graph_helper.h"
#include "paddle/fluid/string/string_helper.h"

namespace paddle {
namespace framework {
namespace ir {

using paddle::operators::OpVariant;
using paddle::operators::OpVariantSet;
using paddle::operators::OpAndGradOpPair;

void RecurrentOpEagerDeletionPass::ApplyImpl(Graph *graph) const {
// Find all recurrent_op and recurrent_grad_op in graph
// Note the graph only contains ops and block 0
std::unordered_map<size_t, OpAndGradOpPair> target_ops =
DeviceIdToRecurrentAndRecurrentGradOp(*graph);

for (auto &entry : target_ops) {
// Prepare safe eager deletion on different devices because the garbage
// collection may be different across devices
OpAndGradOpPair &op_pair = entry.second;
PrepareSafeEagerDeletionOnRecurrentOpAndRecurrentGradOp(&op_pair);
}
}

// Returns a std::unordered_map mapping from the device id to recurrent op and
// grad op pair
std::unordered_map<size_t, OpAndGradOpPair>
RecurrentOpEagerDeletionPass::DeviceIdToRecurrentAndRecurrentGradOp(
const Graph &graph) const {
std::unordered_map<size_t, OpAndGradOpPair> ret;
std::vector<details::OpHandleBase *> all_ops =
FilterByNodeWrapper<details::OpHandleBase>(graph);

for (auto *op : all_ops) {
auto compute_op = dynamic_cast<details::ComputationOpHandle *>(op);
if (compute_op == nullptr) continue;

if (compute_op->Name() == "recurrent") {
// GetScopeIdx() returns device/place id
ret[compute_op->GetScopeIdx()].first.emplace(compute_op->GetOp());
} else if (compute_op->Name() == "recurrent_grad") {
// GetScopeIdx() returns device/place id
ret[compute_op->GetScopeIdx()].second.emplace(compute_op->GetOp());
}
}
return ret;
}

} // namespace ir
} // namespace framework
} // namespace paddle

REGISTER_PASS(recurrent_op_eager_deletion_pass,
paddle::framework::ir::RecurrentOpEagerDeletionPass);
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// 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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommend to remove this header file.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reply to you offline.


#include <unordered_map>

#include "paddle/fluid/framework/details/computation_op_handle.h"
#include "paddle/fluid/framework/details/multi_devices_helper.h"
#include "paddle/fluid/framework/ir/graph_helper.h"
#include "paddle/fluid/operators/controlflow/op_variant.h"
#include "paddle/fluid/operators/controlflow/recurrent_op_helper.h"

namespace paddle {
namespace framework {
namespace ir {

// Pass class set skip eager deletion vars for recurrent ops
class RecurrentOpEagerDeletionPass : public Pass {
protected:
void ApplyImpl(Graph *graph) const override;

private:
// Returns a std::unordered_map mapping from the device id to recurrent op and
// grad op pair
std::unordered_map<size_t, paddle::operators::OpAndGradOpPair>
DeviceIdToRecurrentAndRecurrentGradOp(const Graph &graph) const;
};

} // namespace ir
} // namespace framework
} // namespace paddle
4 changes: 3 additions & 1 deletion paddle/fluid/operators/controlflow/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
include(operators)
register_operators(DEPS naive_executor)
cc_library(while_op_helper SRCS while_op_helper.cc DEPS operator)
cc_library(op_variant SRCS op_variant.cc DEPS operator proto_desc)
cc_library(recurrent_op_helper SRCS recurrent_op_helper.cc DEPS operator op_variant recurrent_op)
cc_library(while_op_helper SRCS while_op_helper.cc DEPS operator op_variant)

file(APPEND ${pybind_file} "USE_OP(less_than);\nUSE_OP(logical_and);\nUSE_NO_KERNEL_OP(read_from_array);\n")
72 changes: 72 additions & 0 deletions paddle/fluid/operators/controlflow/op_variant.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// 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.

#include "paddle/fluid/operators/controlflow/op_variant.h"

namespace paddle {
namespace operators {

struct InputsVisitor
: public boost::static_visitor<const framework::VariableNameMap *> {
template <typename OpType>
const framework::VariableNameMap *operator()(const OpType *op) const {
return &(op->Inputs());
}
};

struct OutputsVisitor
: public boost::static_visitor<const framework::VariableNameMap *> {
template <typename OpType>
const framework::VariableNameMap *operator()(const OpType *op) const {
return &(op->Outputs());
}
};

struct AttributeMapVisitor
: public boost::static_visitor<const framework::AttributeMap *> {
const framework::AttributeMap *operator()(const framework::OpDesc *op) const {
return &(op->GetAttrMap());
}

const framework::AttributeMap *operator()(
const framework::OperatorBase *op) const {
return &(op->Attrs());
}
};

struct RawPointerVisitor : public boost::static_visitor<const void *> {
template <typename OpType>
const void *operator()(const OpType *op) const {
return op;
}
};

const framework::VariableNameMap &OpVariant::Inputs() const {
return *boost::apply_visitor(InputsVisitor(), op_);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about move InputsVisitor, OutputsVisitor, AttributeMapVisitor to this source file as well?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also move RawPointerVisitor to this source file.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}

const framework::VariableNameMap &OpVariant::Outputs() const {
return *boost::apply_visitor(OutputsVisitor(), op_);
}

const framework::AttributeMap &OpVariant::Attrs() const {
return *boost::apply_visitor(AttributeMapVisitor(), op_);
}

const void *OpVariant::RawPointer() const {
return boost::apply_visitor(RawPointerVisitor(), op_);
}

} // namespace operators
} // namespace paddle
69 changes: 69 additions & 0 deletions paddle/fluid/operators/controlflow/op_variant.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// 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 <string>

#include "paddle/fluid/framework/operator.h"
#include "paddle/fluid/framework/program_desc.h"
#include "paddle/fluid/platform/variant.h"

namespace paddle {
namespace operators {

// OpVariant is a wrapper class of OpDesc and OperatorBase pointer
// So that API would be the same.
class OpVariant {
public:
OpVariant(const framework::OperatorBase *op) : op_(op) {} // NOLINT

OpVariant(const framework::OpDesc *op) : op_(op) {} // NOLINT

const framework::VariableNameMap &Inputs() const;

const framework::VariableNameMap &Outputs() const;

const framework::AttributeMap &Attrs() const;

const void *RawPointer() const;

template <typename AttrType>
const AttrType &Attr(const std::string &name) const {
auto &attrs = Attrs();
auto it = attrs.find(name);
PADDLE_ENFORCE(it != attrs.end(), "Cannot find attribute %s", name);
return boost::get<AttrType>(it->second);
}

bool operator==(const OpVariant &other) const {
return RawPointer() == other.RawPointer();
}

int which() const { return static_cast<int>(op_.which()); }

struct Hasher {
size_t operator()(const OpVariant &op) const {
return reinterpret_cast<size_t>(op.RawPointer());
}
};

private:
const boost::variant<const framework::OperatorBase *,
const framework::OpDesc *>
op_;
};

} // namespace operators
} // namespace paddle
Loading