This is an archive of the discontinued LLVM Phabricator instance.

[mlir][tensor] Add gather/scatter op definitions to the tensor dialect.
ClosedPublic

Authored by nicolasvasilache on Jul 22 2022, 4:42 AM.

Details

Summary

Gather/Scatter are examined from first principles in light of our recent progress on tensor-based codegen
and in-place bufferization.

In the future, lowering of these abstractions to operate inplace on buffers
will likely require a more powerful buffer representation than strided memref.

General context: https://discourse.llvm.org/t/rfc-structured-codegen-beyond-rectangular-arrays/64707
Relevant TL;DR parts of the proposal:

Diff Detail

Event Timeline

nicolasvasilache requested review of this revision.Jul 22 2022, 4:42 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 22 2022, 4:42 AM
nicolasvasilache edited the summary of this revision. (Show Details)Jul 22 2022, 4:46 AM
nicolasvasilache retitled this revision from [mlir[tensor]][WIP] Add gather/scatteer/parallel_scatter op definitions. to [mlir[tensor]] Add gather/scatter/parallel_scatter op definitions to the tensor dialect..
nicolasvasilache edited the summary of this revision. (Show Details)
nicolasvasilache retitled this revision from [mlir[tensor]] Add gather/scatter/parallel_scatter op definitions to the tensor dialect. to [mlir][tensor] Add gather/scatter/parallel_scatter op definitions to the tensor dialect..Aug 19 2022, 8:34 AM

Note this is failing with

tools/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.cpp.inc.d
error: expected literal, variable, directive, or optional group

$input `[` $indices `]` () $unique
                         ^

