From a5579360037007b30c2fe3f553e28c7960e8fe9a Mon Sep 17 00:00:00 2001 From: Gordon Date: Mon, 12 Aug 2019 14:31:56 +0100 Subject: [PATCH 1/2] CP013: Make affinity properties hints. --- affinity/cpp-23/d1436r2.md | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/affinity/cpp-23/d1436r2.md b/affinity/cpp-23/d1436r2.md index 1c028b0..71d2216 100644 --- a/affinity/cpp-23/d1436r2.md +++ b/affinity/cpp-23/d1436r2.md @@ -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 @@ -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 @@ -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`, @@ -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.

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.

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.

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.

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.

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.

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:* The requirements of the `bulk_execution_affinity_t` nested properties do not enforce any specific binding. *--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 From 59e60451e67696cc3f4791485c51c8afd72fb23c Mon Sep 17 00:00:00 2001 From: Gordon Date: Sun, 29 Sep 2019 02:06:34 +0100 Subject: [PATCH 2/2] Alter wording of note to be more clear. --- affinity/cpp-23/d1436r2.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/affinity/cpp-23/d1436r2.md b/affinity/cpp-23/d1436r2.md index 71d2216..5475b8a 100644 --- a/affinity/cpp-23/d1436r2.md +++ b/affinity/cpp-23/d1436r2.md @@ -302,7 +302,7 @@ The `bulk_execution_affinity_t` property provides nested property types and obje | `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.

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.

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 any specific binding. *--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*]