P2689: Bounded atomic_ref and atomic_accessor LEWG Presentation 04/30/2024
Nobody has claimed this yet.
- Dominant language
- HTML
- Stars
- 29
- Forks
- 26
- PR merge metrics
- No merged PRs in 30d
Description
Atomic Refs Bound to Memory Orderings & Atomic Accessors
The mdspan paper P0009 listed atomic accessors as a reason for having accessors in the first place.
One of the use cases is for parallel algorithms updating data in a way which has data races.
Consider the histogram computation:
template<class ExecT>
void compute_histogram(ExecT exec, float bin_size,
std::mdspan<int, std::dextents<size_t,1>> output,
std::mdspan<float, std::dextents<size_t,1>> data) {
static_assert(std::is_execution_policy_v<ExecT>);
std::for_each(exec, data.data_handle(), data.data_handle()+data.extent(0), [=](float val) {
int bin = std::abs(val)/bin_size;
bin = std::clamp(bin, size_t(0), output.extent(0));
output[bin]++;
});
Depending on whether ExecT is sequenced_policy or not, the update needs to happen atomically.
With just atomic_ref one could do:
std::for_each(exec, data.data_handle(), data.data_handle()+data.extent(0), [=](float val) {
int bin = std::abs(val)/bin_size;
bin = std::clamp(bin, size_t(0), output.extent(0));
atomic_ref(output[bin])++;
});
This paper proposes a way for doing that for general mdspans without writing out atomic_ref everywhere inside a complex algorithm and also fixes the fact that you can't do the simple ++ with relaxed memory order - enough for these kind of accumulation cases.
What this paper proposes
- "Bounded" versions of
atomic_refwith a fixed (bounded) memory orderatomic_ref_relaxed,atomic_ref_seq_cst,atomic_ref_acq_rel- Conceptually just like
atomic_refwith a fixed memory order - all the same members
- Corresponding atomic accessors which use the various
atomic_reftypes as reference typeatomic_accessor=>atomic_refatomic_accessor_relaxed=>atomic_ref_relaxedatomic_accessor_acq_rel=>atomic_ref_acq_relatomic_accessor_seq_cst=>atomic_ref_seq_cst
Histogram with atomic accessor
// sequenced_policy does not attach atomic accessor
template<class T, class Extents, class LayoutPolicy>
auto add_atomic_accessor_if_needed(
std::execution::sequenced_policy, mdspan<T, Extents, LayoutPolicy> m) {
return m;
}
// parallel policies attach atomic accessor:
template<class ExecutionPolicy, class T, class Extents, class LayoutPolicy>
auto add_atomic_accessor_if_needed(
ExecutionPolicy, mdspan<T, Extents, LayoutPolicy> m) {
return mdspan(m.data_handle(), m.mapping(), atomic_accessor<T>());
}
template<class ExecT>
void compute_histogram(ExecT exec, float bin_size,
std::mdspan<int, std::dextents<size_t,1>> output,
std::mdspan<float, std::dextents<size_t,1>> data) {
static_assert(std::is_execution_policy_v<ExecT>);
auto accumulator = add_atomic_accessor_if_needed(exec, output);
std::for_each(exec, data.data_handle(), data.data_handle()+data.extent(0), [=](float val) {
int bin = std::abs(val)/bin_size;
bin = std::clamp(bin, size_t(0), output.extent(0));
// this is now atomic for parallel policies
accumulator[bin]++;
});
Previous Question: Why not expose the templated type?
- There is really no use-case where one would want to write something generic over the memory order!
- The algorithm determines the memory order you need - the only generic question we identified is whether you need atomics at all (i.e. what execution policy is used)
- SG1 also felt that its easier to see the memory order with the explicit names
- We don't feel there is any real risk here and
mdspansomewhat hides its accessor anyway
- We don't feel there is any real risk here and
Wording Considerations
- Used exposition only
atomic-ref-bound<T,MemoryOrder>for wordingatomic_ref_MEM_ORDERare template aliases - see open question whether this is ok
atomic_refhas 4 specializations: general, integral (not bool), floating point and pointeratomic-ref-boundneeds only 2 (general and arithmetic/pointer{not-bool} versions)- integral, floating point and pointer type versions can be defined in terms of
atomic_refwith constraints on member functions - the only reason we need general is
difference_typemember typedef -> doesn't exist inatomic_refgeneral
- integral, floating point and pointer type versions can be defined in terms of
Open Questions
- Is reasoning for having
atomic-ref-boundexposition only good enough, or does LEWG want it as a public thing?- Please Poll:
atomic-ref-boundshould be exposition only. - Author position: in favor
- Please Poll:
- Converting between
atomic-ref-boundandbasic-atomic-accessorsof different memory orders- We don't see many good reasons to have them:
atomic_refis meant to be almost usedin-placefor individual operations e.g.atomic_ref(a[i])++- atomic accessors are something you are supposed to add in a fairly local scope
- we don't expect folks to pass
mdspanwith atomic accessors around
- There is a reason not to permit it:
- Writing functions which take
atomic_ref_MEM_ORDERimply ordering behavior: allowing conversions would change that behavior
- Writing functions which take
- Please Poll:
atomic-ref-boundandbasic-atomic-accessorshould have converting constructors for different memory-orders- Author position: against
- We don't see many good reasons to have them:
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
The issue is a LEWG presentation proposing bounded atomic_ref types and atomic accessors, but it names no repository files, tests, or implementation entry points. Start by reviewing the proposal and its open questions; the issue provides no concrete implementation scope or acceptance criteria beyond resolving the design polls.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100