Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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 benchmark/fluid/mnist.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import argparse
import time

import paddle.v2 as paddle
import paddle
import paddle.fluid as fluid
import paddle.fluid.profiler as profiler

Expand Down
2 changes: 1 addition & 1 deletion paddle/fluid/framework/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ cc_test(variable_test SRCS variable_test.cc)
cc_library(threadpool SRCS threadpool.cc DEPS enforce)
cc_test(threadpool_test SRCS threadpool_test.cc DEPS threadpool)

cc_library(scope SRCS scope.cc DEPS glog threadpool)
cc_library(scope SRCS scope.cc DEPS glog threadpool profiler)
cc_test(scope_test SRCS scope_test.cc DEPS scope)

cc_library(data_device_transform SRCS data_device_transform.cc DEPS tensor)
Expand Down
30 changes: 30 additions & 0 deletions paddle/fluid/framework/details/var_handle.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#pragma once
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>

Expand Down Expand Up @@ -73,6 +74,35 @@ struct DummyVarHandle : public VarHandleBase {
std::string DebugString() const override;
};

// a runtime unique variable identity.
struct VarUUID {
explicit VarUUID(const std::string& name) : name(name) {
std::hash<std::string> hasher;
unique_id = hasher(name);
}
VarUUID(const std::string& name, int id) : name(name), unique_id(id) {}
bool operator==(const VarUUID& rhs) const {
return unique_id == rhs.unique_id;
}
bool operator!=(const VarUUID& rhs) const {
return unique_id != rhs.unique_id;
}
std::string name;
int unique_id; /*default -1 if uninitialized*/
};

struct VarUUIDHash {
size_t operator()(const VarUUID& id) const { return id.unique_id; }
};

inline std::ostream& operator<<(std::ostream& os, const VarUUID& var) {
os << var.name;
if (VLOG_IS_ON(5)) {
os << "[" << var.unique_id << "]";
}
return os;
}

} // namespace details
} // namespace framework
} // namespace paddle
39 changes: 27 additions & 12 deletions paddle/fluid/framework/scope.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ limitations under the License. */
#include "paddle/fluid/framework/scope.h"

#include <memory> // for unique_ptr
#include <set>
#include <unordered_set>
#include "glog/logging.h"
#include "paddle/fluid/framework/threadpool.h"
#include "paddle/fluid/platform/profiler.h"
#include "paddle/fluid/string/printf.h"