/var/lib/buildkite-agent/builds/llvm-project/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td:413:1: note: in custom assembly format for this operation
def Tensor_GatherOp : Tensor_Op<"gather", [
^

jpienaar added inline comments.Aug 19 2022, 11:28 AM
mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td
413

Summary should be single line with no trailing punctuation (https://mlir.llvm.org/docs/OpDefinitions/#operation-documentation)

425
   ```mlir
``` ?
448

Coordinates being the input side?

465

New line before, tag with mlir again to ensure markdown generation does whats expected

1302

This sentence feels out of place.

1322

Not sure if I follow, wouldn't the result be consumed by the parent parallel op?

mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td
1322

The parent ParallelCombiningOpInterface takes ops on tensors that do not return and combines them into the result, so there is no result to consume for this specific op
(more context in: https://discourse.llvm.org/t/rfc-parallel-abstraction-for-tensors-and-buffers/62607).

I can rephrase to make it more explicit, thanks!

mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td
1322

Actually I can also take this out of scope for now: getting the op right in the sequential case is the first step.

nicolasvasilache retitled this revision from [mlir][tensor] Add gather/scatter/parallel_scatter op definitions to the tensor dialect. to [mlir][tensor] Add gather/scatter op definitions to the tensor dialect..Aug 22 2022, 2:43 AM
nicolasvasilache edited the summary of this revision. (Show Details)
nicolasvasilache marked 6 inline comments as done.
nicolasvasilache retitled this revision from [mlir][tensor] Add gather/scatter op definitions to the tensor dialect. to [mlir[tensor]] Add gather/scatter op definitions to the tensor dialect..
nicolasvasilache edited the summary of this revision. (Show Details)

Address comments.

mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td
425

thanks! also updated a few other places I had missed in the past.

448

rephrased

bixia added inline comments.Aug 22 2022, 9:07 AM
mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td
434

to allow?

441

So 1 here is the size of the slice in dimension 1? What kind of syntax is this? The other two dimensions seem to be using numpy slice syntax. Would it be better to replace this with c:c+1 where c is the coordinate value in %input, and adjust the text description?

457–458

I think this is AoS not SoA, an array of coordinate tuples(structure).

The description doesn't mention the other dimensions beside the most minor dimension becomes part of the dimensions in the resulting tensor. It would be helpful to add this information.

473

"allow gather to view into the input data" doesn't make sense to me. Do you actually want to say:

Nested buffer support would allow us to show that the gather output is an array of 4-element slices?

1301

insert?

nicolasvasilache marked 3 inline comments as done.

Address comments and update op semantics according to: https://discourse.llvm.org/t/rfc-adding-gather-scatter-ops/64757

mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td
441

This was confusing indeed, I reworked this part, please lmk what you think.

Please also look at https://discourse.llvm.org/t/rfc-adding-gather-scatter-ops/64757.

457–458

You're right, thanks, updated.

I spelled out the types without dropping the 1s for now and tried to explain better, please let me know if this requires further clarifications.

473

I rephrased that part, please let me know if this still does not make sense.

nicolasvasilache marked 2 inline comments as done.
nicolasvasilache retitled this revision from [mlir[tensor]] Add gather/scatter op definitions to the tensor dialect. to [mlir][tensor] Add gather/scatter op definitions to the tensor dialect..

s/extract/insert

Update scatter and add tests.

More fixes + tests.

Use AnySignlessIntegerOrIndex

Drop spurious auto-introduced includes.

ftynse added inline comments.Aug 31 2022, 7:10 AM
mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td
413

let summary, let description, etc. here and below

424

Please also specify that the trailing dimension of the index tensor contains the coordinates and it is expected to have its size equal to the number of dimensions being gathered.

425

Nit: otherwise _ is interpreted by markdown

511

Would it simplify deeper implementation to make this attribute mandatory and just have syntactic sugar that sets it to gather_dims(0, 1,2 ...) when it is missing from the textual form?

524

Is this expected to connect to InferTypeOpInterface?

1360–1362

If I am not misreading it, the RFC discussion concluded that uniqueness is always a requirement for scatter and that it won't support repeated indices at this point.

mlir/lib/Dialect/Tensor/IR/TensorOps.cpp
566 ↗(On Diff #456900)

(Small)DenseSet should be enough here, nothing relies on the order of insertion. More nitpicky, we the expected size of the array, it is likely more wasteful to create a parallel data structure than to just do binary search through the vector (which we enforced to be sorted in the verifier) several times.

578 ↗(On Diff #456900)

Nit: can't we just append to resultShape after reserving resultShape() + sourceType.getRank() space in it?

588 ↗(On Diff #456900)

I would plainly disallow empty gather_dims. It is confusing that gather_dims() is equivalent to gather_dims(0, 1, 2, ...) and may be interpreted as a (misnamed) list of dimensions not to gather.

2398–2409 ↗(On Diff #456900)

This is common with gather, could we factor out the impl?

nicolasvasilache marked 9 inline comments as done.

Address comments.

mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td
413

hmmm I manage to copy-paste the 1 bad op and reuse as a template .. fixed the other places, thanks for catching!

524

Ideally yes, but I am reluctant to embark on this path until some prototyping is available for memref<memref>. Can we do this in a followup?
Added a TODO in the meantime.

1360–1362

How would you phrase this differently ?
The presence of the unique attribute is enforced but we can't statically enforce true uniqueness.
UB seems the proper way to express this?

ftynse accepted this revision.Sep 2 2022, 7:20 AM
ftynse added inline comments.
mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td
1360–1362

UB is the proper way. I was thinking that we can just drop the attribute. Or is there some anticipation that it will become optional?

This revision is now accepted and ready to land.Sep 2 2022, 7:20 AM

Change gather/scatter to non-optional.

nicolasvasilache marked an inline comment as done.Sep 2 2022, 7:30 AM
nicolasvasilache added inline comments.
mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td
511

What's the best way to achieve this these days, still use a custom parser/printer or can we just use a simpler embedded directive for this in the asm format?

1360–1362

ah yes ok, dropped the attribute, kept the syntax as being unambiguously clear about the semantics is important here.

ftynse added inline comments.Sep 2 2022, 7:36 AM
mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td
511

For the syntax, I'd go with an embedded custom directive for this attribute specifically.

In any case, I was really asking a question as you may have a deeper prototype somewhere and it's hard for me to say whether this will help the implementation or just add more complexity in the syntax.

nicolasvasilache marked 3 inline comments as done.Sep 2 2022, 10:32 AM
nicolasvasilache added inline comments.
mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td
511

Dropping optional is a good suggestion and will indeed simplify things.

Gave a shot to the custom thing but unless we change the syntax to something like:

input[%indices: indices_type] gather_dims(...)

I don't see a good way of writing it atm without implementing the whole parser (type must be resolved before I am able to know to what dim to automatically expand the no gather_dims).

I'll drop the implicit syntax and require explicit everything for now to remove the Optional, the syntax bikeshedding is separable.

nicolasvasilache marked an inline comment as done.Sep 3 2022, 4:13 AM
nicolasvasilache added a subscriber: Mogball.
nicolasvasilache added inline comments.
mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td
511

I also tried something like `DefaultValuedAttr<DenseI64ArrayAttr, "llvm::to_vector(llvm::seq<int64_t>(0, getIndices().getType().cast<RankedRensorType>().getIndicesType().getRank() - 1))">:$gather_dims```.
Unfortunately, the generated GatherOp::populateDefaultAttrs does not seem to receive enough information to be able to write such a default.

Maybe @Mogball will have more insight here.

Drop implicit form of gather_dims and scatter_dims: all must be explicit atm.

This revision was landed with ongoing or failed builds.Sep 5 2022, 2:02 AM
This revision was automatically updated to reflect the committed changes.
Mogball added inline comments.Sep 5 2022, 12:10 PM
mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td
511

You can't make the "default" value depend on another op attribute or property.

mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td
511

Thanks for confirming @Mogball , would the feature make sense ?
I.e. non-constexpr default values are generally useful but maybe this is not useful enough to justify adding the support.

Mogball added inline comments.Sep 16 2022, 10:13 AM
mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td
511

This can be achieved with a derived attribute that uses the value of an optional attribute or some derived value