This is an archive of the discontinued LLVM Phabricator instance.

[MLIR] Add Async dialect with trivial async.region operation
ClosedPublic

Authored by ezhulenev on Sep 28 2020, 5:52 PM.

Details

Summary

Start Async dialect for modeling asynchronous execution.

Diff Detail

Event Timeline

ezhulenev created this revision.Sep 28 2020, 5:52 PM
Herald added a project: Restricted Project. · View Herald TranscriptSep 28 2020, 5:52 PM
ezhulenev requested review of this revision.Sep 28 2020, 5:52 PM
rriddle added inline comments.Sep 28 2020, 6:00 PM
mlir/include/mlir/Dialect/Async/IR/AsyncOps.td
50

nit: Please do not put usernames in TODOs.

ezhulenev updated this revision to Diff 294846.Sep 28 2020, 6:05 PM

Update TODO

ezhulenev marked an inline comment as done.Sep 28 2020, 6:05 PM
mehdi_amini accepted this revision.Sep 28 2020, 6:11 PM

LG but please wait for @herhut to have a look

mlir/include/mlir/Dialect/Async/IR/Async.h
14

Can you fix the clang-tidy warning?

mlir/include/mlir/Dialect/Async/IR/AsyncBase.td
38
mlir/include/mlir/Dialect/Async/IR/AsyncOps.td
32

I think it is important to clarify whether it is guaranteed that they will execute concurrently, i.e. is it valid to have in compute0 a spin-lock on a flag that has to be set by compute1.
Or only explicit dependencies are making side-effects visible?

55

Could skip the type entirely here?

This revision is now accepted and ready to land.Sep 28 2020, 6:11 PM
ezhulenev updated this revision to Diff 294861.Sep 28 2020, 7:01 PM
ezhulenev marked 3 inline comments as done.

Update documentation + fix header guard.

ezhulenev updated this revision to Diff 294862.Sep 28 2020, 7:03 PM

Fix typos

mlir/include/mlir/Dialect/Async/IR/AsyncOps.td
32

I think it is important to have sequential execution legal, clarified it in description.

55

I was thinking that with an addition of return values from async regions, it will be clearer to have an explicit token return type.

Example:

%0#2 = async.region {
  %1 = alloc : memref<10xf32>
  async.yield %0 : memref<10xf32>
} : () -> (!async.token, !async.value<memref<10xf32>>)
             ^                       ^
             |                       |  
              region completed    return value is ready

Rename async.region to async.execute

herhut accepted this revision.Sep 29 2020, 2:14 AM

Thanks for starting this!

mlir/include/mlir/Dialect/Async/IR/AsyncOps.td
55

Do we need both types here? Does it ever happen that the async.value is ready before or after the async.token becomes ready? I can see that we want a async.value<void> like thing in case the async.region does not produce a value (and we can name it async.token). I am just not sure about requiring it to always be present.

ezhulenev added inline comments.Sep 29 2020, 11:04 AM
mlir/include/mlir/Dialect/Async/IR/AsyncOps.td
55

Not sure about that. Having a token is convenient when you have two async regions that produce values, however there is no "true data dependency" between them.

Example:

%0:3 = async.execute (%arg : memref) {
} : !async.token, !async.value<foo>, !async.value<bar>

%1 = async.execute [%0#1](%arg : memref) {
   ... do not need the value foo here
} : ...

both regions read-write into memref (e.g. scratch buffer) but second op does not need any of the produced values. Token can be constructed from any async value, but then it becomes a question, which value to choose. I feel that explicit token makes semantics clearer.

mehdi_amini added inline comments.Sep 29 2020, 11:25 AM
mlir/include/mlir/Dialect/Async/IR/AsyncOps.td
55

It seems easier to me to handle the region with having always this token there: it makes it more regular.
It is also less ambiguous if a dependency is on the side-effects of the region or on the availability of a particular result. Otherwise a result may have users that aren't interested in the value itself but are just synchronizing on the async task.