Skip to content

Commit 6167372

Browse files
author
Gordon Brown
committed
Issue #34: Introduce free function for retrieving a threads resource.
* Introduce the `this_thread::get_resource` free function for retrieving the underlying execution resource of the current thread of execution. * Rename `this_system::resources` to `this_system::get_resources` to be more consistent with the current standard. * Correct typos.
1 parent 15d9eee commit 6167372

File tree

1 file changed

+38
-13
lines changed

1 file changed

+38
-13
lines changed

affinity/cpp-20/d0796r2.md

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,16 @@
1414

1515
# Changelog
1616

17+
### P0796r2 (RAP)
18+
19+
* Introduced a free function for retrieving the execution resource underlying the current thread of execution.
20+
1721
### P0796r1 (JAX)
1822

1923
* Introduce proposed wording.
2024
* Based on feedback from SG1, introduced a pair-wise interface for querying the relative affinity between execution resources.
2125
* 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.
2327

2428
### P0796r0 (ABQ)
2529

@@ -180,12 +184,12 @@ An `execution_resource` is a light weight structure which acts as an identifier
180184
181185
### System topology
182186
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`. The `execution_resources` available within the system can be initialised dynamically by a runtime library, however must be done so before `main` is called, given that after that point the system topology cannot 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`. The `execution_resources` available within the system can be initialised dynamically by a runtime library, however must be done so before `main` is called, given that after that point the system topology cannot change.
184188
185189
Below *(Listing 2)* is an example of iterating over the system level resources and priniting out it's capabilities.
186190
187191
```cpp
188-
for (auto res : execution::this_system::resources()) {
192+
for (auto res : execution::this_system::get_resources()) {
189193
std::cout << res.name() `\n`;
190194
std::cout << res.can_place_memory() << `\n`;
191195
std::cout << res.can_place_agents() << `\n`;
@@ -194,14 +198,18 @@ for (auto res : execution::this_system::resources()) {
194198
```
195199
*Listing 2: Example of querying all the system level execution resources*
196200

201+
### Current resource
202+
203+
The `execution_resource` which underlies the current thread of execution can be queried through `this_thread::get_resource`.
204+
197205
### Querying relative affinity
198206

199-
The `affinity_query` class template provides an abstraction for a relative affinity value between two `execution_resource`s, derived from a particular `affinity_operation` and `affinity_metric`. The `affinity_query` is templated by `affinity_operation` and `affinity_metric` and is constructed from two `execution_resource`s. An `affinity_query` does not mean much on it's own, instead a relative magnitude of affinity can be queried by using comparison operators. If nessesary the value of an `affinity_query` can also be queried through `native_affinity`, though the return value of this is implementation defined.
207+
The `affinity_query` class template provides an abstraction for a relative affinity value between two `execution_resource`s, derived from a particular `affinity_operation` and `affinity_metric`. The `affinity_query` is templated by `affinity_operation` and `affinity_metric` and is constructed from two `execution_resource`s. An `affinity_query` does not mean much on it's own, instead a relative magnitude of affinity can be queried by using comparison operators. If necessary the value of an `affinity_query` can also be queried through `native_affinity`, though the return value of this is implementation defined.
200208

201209
Below *(listing 3)* is an example of how you can query the relative affinity between two `execution_resource`s.
202210

203211
```cpp
204-
auto systemLevelResources = execution::this_system::resources();
212+
auto systemLevelResources = execution::this_system::get_resources();
205213
auto memberResources = systemLevelResources.resources();
206214

207215
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
223231
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 then that *execution resource* can be further partitioned.
224232

225233
```cpp
226-
auto &resources = execution::this_system::resources();
234+
auto &resources = execution::this_system::get_resources();
227235

228236
execution::execution_context execContext(resources[0]);
229237

230-
auto &systelLevelResource = execContext.resource();
238+
auto &systemLevelResource = execContext.resource();
231239

232240
// resource[0] should be equal to execResource
233241

234-
for (auto res : systelLevelResource.resources()) {
242+
for (auto res : systemLevelResource.resources()) {
235243
std::cout << res.name() << `\n`;
236244
}
237245
```
@@ -242,11 +250,11 @@ for (auto res : systelLevelResource.resources()) {
242250
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)*.
243251
244252
```cpp
245-
auto cList = std::execution::this_system::resources();
253+
auto cList = std::execution::this_system::get_resources();
246254
// FindASocketResource is a user-defined function that finds a
247255
// resource that is a CPU socket in the given resource list
248256
auto& socket = findASocketResource(cList);
249-
execution_contexteC{socket} // Associated with the socket
257+
execution_contextC{socket} // Associated with the socket
250258
auto executor = eC.executor(); // By transitivity, associated with the socket too
251259
auto socketAllocator = eC.allocator(); // Retrieve an allocator to the closest memory node
252260
std::vector<int, decltype(socketAllocator)> v1(100, socketAllocator);
@@ -343,13 +351,20 @@ If a particular policy or algorithm requires to access placement information, th
343351

344352
};
345353

354+
} // execution
355+
346356
/* This system */
347357

348358
namespace this_system {
349359
std::vector<execution_resource> resources() noexcept;
350360
}
351361

352-
} // execution
362+
/* This thread */
363+
364+
namespace this_thread {
365+
std::experimental::execution::execution_resource get_resource() noexcept;
366+
}
367+
353368
} // experimental
354369
} // std
355370

@@ -505,16 +520,26 @@ The `affinity_query` class template provides an abstraction for a relative affin
505520
506521
## Free functions
507522

508-
The free function `this_system::resources` is provided for retrieving the `execution_resource`s which encapsulate the hardware platforms available within the system, these are refered to 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, these are referred to as the *system level resources*.
509526

510527
std::vector<execution_resource> resources() noexcept;
511528

512529
*Returns:* A std::vector containing all *system level resources*.
513530

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`.
515532

516533
> [*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 with an alternative type which is more restrictive at a later date such as a range. *--end note*]
517534
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.
538+
539+
std::experimental::execution::execution_resource get_resource() noexcept;
540+
541+
*Returns:* The `execution_resource` underlying the current thread of execution.
542+
518543
# Future Work
519544

520545
## Migrating data from memory allocated in one partition to another

0 commit comments

Comments
 (0)