You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: affinity/cpp-20/d0796r2.md
+39-14Lines changed: 39 additions & 14 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -14,12 +14,16 @@
14
14
15
15
# Changelog
16
16
17
+
### P0796r2 (RAP)
18
+
19
+
* Introduced a free function for retrieving the execution resource underlying the current thread of execution.
20
+
17
21
### P0796r1 (JAX)
18
22
19
23
* Introduce proposed wording.
20
24
* Based on feedback from SG1, introduce a pair-wise interface for querying the relative affinity between execution resources.
21
25
* Introduce an interface for retrieving an allocator or polymorphic memory resource.
22
-
* Based on feedback from SG1, remove requirement for a hierarchical system topology structure, which doesn't require a root resouce.
26
+
* Based on feedback from SG1, remove requirement for a hierarchical system topology structure, which doesn't require a root resource.
23
27
24
28
### P0796r0 (ABQ)
25
29
@@ -180,12 +184,12 @@ An `execution_resource` is a lightweight structure which acts as an identifier t
180
184
181
185
### System topology
182
186
183
-
The system topology is made up of a number of system-level `execution_resource`s, which can be queried through `this_system::resource` which returns a `std::vector`. A run-time library may initialize the `execution_resources` available within the system dynamically. However, this must be done before `main` is called, given that after that point, the system topology may not change.
187
+
The system topology is made up of a number of system-level `execution_resource`s, which can be queried through `this_system::get_resources` which returns a `std::vector`. A run-time library may initialize the `execution_resource`s available within the system dynamically. However, this must be done before `main` is called, given that after that point, the system topology may not change.
184
188
185
189
Below *(Listing 2)* is an example of iterating over the system-level resources and printing out their capabilities.
186
190
187
191
```cpp
188
-
for (auto res : execution::this_system::resources()) {
192
+
for (auto res : execution::this_system::get_resources()) {
189
193
std::cout << res.name() `\n`;
190
194
std::cout << res.can_place_memory() << `\n`;
191
195
std::cout << res.can_place_agents() << `\n`;
@@ -194,14 +198,18 @@ for (auto res : execution::this_system::resources()) {
194
198
```
195
199
*Listing 2: Example of querying all the system level execution resources*
196
200
201
+
### Current resource
202
+
203
+
The `execution_resource` which underlies the current thread of execution can be queried through `this_thread::get_resource`.
204
+
197
205
### Querying relative affinity
198
206
199
207
The `affinity_query` class template provides an abstraction for a relative affinity value between two `execution_resource`s. This value depends on a particular `affinity_operation` and `affinity_metric`. As a result, the `affinity_query` is templated on `affinity_operation` and `affinity_metric`, and is constructed from two `execution_resource`s. An `affinity_query` is not meant to be meaningful on its own. Instead, users are meant to compare two queries with comparison operators, in order to get a relative magnitude of affinity. If necessary, the value of an `affinity_query` can also be queried through `native_affinity`, though the return value of this is implementation defined.
200
208
201
209
Below *(listing 3)* is an example of how to query the relative affinity between two `execution_resource`s.
202
210
203
211
```cpp
204
-
auto systemLevelResources = execution::this_system::resources();
212
+
auto systemLevelResources = execution::this_system::get_resources();
205
213
auto memberResources = systemLevelResources.resources();
206
214
207
215
auto relativeLatency01 = execution::affinity_query<execution::affinity_operation::read,
@@ -223,15 +231,15 @@ The `execution_context` class provides an abstraction for managing a number of l
223
231
Below *(Listing 4)* is an example of how this extended interface could be used to construct an *execution context* from an *execution resource* which is retrieved from the *system’s resource topology*. Once an *execution context* is constructed it can then still be queried for its *execution resource*, and that *execution resource* can be further partitioned.
224
232
225
233
```cpp
226
-
auto &resources = execution::this_system::resources();
234
+
auto &resources = execution::this_system::get_resources();
auto &systelLevelResource = execContext.resource();
238
+
auto &systemLevelResource = execContext.resource();
231
239
232
240
// resource[0] should be equal to execResource
233
241
234
-
for (auto res : systelLevelResource.resources()) {
242
+
for (auto res : systemLevelResource.resources()) {
235
243
std::cout << res.name() << `\n`;
236
244
}
237
245
```
@@ -242,11 +250,11 @@ for (auto res : systelLevelResource.resources()) {
242
250
When creating an `execution_context` from a given `execution_resource`, the executors and allocators associated with it are bound to that `execution_resource`. For example, when creating an `execution_resource` from a CPU socket resource, all executors associated with the given socket will spawn execution agents with affinity to the socket partition of the system *(Listing 5)*.
243
251
244
252
```cpp
245
-
auto cList = std::execution::this_system::resources();
253
+
auto cList = std::execution::this_system::get_resources();
246
254
// FindASocketResource is a user-defined function that finds a
247
255
// resource that is a CPU socket in the given resource list
248
256
auto& socket = findASocketResource(cList);
249
-
execution_contexteC{socket} // Associated with the socket
257
+
execution_contextC{socket} // Associated with the socket
250
258
auto executor = eC.executor(); // By transitivity, associated with the socket too
251
259
auto socketAllocator = eC.allocator(); // Retrieve an allocator to the closest memory node
*Returns:* An `expected<size_t, error_type>` where,
499
-
* if the affinity query was succesful, the value of type `size_t` represents the magnitude of the relative affinity;
514
+
* if the affinity query was successful, the value of type `size_t` represents the magnitude of the relative affinity;
500
515
* if the affinity query was not successful, the error is an error of type `error_type` which represents the reason for affinity query failed.
501
516
502
517
> [*Note:* An affinity query is permitted to fail if affinity between the two execution resources cannot be calculated for any reason, such as the resources are of different vendors or communication between the resources is not possible. *--end note*]
@@ -505,16 +520,26 @@ The `affinity_query` class template provides an abstraction for a relative affin
505
520
506
521
## Free functions
507
522
508
-
The free function `this_system::resources` is provided for retrieving the `execution_resource`s which encapsulate the hardware platforms available within the system. We refer to these resources as the *system level resources*.
523
+
### `this_system::get_resources`
524
+
525
+
The free function `this_system::get_resources` is provided for retrieving the `execution_resource`s which encapsulate the hardware platforms available within the system. We refer to these resources as the *system level resources*.
*Returns:* An `std::vector` containing all *system level resources*.
513
530
514
-
*Requires:* If `this_system::resources().size() > 0`, `this_system::resources()[0]` be the `execution_resource` use by `std::thread`. The value returned by `this_system::resources()` be the same at any point after the invocation of `main`.
531
+
*Requires:* If `this_system::get_resources().size() > 0`, `this_system::get_resources()[0]` be the `execution_resource` use by `std::thread`. The value returned by `this_system::get_resources()` be the same at any point after the invocation of `main`.
515
532
516
533
> [*Note:* Returning a `std::vector` allows users to potentially manipulate the container of `execution_resource`s after it is returned. We may want to replace this at a later date with an alternative type which is more restrictive, such as a range or span. *--end note*]
517
534
535
+
### `this_thread::get_resource`
536
+
537
+
The free function `this_thread::get_resource` is provided for retrieving the `execution_resource` underlying the current thread of execution.
*Returns:* The `execution_resource` underlying the current thread of execution.
542
+
518
543
# Future Work
519
544
520
545
## Migrating data from memory allocated in one partition to another
@@ -545,7 +570,7 @@ We may wish to mirror the design of the executors proposal and have a generic qu
545
570
546
571
## Dynamic topology discovery
547
572
548
-
The current proposal requires that all `execution_resource`s are initialized before `main` is called. This therefore does not permit an `execution_resource` to become available or go off-line at run time. We may wish to support this in the future, however this is outside of the scope of this paper.
573
+
The current proposal requires that all `execution_resource`s are initialized before `main` is called. This therefore does not permit an `execution_resource` to become available or go off-line at run time. We may wish to support this in the future, however this is outside of the scope of this paper at the moment.
0 commit comments