Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 11 additions & 14 deletions affinity/cpp-23/d1436r2.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@

# Changelog

### P1436r2 (BEL 2019)

* Alter the wording on the `bulk_execution_affinity_t` properties so they are now hints that request the executor provide a particular pattern of binding, rather than a guarantee.

### P1436r1 (COL 2019)

* Introduce wording to clarify when two invocations of bulk_execute
Expand Down Expand Up @@ -256,7 +260,7 @@ constexpr memory_locality_intersection_t memory_locality_intersection;

## Bulk execution affinity properties

We propose an executor property group called `bulk_execution_affinity` which contains the nested properties `none`, `balanced`, `scatter` or `compact`. Each of these properties, if applied to an *executor* enforces a particular guarantee of binding *execution agents* to the *execution resources* associated with the *executor* in a particular pattern.
We propose an executor property group called `bulk_execution_affinity` which contains the nested properties `none`, `balanced`, `scatter` and `compact`. Each of these properties, if applied to an *executor* provides a hint to the `executor` that requests a particular binding of *execution agents* to the *execution resources* associated with the *executor* in a particular pattern.

### Example

Expand All @@ -283,7 +287,7 @@ Below is an example *(Listing 4)* of executing a parallel task over 8 threads us

### Proposed Wording

The `bulk_execution_affinity_t` property is a behavioral property as defined in P0443 [[22]][p0443] which describes the guarantees an executor provides to the binding of *execution agents* created by a call to `bulk_execute` to the underlying *threads of execution* and to the locality of those *threads of execution*.
The `bulk_execution_affinity_t` properties are a group of mutually exclusive behavioral properties (as defined in P0443 [[22]][p0443]) which provide a hint to the *executor* to, if possible, bind the *execution agents* created by a bulk invocation from an *executor*, to the underlying *execution resources* in a particular pattern relative to their physical closeness.

The `bulk_execution_affinity_t` property provides nested property types and objects as described below, where:
* `e` denotes an executor object of type `E`,
Expand All @@ -293,24 +297,17 @@ The `bulk_execution_affinity_t` property provides nested property types and obje

| Nested Property Type | Nested Property Name | Requirements |
|----------------------|----------------------|--------------|
| `bulk_execution_affinity_t::none_t` | `bulk_execution_affinity_t::none` | A call to `e.bulk_execute(f, s, sf)` has no requirements on the binding of *execution agents* to the underlying *execution resources*. | |
| `bulk_execution_affinity_t::scatter_t` | `bulk_execution_scatter_t::scatter` | A call to `e.bulk_execute(f, s, sf)` must bind the created *execution agents* to the underlying *execution resources* (ordered by physical closeness) such that they are distributed equally across the *execution resources* in a round-robin fashion. <br><br> If the execution context associated with `e` fails to bind the created *execution agents* to the underlying *execution resources* then `bulk_execute` must throw an exception. |
| `bulk_execution_affinity_t::compact_t` | `bulk_execution_compact_t::compact` | A call to `e.bulk_execute(f, s, sf)` must bind the created *execution agents* to the underlying *execution resources* such that they are distributed as close as possible to the *execution resource* of the *thread of execution* which created them. <br><br> If the execution context associated with `e` fails to bind the created *execution agents* to the underlying *execution resources* then `bulk_execute` must throw an exception. |
| bulk_execution_affinity_t::balanced_t | bulk_execution_balanced_t::balanced | A call to `e.bulk_execute(f, s, sf)` must bind the created *execution agents* to the underlying *execution resources* (ordered by physical closeness) such that they are distributed equally across the *execution resources* in a bin packing fashion. <br><br> If the execution context associated with `e` fails to bind the created *execution agents* to the underlying *execution resources* then `bulk_execute` must throw an exception. |
| `bulk_execution_affinity_t::none_t` | `bulk_execution_affinity_t::none` | A call to `e.bulk_execute(f, s, sf)` has no requirements on the binding of *execution agents* to the underlying *execution resources*. |
| `bulk_execution_affinity_t::scatter_t` | `bulk_execution_scatter_t::scatter` | A call to `e.bulk_execute(f, s, sf)` should aim to bind the created *execution agents* to the underlying *execution resources* (ordered by physical closeness) such that they are distributed equally across the *execution resources* in a round-robin fashion. <br><br> If the execution context associated with `e` is not able to bind the *execution agents* to the underlying *execution resources* as requested it should fall back to `bulk_execution_affinity_t::none_t`. |
| `bulk_execution_affinity_t::compact_t` | `bulk_execution_compact_t::compact` | A call to `e.bulk_execute(f, s, sf)` should aim to bind the created *execution agents* to the underlying *execution resources* such that they are distributed as close as possible to the *execution resource* of the *thread of execution* which created them. <br><br> If the execution context associated with `e` is not able to bind the *execution agents* to the underlying *execution resources* as requested it should fall back to `bulk_execution_affinity_t::none_t`. |
| bulk_execution_affinity_t::balanced_t | bulk_execution_balanced_t::balanced | A call to `e.bulk_execute(f, s, sf)` should aim to bind the created *execution agents* to the underlying *execution resources* (ordered by physical closeness) such that they are distributed equally across the *execution resources* in a bin packing fashion. <br><br> If the execution context associated with `e` is not able to bind the *execution agents* to the underlying *execution resources* as requested it should fall back to `bulk_execution_affinity_t::none_t`. |

> [*Note:* The requirements of the `bulk_execution_affinity_t` nested properties do not enforce a specific binding, simply that the binding follows the requirements set out above and that the pattern is consistent across invocations of the bulk execution functions. *--end note*]
> [*Note:* An implementation is free to choose how it maps individual work items to the underlying *execution resources*, providing it aims to achieve the requested affinity relationship. *--end note*]

> [*Note:* It's expected that the default value of `bulk_execution_affinity_t` for most executors be `bulk_execution_affinity_t::none_t`. *--end note*]

> [*Note:* The terms used for the `bulk_execution_affinity_t` nested properties are derived from the OpenMP properties [[33]][openmp-affinity] including the Intel specific balanced affinity binding [[[34]][intel-balanced-affinity] *--end note*]

For any two invocations; `e1.bulk_execute(f1, s1, sf1)` and `e2.bulk_execute(f2, s2, sf2)`, the binding of *execution agents* to the underlying *execution resources* must be consistent, if:
* `e1 == e2`,
* `execution::query(e1, execution::bulk_execution_affinity) != execution::bulk_execution_affinity.none`, and
* `s1 == s2`.

> [*Note:* If you have two invocation of `bulk_execute` where the binding of *execution agents* to the underlying *execution resources* is guaranteed to be consistent, this can lead to limitations of resource utilization. *--end note*]

> [*Note:* If two *executors* `e1` and `e2` invoke a bulk execution function in order, where `execution::query(e1, execution::context) == query(e2, execution::context)` is `true` and `execution::query(e1, execution::bulk_execution_affinity) == query(e2, execution::bulk_execution_affinity)` is `false`, this will likely result in `e1` binding *execution agents* if necessary to achieve the requested affinity pattern and then `e2` rebinding to achieve the new affinity pattern. Rebinding *execution agents* to *execution resources* may take substantial time and may affect performance of subsequent code. *--end note*]

## Concurrency property
Expand Down