Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

optimize attr default value #33357

Merged
merged 18 commits into from
Jun 23, 2021
Merged

optimize attr default value #33357

merged 18 commits into from
Jun 23, 2021

Conversation

wanghuancoder
Copy link
Contributor

@wanghuancoder wanghuancoder commented Jun 4, 2021

PR types

Performance optimization

PR changes

Others

Describe

1. 背景

每个OP有很多的Attribute,这些Attribute在OP Maker中设置默认值和Checker。在上层使用时,通常只传递少部分Attribute,而更多的,需要靠Checker补填默认值。这部分逻辑在TypedAttrChecker中。
而Attribute的存储方式是using AttributeMap = std::unordered_map<std::string, Attribute>;,经测试发现,这种数据结构的补填、拷贝都非常慢。在动态图中,直接增加了框架的调度成本。

2. 内容

本PR优化Attribute补填默认值带来的性能开销。

主要方法是: 不再向上层传入的AttrsMap中补填默认值。而是在注册前向OP时生成DefaultAttrMap,DefaultAttrMap用于存储OP的默认值。在传递AttrsMap时,伴随传递DefaultAttrMap,在查询Attr时,先从AttrsMap中查找,再从DefaultAttrMap中查找。对于GradOP和DoubleGradOP,其Attr为前向OP的Attr,因此在执行dygraph_grad_op_maker_时,不仅传入AttrsMap,也传入DefaultAttrMap,最终存储在OPBase中。

3. 性能测试

使用core.ops.elementwise_add测试,本PR对core.ops.elementwise_add有18.93%的性能提升。

@paddle-bot-old
Copy link

paddle-bot-old bot commented Jun 4, 2021

Thanks for your contribution!
Please wait for the result of CI firstly. See Paddle CI Manual for details.

@@ -181,7 +181,8 @@ void Tracer::TraceOp(const std::string& type, const NameVarBaseMap& ins,
#endif
}

