Skip to content

Commit 70b5cbd

Browse files
authored
Merge pull request #44 from AerialMantis/issue-34
Issue #34: Introduce free function for retrieving a threads resource
2 parents f1b2484 + 6893808 commit 70b5cbd

File tree

1 file changed

+41
-16
lines changed

1 file changed

+41
-16
lines changed

affinity/cpp-20/d0796r2.md

Lines changed: 41 additions & 16 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

@@ -496,7 +511,7 @@ The `affinity_query` class template provides an abstraction for a relative affin
496511
friend expected<size_t, error_type> operator>=(const affinity_query&, const affinity_query&);
497512

498513
*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;
500515
* if the affinity query was not successful, the error is an error of type `error_type` which represents the reason for affinity query failed.
501516

502517
> [*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
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
@@ -535,7 +560,7 @@ With the ability to place memory with affinity comes the ability to define algor
535560

536561
## Level of abstraction
537562

538-
The current proposal provides an interface for querying whether an `execution_resource` can allocate and/or execute work, it can provide the concurrency it supports and it can provide a name. We also provide the `affinity_query` structure for querying the relative affinity metrics between two `execution_resource`s. However this may not be enough information for users to take full advance of the system, they may also want to know what kind of memory is available or the properties by which work is executed. It was decided that attempting to enumerate the various hardware components would not be ideal as that would make it harder for implementers to support new hardware. It has been discussed that a better approach would be to parameterise the additional properties of hardware such that hardware queries could be much more generic.
563+
The current proposal provides an interface for querying whether an `execution_resource` can allocate and/or execute work, it can provide the concurrency it supports and it can provide a name. We also provide the `affinity_query` structure for querying the relative affinity metrics between two `execution_resource`s. However this may not be enough information for users to take full advance of the system, they may also want to know what kind of memory is available or the properties by which work is executed. It was decided that attempting to enumerate the various hardware components would not be ideal as that would make it harder for implementors to support new hardware. It has been discussed that a better approach would be to parameterize the additional properties of hardware such that hardware queries could be much more generic.
539564

540565
We may wish to mirror the design of the executors proposal and have a generic query interface using properties for querying information about an `execution_resource`. It’s expected that an implementation may provide additional nonstandard queries that are specific to that implementation.
541566

@@ -545,7 +570,7 @@ We may wish to mirror the design of the executors proposal and have a generic qu
545570

546571
## Dynamic topology discovery
547572

548-
The current proposal requires that all `execution_resource`s are initialised before `main` is called, therefore not allowing an `execution_resource` to become available or go offline at runtime. 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, therefore not allowing an `execution_resource` to become available or go offline at runtime. We may wish to support this in the future, however this is outside of the scope of this paper.
549574

550575
| Straw Poll |
551576
|------------|

0 commit comments

Comments
 (0)