DEFINE_bool(benchmark, false,
Expand Down Expand Up @@ -48,13 +49,15 @@ Scope& Scope::NewScope() const {
return *kids_.back();
}

Variable* Scope::Var(const std::string& name) {
Variable* Scope::Var(const std::string& name) { return Var(VarUUID(name)); }

Variable* Scope::Var(const VarUUID& name) {
auto* v = FindVarLocally(name);
if (v != nullptr) return v;
v = new Variable();
vars_[name] = v;
vars_[VarUUID(name)] = v;
VLOG(3) << "Create variable " << name;
v->name_ = &(vars_.find(name)->first);
v->name_ = &(vars_.find(name)->first.name);
return v;
}

Expand All @@ -67,6 +70,11 @@ Variable* Scope::Var(std::string* name) {
}

Variable* Scope::FindVar(const std::string& name) const {
return FindVar(VarUUID(name));
}

Variable* Scope::FindVar(const VarUUID& name) const {
platform::RecordEvent event("Scope");
auto var = FindVarLocally(name);
if (var != nullptr) {
return var;
Expand All @@ -91,26 +99,27 @@ std::vector<std::string> Scope::LocalVarNames() const {
std::vector<std::string> known_vars;
known_vars.reserve(this->vars_.size());
for (auto& p : vars_) {
known_vars.emplace_back(p.first);
known_vars.emplace_back(p.first.name);
}
return known_vars;
}

void Scope::DeleteScope(Scope* scope) const {
void Scope::DeleteScope(Scope* scope) {
std::unique_lock<std::mutex> lock(mutex_);
auto it = std::find(this->kids_.begin(), this->kids_.end(), scope);
PADDLE_ENFORCE(it != this->kids_.end(), "Cannot find %p as kid scope", scope);
this->kids_.erase(it);
// When making memory benchmark on Fluid, we have to delete scope sync.
if (FLAGS_benchmark || FLAGS_eager_delete_scope) {
if (FLAGS_benchmark) {
delete scope;
} else {
Async([scope] { delete scope; });
}
}

void Scope::EraseVars(const std::vector<std::string>& var_names) {
std::set<std::string> var_set(var_names.begin(), var_names.end());
void Scope::EraseVars(const std::vector<VarUUID>& var_names) {
std::unordered_set<VarUUID, VarUUIDHash> var_set(var_names.begin(),
var_names.end());
for (auto it = vars_.begin(); it != vars_.end();) {
if (var_set.find(it->first) != var_set.end()) {
delete it->second;
Expand All @@ -123,13 +132,14 @@ void Scope::EraseVars(const std::vector<std::string>& var_names) {

void Scope::Rename(const std::string& origin_name,
const std::string& new_name) const {
auto origin_it = vars_.find(origin_name);
auto origin_it = vars_.find(VarUUID(origin_name));
PADDLE_ENFORCE(origin_it != vars_.end(),
"Cannot find original variable with name %s", origin_name);
auto new_it = vars_.find(new_name);
VarUUID new_var = VarUUID(new_name);
auto new_it = vars_.find(new_var);
PADDLE_ENFORCE(new_it == vars_.end(),
"The variable with name %s is already in the scope", new_name);
vars_[new_name] = origin_it->second;
vars_[new_var] = origin_it->second;
vars_.erase(origin_it);
}

Expand All @@ -140,6 +150,11 @@ std::string Scope::Rename(const std::string& origin_name) const {
}

Variable* Scope::FindVarLocally(const std::string& name) const {
return FindVarLocally(name);
}

Variable* Scope::FindVarLocally(const VarUUID& name) const {
platform::RecordEvent event("Scope");
auto it = vars_.find(name);
if (it != vars_.end()) return it->second;
return nullptr;
Expand Down
11 changes: 8 additions & 3 deletions paddle/fluid/framework/scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,23 +47,26 @@ class Scope {
Scope& NewScope() const;

/// Create a variable with given name if it doesn't exist.
Variable* Var(const VarUUID& id);
Variable* Var(const std::string& name);

/// Create a variable with a scope-unique name.
Variable* Var(std::string* name = nullptr);

void EraseVars(const std::vector<std::string>& var_names);
/// EraseVars in scope.
void EraseVars(const std::vector<VarUUID>& var_names);

/// Find a variable in the scope or any of its ancestors. Returns
/// nullptr if cannot find.
Variable* FindVar(const VarUUID& name) const;
Variable* FindVar(const std::string& name) const;

const Scope* parent() const { return parent_; }

/// Find the scope or an ancestor scope that contains the given variable.
const Scope* FindScope(const Variable* var) const;

void DeleteScope(Scope* scope) const;
void DeleteScope(Scope* scope);

/// Drop all kids scopes belonged to this scope.
void DropKids();
Expand All @@ -78,13 +81,15 @@ class Scope {
// Rename variable to a new name and return the new name
std::string Rename(const std::string& origin_name) const;

Variable* FindVarLocally(const VarUUID& id) const;
Variable* FindVarLocally(const std::string& name) const;

private:
// Call Scope::NewScope for a sub-scope.
explicit Scope(Scope const* parent) : parent_(parent) {}

mutable std::unordered_map<std::string, Variable*> vars_;
mutable std::unordered_map<VarUUID, Variable*, VarUUIDHash> vars_;

mutable std::list<Scope*> kids_;
Scope const* parent_{nullptr};

Expand Down
25 changes: 13 additions & 12 deletions paddle/fluid/framework/scope_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,47 +18,48 @@ limitations under the License. */

using paddle::framework::Scope;
using paddle::framework::Variable;
using paddle::framework::VarUUID;

TEST(Scope, VarsShadowing) {
Scope s;
Scope& ss1 = s.NewScope();
Scope& ss2 = s.NewScope();

Variable* v0 = s.Var("a");
Variable* v1 = ss1.Var("a");
Variable* v0 = s.Var(VarUUID("a"));
Variable* v1 = ss1.Var(VarUUID("a"));

EXPECT_NE(v0, v1);

EXPECT_EQ(v0, s.FindVar("a"));
EXPECT_EQ(v1, ss1.FindVar("a"));
EXPECT_EQ(v0, ss2.FindVar("a"));
EXPECT_EQ(v0, s.FindVar(VarUUID("a")));
EXPECT_EQ(v1, ss1.FindVar(VarUUID("a")));
EXPECT_EQ(v0, ss2.FindVar(VarUUID("a")));
}

TEST(Scope, FindVar) {
Scope s;
Scope& ss = s.NewScope();

EXPECT_EQ(nullptr, s.FindVar("a"));
EXPECT_EQ(nullptr, ss.FindVar("a"));
EXPECT_EQ(nullptr, s.FindVar(VarUUID("a")));
EXPECT_EQ(nullptr, ss.FindVar(VarUUID("a")));

ss.Var("a");
ss.Var(VarUUID("a"));

EXPECT_EQ(nullptr, s.FindVar("a"));
EXPECT_NE(nullptr, ss.FindVar("a"));
EXPECT_EQ(nullptr, s.FindVar(VarUUID("a")));
EXPECT_NE(nullptr, ss.FindVar(VarUUID("a")));
}

TEST(Scope, FindScope) {
Scope s;
Scope& ss = s.NewScope();
Variable* v = s.Var("a");
Variable* v = s.Var(VarUUID("a"));

EXPECT_EQ(&s, s.FindScope(v));
EXPECT_EQ(&s, ss.FindScope(v));
}

TEST(Scope, GetAllNames) {
Scope s;
Variable* v = s.Var("a");
Variable* v = s.Var(VarUUID("a"));
EXPECT_EQ(&s, s.FindScope(v));

std::vector<std::string> ans = s.LocalVarNames();
Expand Down
4 changes: 4 additions & 0 deletions paddle/fluid/framework/variable.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <typeindex>
#include <typeinfo>

#include "paddle/fluid/framework/details/var_handle.h"
#include "paddle/fluid/platform/enforce.h"

namespace paddle {
Expand Down Expand Up @@ -92,5 +93,8 @@ class Variable {
const std::string* name_;
};

using details::VarUUID;
using details::VarUUIDHash;

} // namespace framework
} // namespace paddle
9 changes: 8 additions & 1 deletion paddle/fluid/operators/delete_var_op.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ 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/details/var_handle.h"
#include "paddle/fluid/framework/op_registry.h"
#include "paddle/fluid/framework/operator.h"

namespace paddle {
namespace operators {
using framework::details::VarUUID;

class DeleteVarOp : public framework::OperatorBase {
public:
DeleteVarOp(const std::string &type, const framework::VariableNameMap &inputs,
Expand All @@ -28,7 +31,11 @@ class DeleteVarOp : public framework::OperatorBase {
dev_ctx.Wait();

auto delete_var_names = Inputs("X");
const_cast<framework::Scope &>(scope).EraseVars(delete_var_names);
std::vector<VarUUID> delete_var_ids;
for (auto &var : delete_var_names) {
delete_var_ids.push_back(VarUUID(var));
}
const_cast<framework::Scope &>(scope).EraseVars(delete_var_ids);
}
};

Expand Down
9 changes: 9 additions & 0 deletions paddle/fluid/platform/profiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,15 @@ RecordEvent::RecordEvent(const std::string& name, const DeviceContext* dev_ctx)
SetCurAnnotation(name_);
}

RecordEvent::RecordEvent(const std::string& name) : start_ns_(PosixInNsec()) {
if (g_state == ProfilerState::kDisabled) return;
platform::CPUPlace place;
dev_ctx_ = DeviceContextPool::Instance().Get(place);
name_ = name;
PushEvent(name_, dev_ctx_);
SetCurAnnotation(name_);
}

RecordEvent::~RecordEvent() {
if (g_state == ProfilerState::kDisabled) return;
DeviceTracer* tracer = GetDeviceTracer();
Expand Down
2 changes: 2 additions & 0 deletions paddle/fluid/platform/profiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ void PushEvent(const std::string& name, const DeviceContext* dev_ctx);
void PopEvent(const std::string& name, const DeviceContext* dev_ctx);

struct RecordEvent {
explicit RecordEvent(const std::string& name);

RecordEvent(const std::string& name, const DeviceContext* dev_ctx);

~RecordEvent();
Expand Down
8 changes: 6 additions & 2 deletions paddle/fluid/pybind/pybind.cc
Original file line number Diff line number Diff line change
Expand Up @@ -250,10 +250,14 @@ All parameter, weight, gradient are variables in Paddle.
py::class_<Scope>(m, "Scope", "")
.def("var",
[](Scope &self, const std::string &name) -> Variable * {
return self.Var(name);
return self.Var(VarUUID(name));
},
py::return_value_policy::reference)
.def("find_var",
[](Scope &self, const std::string &name) -> Variable * {
return self.FindVar(VarUUID(name));
},
py::return_value_policy::reference)
.def("find_var", &Scope::FindVar, py::return_value_policy::reference)
.def(py::init<>())
.def("new_scope", [](Scope &self) -> Scope * { return &self.NewScope(); },
py::return_value_policy::reference)
Expand Down