OpBase::Run(*op, new_ins, outs, attrs, place);
OpBase::Run(*op, new_ins, outs, attrs, attr_checker->GetAttrDefaultMap(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

attr_checker 需要判断是不是存在null的情况

Copy link
Contributor Author

Choose a reason for hiding this comment

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

已修改,感谢!

@paddle-bot-old
Copy link

Sorry to inform you that d44aeb6's CIs have passed for more than 7 days. To prevent PR conflicts, you need to re-run all CIs manually.

if (it == attrs_.end()) {
if (attrs_default_ != nullptr) {
it = attrs_default_->find(name);
if (it == attrs_default_->end()) {
Copy link
Collaborator

@phlrain phlrain Jun 18, 2021

Choose a reason for hiding this comment

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

bool found = false;

if ( it == attrs_ends() )
{
if (attrs_default_ != nullptr) {
it = attrs_default_->find(name);
if (it == attrs_default_->end())
{
found = false;
}
}

PADDLE_ENFORE( found == true, "")

platform::errors::InvalidArgument(
"Attribute (%s) is not set correctly.", attr_name_));
// default_value_setter_ has no more than one element
attr_map->emplace(attr_name_, default_value_setter_[0]());
Copy link
Collaborator

Choose a reason for hiding this comment

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

auto res = attr_map->emplace(attr_name_, default_value_setter_0);
it = res.first;

emplace 之后会返回一个pair, 这个pair的第一个元素是新的iterator

// default_value_setter_ has no more than one element
attr_map->emplace(attr_name_, default_value_setter_[0]());
}
it = attr_map->find(attr_name_);
Copy link
Collaborator

Choose a reason for hiding this comment

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

有了上面的操作后,这个find可以省略

@@ -93,6 +93,8 @@ void OpProtoAndCheckerMaker::operator()(proto::OpProto* proto,
AddAttr<std::string>(OpDeviceAttrName(), "Device type of this operator.")
.SetDefault("");
Validate();

op_checker_->InitDefaultMap();
Copy link
Collaborator

Choose a reason for hiding this comment

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

这个Init可以放在68行后面,后面这些信息动态图都是不需要的

@@ -108,7 +108,7 @@ class VarBase {

void ClearGradVarBase() { grad_var_ = nullptr; }

void SetGradVarBase(VarBase& grad_var) {
void SetGradVarBase(VarBase& grad_var) { // NOLINT
Copy link
Collaborator

Choose a reason for hiding this comment

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

why this line

Copy link
Contributor

Choose a reason for hiding this comment

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

使用const &或者*,避免NOLINT

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done,thx!

Copy link
Contributor

@chenwhql chenwhql left a comment

Choose a reason for hiding this comment

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

个人觉得,DefaultAttr相比AttrDefault更符合英语的修饰习惯

explicit AttrReader(const AttributeMap& attrs)
: attrs_(attrs), attrs_default_(nullptr) {}

AttrReader(const AttributeMap& attrs, const AttributeMap& attrs_default)
Copy link
Contributor

Choose a reason for hiding this comment

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

命名有些奇怪,建议attrs_default -> default_attrs

Copy link
Contributor

Choose a reason for hiding this comment

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

同感

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done,thx!

@@ -410,15 +435,26 @@ class OpAttrChecker {
explicit_checker_num_ = attr_checkers_.size();
}

void InitDefaultMap() {
Copy link
Contributor

Choose a reason for hiding this comment

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

InitDefaultMap意义不明,InitDefaultMap -> InitDefaultAttributeMap

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done,thx!

@@ -410,15 +435,26 @@ class OpAttrChecker {
explicit_checker_num_ = attr_checkers_.size();
}

void InitDefaultMap() {
for (const auto& checker : attr_checkers_) {
checker(&attrs_default_, true, false);
Copy link
Contributor

Choose a reason for hiding this comment

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

attrs_default_ -> default_attrs_

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done,thx!

}
}

const AttributeMap& GetAttrDefaultMap() const { return attrs_default_; }
Copy link
Contributor

Choose a reason for hiding this comment

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

GetAttrDefaultMap -> GetDefaultAttrMap

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done,thx!

@@ -113,9 +113,18 @@ class GradOpBaseMakerBase {
return vec_temp;
}

// Only for dygraph
void SetDygraphAttrsDefaultMap(const framework::AttributeMap& attrs_default) {
Copy link
Contributor

Choose a reason for hiding this comment

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

SetDygraphAttrsDefaultMap -> SetDygraphDefaultAttrsMap

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done,thx!

it = attrs_default_.find(name);
if (it == attrs_default_.end()) {
PADDLE_THROW(
platform::errors::NotFound("Can not find [%s] in attrs", name));
Copy link
Contributor

Choose a reason for hiding this comment

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

同上

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done,thx!

@@ -108,7 +108,7 @@ class VarBase {

void ClearGradVarBase() { grad_var_ = nullptr; }

void SetGradVarBase(VarBase& grad_var) {
void SetGradVarBase(VarBase& grad_var) { // NOLINT
Copy link
Contributor

Choose a reason for hiding this comment

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

使用const &或者*,避免NOLINT

ExtractAttribute<T> extract_attr(name);
T* attr_value = extract_attr(attr);
return *attr_value;
}

private:
const AttributeMap& attrs_;
const AttributeMap* attrs_default_;
Copy link
Contributor

Choose a reason for hiding this comment

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

为什么不同样使用const &类型,这里有什么考虑吗

Copy link
Contributor

Choose a reason for hiding this comment

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

同感

Copy link
Contributor Author

@wanghuancoder wanghuancoder Jun 21, 2021

Choose a reason for hiding this comment

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

引用必须在构造函数的时候初始化。考虑到动态图静态图都使用AttrReader他的构造函数有2种:
AttrReader(const AttributeMap& attrs)
: attrs_(attrs), default_attrs_(nullptr) {}

AttrReader(const AttributeMap& attrs, const AttributeMap& default_attrs)
: attrs_(attrs), default_attrs_(&default_attrs) {}

@@ -154,9 +154,14 @@ void Tracer::TraceOp(const std::string& type, const NameVarBaseMap& ins,
const auto& op_info = op->Info();
auto* attr_checker = op_info.Checker();
if (attr_checker) {
attr_checker->Check(&attrs, true);
attr_checker->Check(&attrs, true, true);
Copy link
Contributor

Choose a reason for hiding this comment

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

建议这里加上参数名注释,方便找到是这里调用的,attr_checker->Check(&attrs, true, /*without_default_value=*/true);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done,thx!

void operator()(AttributeMap* attr_map,
bool get_default_value_only = false) const {
void operator()(AttributeMap* attr_map, bool get_default_value_only = false,
bool without_default_value = false) const {
Copy link
Contributor

Choose a reason for hiding this comment

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

without_default_value这个参数的命名理解起来比较困难,是不是改成only_check_exist_value之类的比较容易理解

Copy link
Contributor

Choose a reason for hiding this comment

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

without_default_value 让人有点儿容易和get_default_value_only 的作用混淆....

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done,thx!

Copy link
Contributor

@JiabinYang JiabinYang left a comment

Choose a reason for hiding this comment

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

some comments

explicit AttrReader(const AttributeMap& attrs)
: attrs_(attrs), attrs_default_(nullptr) {}

AttrReader(const AttributeMap& attrs, const AttributeMap& attrs_default)
Copy link
Contributor

Choose a reason for hiding this comment

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

同感

PADDLE_ENFORCE_NE(attrs_.count(name), 0,
auto it = attrs_.find(name);
bool found = it != attrs_.end();
if (it == attrs_.end()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

why not use found instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done,thx!

ExtractAttribute<T> extract_attr(name);
T* attr_value = extract_attr(attr);
return *attr_value;
}

private:
const AttributeMap& attrs_;
const AttributeMap* attrs_default_;
Copy link
Contributor

Choose a reason for hiding this comment

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

同感

void operator()(AttributeMap* attr_map,
bool get_default_value_only = false) const {
void operator()(AttributeMap* attr_map, bool get_default_value_only = false,
bool without_default_value = false) const {
Copy link
Contributor

Choose a reason for hiding this comment

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

without_default_value 让人有点儿容易和get_default_value_only 的作用混淆....

chenwhql
chenwhql previously approved these changes Jun 21, 2021
Copy link
Contributor

@chenwhql chenwhql left a comment

Choose a reason for hiding this comment

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

LGTM

@phlrain phlrain self-requested a review June 21, 2021 12:21
phlrain
phlrain previously approved these changes Jun 21, 2021
JiabinYang
JiabinYang previously approved these changes Jun 22, 2021
Copy link
Contributor

@JiabinYang JiabinYang left a comment

Choose a reason for hiding this comment

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

LGTM

auto checker_num = attr_checkers_.size();
if (explicit_only) checker_num = explicit_checker_num_;
for (size_t i = 0; i < checker_num; ++i) {
attr_checkers_[i](attr_map, false);
attr_checkers_[i](attr_map, false, only_check_exist_value);
}
}

AttributeMap GetAttrsDefaultValuesMap() const {
Copy link
Collaborator

Choose a reason for hiding this comment

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

GetDefaultAttrsValuesMap()?

@@ -228,6 +241,7 @@ class SingleGradOpMaker<imperative::OpBase>
{
imperative::TracedGradOp traced_grad_op(node);
try {
traced_grad_op.SetAttrDefaultMap(this->DefaultAttrsMap());
Copy link
Collaborator

Choose a reason for hiding this comment

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

SetDefaultAttrMap?

@@ -285,6 +295,10 @@ class TracedGradOp {
return op_->SetAttrMap(attrs);
}

void SetAttrDefaultMap(const framework::AttributeMap& attrs) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

SetDefaultAttrMap?

@@ -35,10 +35,12 @@ class DygraphInferShapeContext : public framework::InferShapeContext {
DygraphInferShapeContext(const NameVarMap<VarType>* in,
const NameVarMap<VarType>* out,
const framework::AttributeMap* attr,
const framework::AttributeMap* attr_default,
Copy link
Collaborator

Choose a reason for hiding this comment

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

@wanghuancoder wanghuancoder dismissed stale reviews from JiabinYang, phlrain, and chenwhql via 806564c June 23, 2021 01:25
Copy link
Contributor

@JiabinYang JiabinYang left a comment

Choose a reason for hiding this comment

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

LGTM

@phlrain phlrain self-requested a review June 23, 2021 08:07
Copy link
Collaborator

@raindrops2sea raindrops2sea left a comment

Choose a reason for hiding this comment

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

LGTM

@wanghuancoder wanghuancoder merged commit 5d2eb67 into PaddlePaddle:develop Jun 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants