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

[Refactor] Enforce attaching storage scope to PointerType #8366

Merged
merged 92 commits into from
Jul 13, 2021

Conversation

masahi
Copy link
Member

@masahi masahi commented Jun 29, 2021

Right now, storage scope information is scattered across different places. This PR proposes to make storage_scope in PointerType, introduced in #8017, be the single source of truth. This enables each Allocate, Store, Load nodes to directly access its storage scope through its associated buffer variable, rather than via attr::stroage_scope + a map between Var and storage scope as currently done today (for example,

std::unordered_map<const VarNode*, StorageScope> storage_scope_;
).

The main changes are:

  • In schedule_ops.cc, attach storage scope information to ProduceRealizeNode, rather than creating AttrStmt with tir::attr::realize_scope scope.
  • In schedule_postproc_to_primfunc.cc, always create a new Buffer using storage scope information in ProduceRealizeNode. This ensures that PointerType associated with the new buffer has always storage scope information attached.
  • In transform passes and codegen classes, try to use storage scope information in AllocateNode directly, and remove attr::storage_scope and attr::realize_scope when they are no longer needed.

Building on this PR, I'll send the following changes later:

  • Introduce a new storage scope of dynamic shared memory
  • Remove remaining use of attr::storage_scope
  • Remove storage scope in Buffer class
    /*! \brief storage scope of the buffer, if other than global */
    String scope;

@masahi masahi marked this pull request as draft June 29, 2021 10:54
@masahi masahi force-pushed the storage_scope_refactor branch 3 times, most recently from 0c9a912 to 79c6e8e Compare June 29, 2021 20:24
@tqchen tqchen self-assigned this Jun 30, 2021
@tqchen
Copy link
Member

tqchen commented Jun 30, 2021

Thanks @masahi . seems there are still testcases that we need to fix

@masahi
Copy link
Member Author

masahi commented Jul 1, 2021

@tqchen I've hit an issue in lower_thread_allreduce.cc. There are multiple uses of AttrStmt where a storage scope of a buffer variable is assigned after some complicated logic, like this:

stmt = AttrStmt(repl->buffer_var, attr::storage_scope, StringImm("shared"), stmt);

So I tried to replace this line by something like SetStorageScope(repl->buffer_var, "shared") but this doesn't work because I cannot get a mutable pointer to PointerType via buffer_var->type_annotation.as<PointerTypeNode>().

Creating a new variable also doesn't work because the old buffer_var is shared with other stmt nodes, so updating the buffer_var of AllocateNode results in the use of undefined variable in other nodes.

What should we do about this?

@tqchen
Copy link
Member

tqchen commented Jul 1, 2021

In this particular case, we might need to create a new buffer var and remap the use of the old buffer vars to new one

@masahi masahi force-pushed the storage_scope_refactor branch 4 times, most recently from 553402d to 73c6496 Compare July 5, 2021 10:17
Jenkinsfile Outdated Show resolved Hide resolved
src/target/llvm/codegen_llvm.cc Show resolved Hide resolved
src/tir/ir/buffer.cc Outdated Show resolved Hide resolved
src/tir/ir/buffer.cc Outdated Show resolved Hide resolved
@masahi masahi force-pushed the storage_scope_refactor branch 2 times, most recently from 9f37d55 to ba670d3 Compare July 7, 2021 00:37
@masahi masahi force-pushed the storage_scope_refactor branch from 426b573 to cb697d8 Compare July 7, 2021 22:04
@masahi
Copy link
Member Author

masahi commented Jul 7, 2021

Should we remove scope from Buffer? The scope is now available from the type annotation of the data member in BufferNode.

Yes this is one of my follow-up items. Apparently scope in Buffer is only used by TensorIR related code.

