Skip to content

Conversation

@kalmarek
Copy link
Contributor

@kalmarek kalmarek commented Jun 6, 2024

Following the discussion in #54642

Implemented:

  • modifyindex_atomic!, swapindex_atomic!, replaceindex_atomic! for GenericMemory
  • getindex_atomic, setindex_atomic!, setindexonce_atomic! for GenericMemory
  • add support for references in @atomic macros
  • add support for vararg indices in @atomic macros
  • tests
  • update docstrings with example usage
  • [ ] update Atomics section of the manual (?)
  • news

@oscardssmith @vtjnash

New @atomic transformations implemented here:

julia> @macroexpand (@atomic a[i1,i2])
:(Base.getindex_atomic(a, :sequentially_consistent, i1, i2))

julia> @macroexpand (@atomic order a[i1,i2])
:(Base.getindex_atomic(a, order, i1, i2))

julia> @macroexpand (@atomic a[i1,i2] = 2.0)
:(Base.setindex_atomic!(a, :sequentially_consistent, 2.0, i1, i2))

julia> @macroexpand (@atomic order a[i1,i2] = 2.0)
:(Base.setindex_atomic!(a, order, 2.0, i1, i2))

julia> @macroexpand (@atomicswap a[i1,i2] = 2.0)
:(Base.swapindex_atomic!(a, :sequentially_consistent, 2.0, i1, i2))

julia> @macroexpand (@atomicswap order a[i1,i2] = 2.0)
:(Base.swapindex_atomic!(a, order, 2.0, i1, i2))

julia> @macroexpand (@atomic a[i1,i2] += 2.0)
:((Base.modifyindex_atomic!(a, :sequentially_consistent, +, 2.0, i1, i2))[2])

julia> @macroexpand (@atomic order a[i1,i2] += 2.0)
:((Base.modifyindex_atomic!(a, order, +, 2.0, i1, i2))[2])

julia> @macroexpand (@atomiconce a[i1,i2] = 2.0)
:(Base.setindexonce_atomic!(a, :sequentially_consistent, :sequentially_consistent, 2.0, i1, i2))

julia> @macroexpand (@atomiconce o1 o2 a[i1,i2] = 2.0)
:(Base.setindexonce_atomic!(a, o1, o2, 2.0, i1, i2))

julia> @macroexpand (@atomicreplace a[i1,i2] (2.0=>3.0))
:(Base.replaceindex_atomic!(a, :sequentially_consistent, :sequentially_consistent, 2.0, 3.0, i1, i2))

julia> @macroexpand (@atomicreplace o1 o2 a[i1,i2] (2.0=>3.0))
:(Base.replaceindex_atomic!(a, o1, o2, 2.0, 3.0, i1, i2))

@oscardssmith oscardssmith added needs tests Unit tests are required for this change needs docs Documentation for this change is required needs news A NEWS entry is required for this change labels Jun 6, 2024
@oscardssmith
Copy link
Member

