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

RFC: clarifying buffer declaration and access #63

Merged
merged 9 commits into from
May 11, 2022

Conversation

vinx13
Copy link
Member

@vinx13 vinx13 commented Mar 18, 2022

In apache/tvm#9727 and RFC#39, we deprecated Load and Store to use BufferLoad and BufferStore instead in order to support generalized multi-dimensional physical buffer access. This is a follow-up that documents necessary clarifications, implications about the new buffer convention, as well as the post-hoc pass checklist.

Rendered version: https://github.com/vinx13/tvm-rfcs/blob/clarify-buffer-access/rfcs/0063-clarifying-buffer-declaration-and-access.md

cc @tqchen @Lunderberg @junrushao1994 @csullivan @mbs-octoml @jroesch @areusch @wrongtest @Hzfengsy

Co-authored-by: Eric Lunderberg <Lunderberg@users.noreply.github.com>
convention of `PrimFunc` and are translated to assertions of buffer shapes, strides, etc. in
runtime.

During the lowering process, although buffer accesses inside `PrimFunc` are flattened to match
Copy link
Contributor

Choose a reason for hiding this comment

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

I have a proof-of-concept implementation of this removal at apache/tvm#10940. It is able to pass all tests in test_target_codegen_llvm.py, and I don't see any roadblocks for updating the other tests as well.

Copy link
Member Author

Choose a reason for hiding this comment

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

Nice. We can then consider moving to explicit DeclBuffer (mentioned in this RFC) to define the alias.

Copy link
Contributor

@areusch areusch left a comment

Choose a reason for hiding this comment

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

thanks @vinx13 @Lunderberg for this clarifying RFC! did a fine-grained pass and attempted to clarify some of the wording per my understanding.

rfcs/0063-clarifying-buffer-declaration-and-access.md Outdated Show resolved Hide resolved
rfcs/0063-clarifying-buffer-declaration-and-access.md Outdated Show resolved Hide resolved
rfcs/0063-clarifying-buffer-declaration-and-access.md Outdated Show resolved Hide resolved
rfcs/0063-clarifying-buffer-declaration-and-access.md Outdated Show resolved Hide resolved
rfcs/0063-clarifying-buffer-declaration-and-access.md Outdated Show resolved Hide resolved
rfcs/0063-clarifying-buffer-declaration-and-access.md Outdated Show resolved Hide resolved
rfcs/0063-clarifying-buffer-declaration-and-access.md Outdated Show resolved Hide resolved
rfcs/0063-clarifying-buffer-declaration-and-access.md Outdated Show resolved Hide resolved
rfcs/0063-clarifying-buffer-declaration-and-access.md Outdated Show resolved Hide resolved
Co-authored-by: Andrew Reusch <areusch@gmail.com>
Copy link
Member Author

@vinx13 vinx13 left a comment

Choose a reason for hiding this comment

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

@areusch Thanks for the great feedback, will update the RFC accordingly

- Buffer map of `PrimFunc`. This specifies how opaque parameters of type `T.handle` should be
interpreted as a buffer inside the `PrimFunc`. `T.handle` represents an opaque pointer (`void *`).
- `T.alloc_buffer` is used `S-TIR` to create and allocate a buffer.
- `T.buffer_decl` can be used to create a buffer alias by specifying the underlying data variable to
Copy link
Member Author

Choose a reason for hiding this comment

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

Yes. In TVM script, it is T.buffer_decl and we have plan to rename it to T.decl_buffer

that has a vectorized type, or by using `Ramp` as an index into a buffer that has a scalar type.
For N-D buffer indices, it is possible that `Ramp` being used in multiple dimensions
(e.g. `A[Ramp(...), ..., Ramp(...)]` ). In this case the number of lanes of the data type of such
value is the product of each `Ramp`. We may want to limit `Ramp` to only the last dimension as
Copy link
Member Author

Choose a reason for hiding this comment

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

@Lunderberg has already sent follow up PR to limit Ramp to the last dimension. I'll update this sentence

for TIR transformations. Passes that rewrite buffers should clearly indicate how aliased buffers
are handled. For example, when changing the underlying layout of stored elements in a buffer, all
buffer aliases must also be updated. While buffer aliasing is typically free at runtime, this
imposes a cost for buffer aliasing both to compile times and development complexity.
Copy link
Member Author

Choose a reason for hiding this comment

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

we don't have any alias analysis right now

- Buffer map of `PrimFunc`. This specifies how opaque parameters of type `T.handle` should be
interpreted as a buffer inside the `PrimFunc`. `T.handle` represents an opaque pointer (`void *`).
- `T.alloc_buffer` is used `S-TIR` to create and allocate a buffer.
- `T.buffer_decl` can be used to create a buffer alias by specifying the underlying data variable to
Copy link
Contributor

Choose a reason for hiding this comment

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

ok, if you're using T. notation here, you mean TVMScript, right? in which case, can you update all occurrences to match what you would grep for if using TVMScript? right now it's a dead-end.


`T.buffer_decl` creates a buffer alias if the underlying data variable (`.data` field) overlaps with
another buffer. Buffer created via `alloc_buffer` always do not alias. Buffer aliases do not need
`Allocate` to create the data variable. Each data variable can be allocated via `Allocate` once.
Copy link
Contributor

Choose a reason for hiding this comment

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

ok, can you update this in the doc? you could simply state "Buffer aliases do not need Allocate to create the data variable--they may simply reuse the data variable from the Buffer being aliased."

@@ -84,8 +92,9 @@ imposes a cost for buffer aliasing both to compile times and development complex
**Discussion: When it is safe to transform a buffer**

We would like to discuss some examples of when it is safe to transform a buffer w.r.t. aliasing rules:

(1) reshape, (2) layout transform (e.g. swap indices), (3) compact.
- (1) reshape
Copy link
Contributor

Choose a reason for hiding this comment

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

i think proper numbered list syntax is like

1. reshape
2. layout transform ...
3. compact


(1) reshape, (2) layout transform (e.g. swap indices), (3) compact.

(1) is fine under aliasing as long as the low level memory is shared. (2) and (3) would need more
Copy link
Contributor

Choose a reason for hiding this comment

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

yeah that makes sense, can you update the RFC?

@areusch
Copy link
Contributor

areusch commented Apr 19, 2022

@vinx13 let me know when this is ready for another look!

@vinx13
Copy link
Member Author

vinx13 commented Apr 20, 2022

@areusch it is ready for another look

Copy link
Contributor

@areusch areusch left a comment

Choose a reason for hiding this comment

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

thanks @vinx13, just a few things to ping on but otherwise no need to block on me.

- Buffer map of `PrimFunc`. This specifies how opaque parameters of type `T.handle` should be
interpreted as a buffer inside the `PrimFunc`. `T.handle` represents an opaque pointer (`void *`).
- `T.alloc_buffer` is used `S-TIR` to create and allocate a buffer.
- `T.buffer_decl` can be used to create a buffer alias by specifying the underlying data variable to
Copy link
Contributor

Choose a reason for hiding this comment

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

could you add a note so someone knows what to grep for post-future rename?


**Explicit `DeclBuffer` IR construct**

`T.buffer_decl` is not an explicit statement in TIR - There is no such node in TIR.
Copy link
Contributor

Choose a reason for hiding this comment

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

ping on this one?

for TIR transformations. Passes that rewrite buffers should clearly indicate how aliased buffers
are handled. For example, when changing the underlying layout of stored elements in a buffer, all
buffer aliases must also be updated. While buffer aliasing is typically free at runtime, this
imposes a cost for buffer aliasing both to compile times and development complexity.
Copy link
Contributor

Choose a reason for hiding this comment

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

ok, perhaps we could state that in RFC i guess? it seems pretty useful to have that if we make this change.

@vinx13
Copy link
Member Author

vinx13 commented Apr 29, 2022

@areusch added some minor updates based on the comments, see the last two commits

Copy link
Contributor

@areusch areusch left a comment

Choose a reason for hiding this comment

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

thanks for the updates and sorry for the long delay!

@areusch areusch merged commit de4fe97 into apache:main May 11, 2022
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.

None yet

3 participants