namespace tvm {
namespace tir {

class UpdatePointerStorageScope : public StmtExprMutator {
Copy link
Member Author

Choose a reason for hiding this comment

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

This is used by passes that require modifying storage scopes after buffer creation. Currently used by lower_thread_allreduce.cc and lower_warp_memory.cc.

@@ -491,6 +491,22 @@ def var(dtype, span):
super().__init__(var, def_symbol=True)


@register
class BufferVarDef(SpecialStmt):
Copy link
Member Author

Choose a reason for hiding this comment

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

cc @spectrometerHBH for tvmscript changes. This is for distinguishing a normal variable from a buffer variable. The latter one requires storage scope. See the change in test_tvmscript_roundtrip.py. The tvm script printer was also updated.

@masahi
Copy link
Member Author

masahi commented Jul 8, 2021

All tests passed, ready for review.

src/tir/transforms/update_pointer_storage_scope.cc Outdated Show resolved Hide resolved
src/runtime/thread_storage_scope.h Outdated Show resolved Hide resolved
src/tir/transforms/update_pointer_storage_scope.cc Outdated Show resolved Hide resolved
src/te/operation/cross_thread_reduction.cc Outdated Show resolved Hide resolved
@@ -177,7 +178,8 @@ Stmt MakeCrossThreadReduction(const ComputeOpNode* self, const Stage& stage,
std::vector<Var> res_handles(size);
for (size_t idx = 0; idx < size; ++idx) {
DataType dtype = reduces[idx]->dtype;
res_handles[idx] = Var("reduce_temp" + std::to_string(idx), PointerType(PrimType(dtype)));
res_handles[idx] =
Copy link
Member

Choose a reason for hiding this comment

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

shall we remove storage_scope attr here

body = AttrStmt(res_handles[idx - 1], tir::attr::storage_scope, StringImm("local"), body);

AttrStmt(normal_res_handles[idx - 1], tir::attr::storage_scope, StringImm("local"), body);

Copy link
Member Author

Choose a reason for hiding this comment

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

Removal of AttrStmt creation with attr::storage_scope will come after this PR, where all attr::storage_scope usages will be removed at once. A lot of places in the code base still assume the existence of AttrStmt with attr::storage_scope, so I don't want to remove some AttrStmt while leaving others in this PR.


namespace tvm {
namespace tir {

class UpdatePointerStorageScopeAllReduce final : public UpdatePointerStorageScope {
Copy link
Member

Choose a reason for hiding this comment

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

Can we merge this pass with UpdatePointerStorageScope by adding check for attr::volatile_scope in VisitStmt_(const AttrStmtNode*)

Copy link
Member Author

Choose a reason for hiding this comment

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

This attr::volatile_scope is created inside this AllocateNode visitor. A visitor for AttrStmtNode don't get to see this.

Copy link
Contributor

@kparzysz-quic kparzysz-quic left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@csullivan csullivan left a comment

Choose a reason for hiding this comment

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

@masahi Thanks for the great and healthy refactor!

@@ -0,0 +1,91 @@
/*
Copy link
Contributor

@csullivan csullivan Jul 12, 2021

Choose a reason for hiding this comment

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

I think we need to also update lower_device_storage_access_info.cc to use the PointerType storage scope in this PR as well.

With a custom storage scope used in a cache_read stage, e.g.

s.cache_read(data, "global.texture", [OL])

I see that lower_device_storage_access_info.cc#L72 is unhappy with the scope tag.

  Check failed: (e.info.defined()) is false: Cannot find memory info of global.texture

and this ICHECK failure does not occur on main.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm interesting. attr::storage_scope and the PointerType should have the same storage scope, by the invariant at

tvm/src/tir/ir/stmt.cc

Lines 64 to 73 in 3e5e0ef

if (attr_key == attr::storage_scope) {
const VarNode* buf = node.as<VarNode>();
ICHECK(buf);
const auto* ptr_type = buf->type_annotation.as<PointerTypeNode>();
ICHECK(ptr_type) << "The provided variable is not of pointer type";
auto attr_scope = value.as<StringImmNode>()->value;
ICHECK_EQ(attr_scope, ptr_type->storage_scope)
<< "Storage scopes attached to AttrStmt and buffer var are different. " << attr_scope
<< ", " << ptr_type->storage_scope;
}
.

A possible explanation is that the value of scope.tag.length() at https://github.com/apache/tvm/blob/main/src/tir/transforms/lower_device_storage_access_info.cc#L70 is different between main and this branch. In this case, GetMemoryInfo assumes that a packed function tvm.info.mem.global.texture is defined, but I don't find it anywhere.

Do you have a repro script?

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks @masahi. I tracked this issue down to the buffer storage scope being set to global and removing the scope tag. Previously this was fine as the AttrStmtNode realize_scope annotation was used during texture lowering.

This demonstrate the value in removing the buffer storage scope in favor of consolidating around the PointerType's storage_scope. I look forward to that PR! Thanks again for this change.

@tqchen tqchen removed their assignment Jul 12, 2021
@tqchen
Copy link
Member

tqchen commented Jul 12, 2021

will let @vinx13 manage this PR

Copy link
Contributor

@csullivan csullivan left a comment

Choose a reason for hiding this comment

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

LGTM

@vinx13 vinx13 merged commit 1a26733 into apache:main Jul 13, 2021
@vinx13
Copy link
Member

vinx13 commented Jul 13, 2021

Thanks @masahi @kparzysz-quic @csullivan @tqchen this is merged

ylc pushed a commit to ylc/tvm that referenced this pull request Sep 29, 2021
* Add storage scope to ProducerRealize, always create a buffer with scope

* update schedule_ops.cc

* update schedule_postproc_to_primfunc.cc

* restore more realize_scope

This reverts commit b66c3ba.

* make the default scope be "" instead of None in ir builder

* restore realize_scope visit in storage_flatten.cc

* update storage_access.cc

* make sure buffer var is of PointerType in ir builder

This reverts commit e650b6c.

* enforce default storage scope of global

* added remap pass but does not work yet

* fixed all reduce issue

This reverts commit 8e20003.

* simplify

* trying mitigation for aot test

* merge remaining changes from initial branch

* remove use of attr::storage_scope from codegen

* restore a visit to AttrStmt with attr::storage_scope in storage_rewrite

* disable check

* lint fix

* revert default scope to ""

* format

* fix volatile access to shared mem in lower all reduce

* fixed gpu coorporative load/store test

* pass storage scope to PointerType in tvm script parser

This reverts commit 99cfb9d18781dcfdea169d920450f9063ab18b6b.

* fixed tvmscript roundtrip test

* fixed tir flatten buffer test

* fixed test_tir_transform_hoist_if.py

* use storage scope global by default in aot_executor_codegen.cc

* add missing default storage scope in create_primfunc.cc

* restore StorageInfo struct in llvm backend

* UpdateStorageScope -> WithStorageScope

* fixed lower warp memory test

* GetStorageScope -> GetPtrStorageScope

* Enable storage scope invariant check in AttrStmt constructor

* remove GetPtrStorageScope and WithStorageScope from public header

* move RemapStorageScope to its own file

* add more method to RemapStorageScope

* update lower_thread_allreduce to use RemapStorageScope

* RemapStorageScope -> UpdatePointerStorageScope

* remove realize_scope from hybrid script

* removed realize_scope in schedule_ops

* remove realize_scope from schedule_postproc_to_primfunc

* remove remaining realize_scope usage from schedule_ops.cc

* remove realize_scope usage from storage_flatten.cc

* fixed test_tir_transform_lower_warp_memory.py following realize_scope removal

* Add storage scope to ProducerRealize, always create a buffer with scope

* update schedule_ops.cc

* update schedule_postproc_to_primfunc.cc

* restore more realize_scope

This reverts commit b66c3ba.

* make the default scope be "" instead of None in ir builder

* restore realize_scope visit in storage_flatten.cc

* update storage_access.cc

* make sure buffer var is of PointerType in ir builder

This reverts commit e650b6c.

* enforce default storage scope of global

* added remap pass but does not work yet

* fixed all reduce issue

This reverts commit 8e20003.

* simplify

* trying mitigation for aot test

* merge remaining changes from initial branch

* remove use of attr::storage_scope from codegen

* restore a visit to AttrStmt with attr::storage_scope in storage_rewrite

* disable check

* lint fix

* revert default scope to ""

* format

* fix volatile access to shared mem in lower all reduce

* fixed gpu coorporative load/store test

* pass storage scope to PointerType in tvm script parser

This reverts commit 99cfb9d18781dcfdea169d920450f9063ab18b6b.

* fixed tvmscript roundtrip test

* fixed tir flatten buffer test

* fixed test_tir_transform_hoist_if.py

* use storage scope global by default in aot_executor_codegen.cc

* add missing default storage scope in create_primfunc.cc

* restore StorageInfo struct in llvm backend

* UpdateStorageScope -> WithStorageScope

* fixed lower warp memory test

* GetStorageScope -> GetPtrStorageScope

* Enable storage scope invariant check in AttrStmt constructor

* remove GetPtrStorageScope and WithStorageScope from public header

* move RemapStorageScope to its own file

* add more method to RemapStorageScope

* update lower_thread_allreduce to use RemapStorageScope

* RemapStorageScope -> UpdatePointerStorageScope

* remove realize_scope from hybrid script

* removed realize_scope in schedule_ops

* remove realize_scope from schedule_postproc_to_primfunc

* remove remaining realize_scope usage from schedule_ops.cc

* remove realize_scope usage from storage_flatten.cc

* fixed test_tir_transform_lower_warp_memory.py following realize_scope removal

* Address comments

* Remove blank line diff

Co-authored-by: Masahiro Masuda <masahi@[email protected]>
Co-authored-by: masa <[email protected]>
zxy844288792 pushed a commit to zxy844288792/tvm that referenced this pull request Mar 4, 2022
* Add storage scope to ProducerRealize, always create a buffer with scope

* update schedule_ops.cc

* update schedule_postproc_to_primfunc.cc

* restore more realize_scope

This reverts commit b66c3ba.

* make the default scope be "" instead of None in ir builder

* restore realize_scope visit in storage_flatten.cc

* update storage_access.cc

* make sure buffer var is of PointerType in ir builder

This reverts commit e650b6c.

* enforce default storage scope of global

* added remap pass but does not work yet

* fixed all reduce issue

This reverts commit 8e20003.

* simplify

* trying mitigation for aot test

* merge remaining changes from initial branch

* remove use of attr::storage_scope from codegen

* restore a visit to AttrStmt with attr::storage_scope in storage_rewrite

* disable check

* lint fix

* revert default scope to ""

* format

* fix volatile access to shared mem in lower all reduce

* fixed gpu coorporative load/store test

* pass storage scope to PointerType in tvm script parser

This reverts commit 99cfb9d18781dcfdea169d920450f9063ab18b6b.

* fixed tvmscript roundtrip test

* fixed tir flatten buffer test

* fixed test_tir_transform_hoist_if.py

* use storage scope global by default in aot_executor_codegen.cc

* add missing default storage scope in create_primfunc.cc

* restore StorageInfo struct in llvm backend

* UpdateStorageScope -> WithStorageScope

* fixed lower warp memory test

* GetStorageScope -> GetPtrStorageScope

* Enable storage scope invariant check in AttrStmt constructor

* remove GetPtrStorageScope and WithStorageScope from public header

* move RemapStorageScope to its own file

* add more method to RemapStorageScope

* update lower_thread_allreduce to use RemapStorageScope

* RemapStorageScope -> UpdatePointerStorageScope

* remove realize_scope from hybrid script

* removed realize_scope in schedule_ops

* remove realize_scope from schedule_postproc_to_primfunc

* remove remaining realize_scope usage from schedule_ops.cc

* remove realize_scope usage from storage_flatten.cc

* fixed test_tir_transform_lower_warp_memory.py following realize_scope removal

* Add storage scope to ProducerRealize, always create a buffer with scope

* update schedule_ops.cc

* update schedule_postproc_to_primfunc.cc

* restore more realize_scope

This reverts commit b66c3ba.

* make the default scope be "" instead of None in ir builder

* restore realize_scope visit in storage_flatten.cc

* update storage_access.cc

* make sure buffer var is of PointerType in ir builder

This reverts commit e650b6c.

* enforce default storage scope of global

* added remap pass but does not work yet

* fixed all reduce issue

This reverts commit 8e20003.

* simplify

* trying mitigation for aot test

* merge remaining changes from initial branch

* remove use of attr::storage_scope from codegen

* restore a visit to AttrStmt with attr::storage_scope in storage_rewrite

* disable check

* lint fix

* revert default scope to ""

* format

* fix volatile access to shared mem in lower all reduce

* fixed gpu coorporative load/store test

* pass storage scope to PointerType in tvm script parser

This reverts commit 99cfb9d18781dcfdea169d920450f9063ab18b6b.

* fixed tvmscript roundtrip test

* fixed tir flatten buffer test

* fixed test_tir_transform_hoist_if.py

* use storage scope global by default in aot_executor_codegen.cc

* add missing default storage scope in create_primfunc.cc

* restore StorageInfo struct in llvm backend

* UpdateStorageScope -> WithStorageScope

* fixed lower warp memory test

* GetStorageScope -> GetPtrStorageScope

* Enable storage scope invariant check in AttrStmt constructor

* remove GetPtrStorageScope and WithStorageScope from public header

* move RemapStorageScope to its own file

* add more method to RemapStorageScope

* update lower_thread_allreduce to use RemapStorageScope

* RemapStorageScope -> UpdatePointerStorageScope

* remove realize_scope from hybrid script

* removed realize_scope in schedule_ops

* remove realize_scope from schedule_postproc_to_primfunc

* remove remaining realize_scope usage from schedule_ops.cc

* remove realize_scope usage from storage_flatten.cc

* fixed test_tir_transform_lower_warp_memory.py following realize_scope removal

* Address comments

* Remove blank line diff

Co-authored-by: Masahiro Masuda <masahi@[email protected]>
Co-authored-by: masa <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants