This is an archive of the discontinued LLVM Phabricator instance.

[mlir][openacc] Add private representation
ClosedPublic

Authored by clementval on May 15 2023, 3:33 PM.

Details

Summary

Currently privatization is not well represented in the OpenACC dialect. This
patch is a prototype to model privatization with a dedicated operation that
declares how the private value is created and destroyed.

The newly introduced operation is acc.private.recipe and it declares
an OpenACC privatization. The operation requires one mandatory and
one optional region.

  1. The initializer region specifies how to create and initialize a new private value. For example in Fortran, a derived-type might have a default initialization. The region has an argument that contains the value that need to be privatized. This is useful if the type is not a known at compile time and the private value is needed to create its copy.
  2. The destroy region specifies how to destruct the value when it reaches its end of life. It takes the privatized value as argument.

A same privatization can be used for multiple operand if they have the same
type and do not require a specific default initialization.

Example:

mlir
acc.private.recipe @privatization_f32 : f32 init {
^bb0(%0: f32):
  // init region contains a sequence of operations to create and initialize the
  // copy if needed.
} destroy {
^bb0(%0: f32):
  // destroy region contains a sequences of operations to destruct the created
  // copy.
}

// The privatization symbol is then used in the corresponding operation.
acc.parallel private(@privatization_f32 -> %a : f32) {
}

Diff Detail

Event Timeline

clementval created this revision.May 15 2023, 3:33 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 15 2023, 3:33 PM
clementval requested review of this revision.May 15 2023, 3:33 PM

Note that the same operation could be used for firstprivate with some small additions.

jeanPerier accepted this revision.May 16 2023, 12:16 AM

Looks great!

This revision is now accepted and ready to land.May 16 2023, 12:16 AM

Awesome! This design what I had envisioned with regards to keeping track of initializer. This same approach should work for scalar reductions also whose private copies have explicit initial values in the spec - not just types with default initializer.

I have a few questions:

  1. Should the allocation logic should be part of initialization? For example, 2.5.13 private clause says "; it declares that a copy of each item on the list will be created for each gang in all dimensions.". Depending on how gang parallelism is mapped to the underlying hardware, the allocation may not be a stack allocation for which an alloca is relevant for. However, on the flip side, we need some info from frontend with regards to allocation size/type. So maybe allocation/initialization sections should be separated or we need some other way to encode size info.
  2. Should the init section should be enforced to exist? OpenACC spec does not specify or enforce initial values for private. Thus it depends on the source language itself. However, I guess you could argue that for those cases, each dialect should have an initializer with an op specifying the "undefined" state. That said, if you think for uniformity reasons we should always capture this info even if undefined, I would be OK with it.
  3. Can we find a better name than "declare"? declare is an OpenACC directive with specific semantics. As I thought about it, I kind of like acc.private.recipe, acc.reduction.recipe, etc since these are operations that provide the instructions which will eventually be used for materializing semantics.

Awesome! This design what I had envisioned with regards to keeping track of initializer. This same approach should work for scalar reductions also whose private copies have explicit initial values in the spec - not just types with default initializer.

I have a few questions:

  1. Should the allocation logic should be part of initialization? For example, 2.5.13 private clause says "; it declares that a copy of each item on the list will be created for each gang in all dimensions.". Depending on how gang parallelism is mapped to the underlying hardware, the allocation may not be a stack allocation for which an alloca is relevant for. However, on the flip side, we need some info from frontend with regards to allocation size/type. So maybe allocation/initialization sections should be separated or we need some other way to encode size info.

We can for sure have a separate regions for allocation/init or the region can just contains the alloc + init information. If the allocation change from the standard one, we should then probably have a pass that can update the init region or duplicate the whole op with specific allocation.

  1. Should the init section should be enforced to exist? OpenACC spec does not specify or enforce initial values for private. Thus it depends on the source language itself. However, I guess you could argue that for those cases, each dialect should have an initializer with an op specifying the "undefined" state. That said, if you think for uniformity reasons we should always capture this info even if undefined, I would be OK with it.

I'm fine making the init region optional if we have a dedicated alloc region otherwise I was thinking that the init region holds at least the information about how to allocate the private copy so that's why I made it non optional.

  1. Can we find a better name than "declare"? declare is an OpenACC directive with specific semantics. As I thought about it, I kind of like acc.private.recipe, acc.reduction.recipe, etc since these are operations that provide the instructions which will eventually be used for materializing semantics.

Right declare is a specific directive in OpenACC so we might want to change the name here. I'm fine with recipe since I can't find another name.

clementval edited the summary of this revision. (Show Details)May 16 2023, 8:46 AM
clementval edited the summary of this revision. (Show Details)
  • Rename declare to recipe
  • Couple of typos fix
  • emphasize that init region is for both allocation + initialization if needed
clementval edited the summary of this revision. (Show Details)May 16 2023, 10:25 AM
razvanlupusoru accepted this revision.May 16 2023, 12:50 PM

Thank you.

This revision was automatically updated to reflect the committed changes.