other than the comment above this looks good! (it is missing an implementation of getindex_atomic which we need because the regular getindex doesn't have a place to pass an order)

@kalmarek
Copy link
Contributor Author

kalmarek commented Jun 7, 2024

@oscardssmith I'm not sure about the semantics of the suggested getindex_atomic. One can write a completely generic

function getindex_atomic(mem::GenericMemory, i::Int, order=default_access_order(mem))
    memref = memoryref(mem, i, @_boundscheck)
    return memoryrefget(memref, i, order, @_boundscheck)
end

but there's nothing atomic about the function, except the order argument. Is this what you meant?

@oscardssmith
Copy link
Member

The point is just that (but probably restricted to AtomicMemory since

julia> m = Memory{Int}(undef, 5);

julia> Base.memoryrefget(memoryref(m, 1), :acquire, false)
ERROR: ConcurrencyViolationError("memoryrefget: non-atomic memory cannot be accessed atomically")
Stacktrace:
 [1] top-level scope
   @ REPL[3]:1

The reason we need this function is for the user to be able to provide a stricter order than :monotonic

@kalmarek kalmarek force-pushed the mk/atomic_macro_memory branch from 190287c to c7f721c Compare June 7, 2024 14:16
@kalmarek
Copy link
Contributor Author

kalmarek commented Jun 7, 2024

@oscardssmith thanks for the clarification;

Alongside modifyindex_atomic!, swapindex_atomic! and replaceindex_atomic! I've also implemented

  • getindex_atomic(::GenericMemory, i, ...)
  • setindex_atomic!(::GenericMemory, i, ...) and
  • setindexonce_atomic!(::GenericMemory, i, ...).

I added some converts (val isa T ? val : convert(T, val)::T) those *index methods and the support for indexing in @atomic macro with the semantics as in the opening comment.

Please have a look and comment!

I'll write/update docstrings once the code is approved.

@kalmarek kalmarek changed the title implement (modify|swap|replace)index! for GenericMemory add support for indexing in @atomic macro Jun 7, 2024
@oscardssmith
Copy link
Member

This looks great to me! We definitely need more tests (and review from @vtjnash to make sure that all of the default orders etc are correct).

@kalmarek
Copy link
Contributor Author

kalmarek commented Jun 7, 2024

the default orderings are the ones from the existing cases of @atomic macro.

@kalmarek
Copy link
Contributor Author

@vtjnash could you have a look at the proposed changes?
In particular the choices of orderings for the @atomic macro.
Do we need even more tests?

@oscardssmith what kind of docs should be written?

To me the docstring of the atomic macro is already too long, asking rather for a paragraph in the atomics part of the manual.

@kalmarek kalmarek requested a review from oscardssmith June 18, 2024 14:28
@oscardssmith
Copy link
Member

I think this does need some docs under the @atomic macro, e.g.

  @atomic m[i] = new
  @atomic m[i] += addend
  @atomic :release m[i] = new
  @atomic :acquire_release m[i] += addend

but I agree with you that the docstring is already pretty long, but I kind of think that it is necessary to at least list the transforms that the macro does.

@kalmarek kalmarek force-pushed the mk/atomic_macro_memory branch from cabf062 to 9760b73 Compare June 19, 2024 19:11
@kalmarek
Copy link
Contributor Author

@oscardssmith @vtjnash I've updated docstrings and added NEWS entry. Please let me know if something else needs to be done/changed (i.e. please review :).

To me it seems ready to merge!

@vchuravy
Copy link
Member

Would be nice to check that Atomix.jl still works and can be used as a backwards compatible layer to get this functionality on older Julia versions.

@vchuravy vchuravy mentioned this pull request Jun 27, 2024
4 tasks
@kalmarek
Copy link
Contributor Author

@vchuravy I was actually thinking about spinning this functionality into a small package for julia-1.11, but merging into Atomix.jl would be even better. My only hesitation is that this package has not seen any activity in 2 years and was mostly developed by the brilliant tkf who left the community. Is it worth the effort?

@vchuravy
Copy link
Member

Atomix is actively used and @maleadt or I have commit privileges.

@kalmarek kalmarek requested a review from vtjnash June 30, 2024 22:11
@nsajko nsajko added the feature Indicates new feature / enhancement requests label Jul 1, 2024
@kalmarek
Copy link
Contributor Author

kalmarek commented Jul 2, 2024

@oscardssmith @vtjnash please let me know what else need to be done here.

@nsajko, since you have access to lables I think that needs news, needs docs and needs tests are satisfied and could be removed.

@nsajko nsajko removed needs tests Unit tests are required for this change needs docs Documentation for this change is required needs news A NEWS entry is required for this change labels Jul 2, 2024
@oscardssmith
Copy link
Member

IMO this is ready to merge, but I do want @vtjnash to have a last lock

@oscardssmith oscardssmith merged commit 23dabef into JuliaLang:master Jul 7, 2024
@oscardssmith
Copy link
Member

Thanks so much for doing this!

@vtjnash
Copy link
Member

vtjnash commented Jul 8, 2024

Awesome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arrays [a, r, r, a, y, s] atomics feature Indicates new feature / enhancement requests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants