Skip to content

Commit c39c213

Browse files
authored
[SYCL][COMPAT] Atomics: Support for multiple datatypes, remove runtime memoryOrder (#11788)
This PR replaces #11338, following discussion with DPCT team. Change summary: - Remove runtime `memoryOrder` option (no longer needed) - Define `type_identity_t` and use it to avoid template deduction errors. - New tests for the above (e.g. `int *` addr with `unsigned int` operand) - New free function `atomic_fetch_compare_dec`
1 parent 28cf832 commit c39c213

File tree

10 files changed

+465
-690
lines changed

10 files changed

+465
-690
lines changed

sycl/doc/syclcompat/README.md

Lines changed: 72 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -836,154 +836,122 @@ wrong queue is used as an argument in any of the member functions of the
836836
#### Atomic Operations
837837

838838
SYCLcompat provides an interface for common atomic operations (`add`, `sub`,
839-
`and`, `or`, `xor`, `min`, `max`, `exchange`, `compare_exchange`). While SYCL
840-
exposes atomic operations through member functions of `sycl::atomic_ref`, this
841-
library provides access via functions taking a standard pointer argument.
842-
Template arguments control the `sycl::memory_scope`, `sycl::memory_order` and
843-
`sycl::access::address_space` of these atomic operations. SYCLcompat also
844-
exposes overloads for these atomic functions which take a runtime memoryScope
845-
argument. Every atomic operation is implemented via an API function taking a raw
846-
pointer as the target. Additional overloads for
839+
`and`, `or`, `xor`, `min`, `max`, `inc`, `dec`, `exchange`, `compare_exchange`).
840+
While SYCL exposes atomic operations through member functions of
841+
`sycl::atomic_ref`, this library provides access via functions taking a standard
842+
pointer argument. Template arguments control the `sycl::memory_scope`,
843+
`sycl::memory_order` and `sycl::access::address_space` of these atomic
844+
operations. SYCLcompat also exposes overloads for these atomic functions which
845+
take a runtime memoryScope argument. Every atomic operation is implemented via
846+
an API function taking a raw pointer as the target. Additional overloads for
847847
`syclcompat::compare_exchange_strong` are provided which take a
848-
`sycl::multi_ptr` instead of a raw pointer. Addition and subtraction make use of
849-
`arith_t` to differentiate between numeric and pointer arithmetics.
848+
`sycl::multi_ptr` instead of a raw pointer. The type of the operand for most
849+
atomic operations is defined as `syclcompat::type_identity_t<T>` to avoid
850+
template deduction issues when an operand of a different type (e.g. double
851+
literal) is supplied. Atomic addition and subtraction free functions make use of
852+
`syclcompat::arith_t<T>` to differentiate between numeric and pointer
853+
arithmetics.
850854

851855
The available operations are exposed as follows:
852856

853857
``` c++
854858
namespace syclcompat {
855859

860+
template <class T> struct type_identity {
861+
using type = T;
862+
};
863+
template <class T> using type_identity_t = typename type_identity<T>::type;
864+
856865
template <typename T> struct arith {
857866
using type = std::conditional_t<std::is_pointer_v<T>, std::ptrdiff_t, T>;
858867
};
859868
template <typename T> using arith_t = typename arith<T>::type;
860869

861-
template <typename T,
862-
sycl::access::address_space addressSpace =
863-
sycl::access::address_space::global_space,
870+
template <sycl::access::address_space addressSpace =
871+
sycl::access::address_space::generic_space,
864872
sycl::memory_order memoryOrder = sycl::memory_order::relaxed,
865-
sycl::memory_scope memoryScope = sycl::memory_scope::device>
873+
sycl::memory_scope memoryScope = sycl::memory_scope::device,
874+
typename T>
866875
T atomic_fetch_add(T *addr, arith_t<T> operand);
867-
template <typename T,
868-
sycl::access::address_space addressSpace =
869-
sycl::access::address_space::global_space,
870-
sycl::memory_scope memoryScope = sycl::memory_scope::device>
871-
T atomic_fetch_add(T *addr, arith_t<T> operand,
872-
sycl::memory_order memoryOrder);
873876

874-
template <typename T,
875-
sycl::access::address_space addressSpace =
876-
sycl::access::address_space::global_space,
877+
template <sycl::access::address_space addressSpace =
878+
sycl::access::address_space::generic_space,
877879
sycl::memory_order memoryOrder = sycl::memory_order::relaxed,
878-
sycl::memory_scope memoryScope = sycl::memory_scope::device>
880+
sycl::memory_scope memoryScope = sycl::memory_scope::device,
881+
typename T>
879882
T atomic_fetch_sub(T *addr, arith_t<T> operand);
880-
template <typename T,
881-
sycl::access::address_space addressSpace =
882-
sycl::access::address_space::global_space,
883-
sycl::memory_scope memoryScope = sycl::memory_scope::device>
884-
T atomic_fetch_sub(T *addr, arith_t<T> operand,
885-
sycl::memory_order memoryOrder);
886883

887-
template <typename T,
888-
sycl::access::address_space addressSpace =
889-
sycl::access::address_space::global_space,
884+
template <sycl::access::address_space addressSpace =
885+
sycl::access::address_space::generic_space,
890886
sycl::memory_order memoryOrder = sycl::memory_order::relaxed,
891-
sycl::memory_scope memoryScope = sycl::memory_scope::device>
892-
T atomic_fetch_and(T *addr, T operand);
893-
template <typename T,
894-
sycl::access::address_space addressSpace =
895-
sycl::access::address_space::global_space,
896-
sycl::memory_scope memoryScope = sycl::memory_scope::device>
897-
T atomic_fetch_and(T *addr, T operand, sycl::memory_order memoryOrder);
887+
sycl::memory_scope memoryScope = sycl::memory_scope::device,
888+
typename T>
889+
T atomic_fetch_and(T *addr, type_identity<T> operand);
898890

899-
template <typename T,
900-
sycl::access::address_space addressSpace =
901-
sycl::access::address_space::global_space,
891+
template <sycl::access::address_space addressSpace =
892+
sycl::access::address_space::generic_space,
902893
sycl::memory_order memoryOrder = sycl::memory_order::relaxed,
903-
sycl::memory_scope memoryScope = sycl::memory_scope::device>
904-
T atomic_fetch_or(T *addr, T operand);
905-
template <typename T,
906-
sycl::access::address_space addressSpace =
907-
sycl::access::address_space::global_space,
908-
sycl::memory_scope memoryScope = sycl::memory_scope::device>
909-
T atomic_fetch_or(T *addr, T operand, sycl::memory_order memoryOrder);
894+
sycl::memory_scope memoryScope = sycl::memory_scope::device,
895+
typename T>
896+
T atomic_fetch_or(T *addr, type_identity<T> operand);
910897

911-
template <typename T,
912-
sycl::access::address_space addressSpace =
913-
sycl::access::address_space::global_space,
898+
template <sycl::access::address_space addressSpace =
899+
sycl::access::address_space::generic_space,
914900
sycl::memory_order memoryOrder = sycl::memory_order::relaxed,
915-
sycl::memory_scope memoryScope = sycl::memory_scope::device>
916-
T atomic_fetch_xor(T *addr, T operand);
917-
template <typename T,
918-
sycl::access::address_space addressSpace =
919-
sycl::access::address_space::global_space,
920-
sycl::memory_scope memoryScope = sycl::memory_scope::device>
921-
T atomic_fetch_xor(T *addr, T operand, sycl::memory_order memoryOrder);
901+
sycl::memory_scope memoryScope = sycl::memory_scope::device,
902+
typename T>
903+
T atomic_fetch_xor(T *addr, type_identity<T> operand);
922904

923-
template <typename T,
924-
sycl::access::address_space addressSpace =
925-
sycl::access::address_space::global_space,
905+
template <sycl::access::address_space addressSpace =
906+
sycl::access::address_space::generic_space,
926907
sycl::memory_order memoryOrder = sycl::memory_order::relaxed,
927-
sycl::memory_scope memoryScope = sycl::memory_scope::device>
928-
T atomic_fetch_min(T *addr, T operand);
929-
template <typename T,
930-
sycl::access::address_space addressSpace =
931-
sycl::access::address_space::global_space,
932-
sycl::memory_scope memoryScope = sycl::memory_scope::device>
933-
T atomic_fetch_min(T *addr, T operand, sycl::memory_order memoryOrder);
908+
sycl::memory_scope memoryScope = sycl::memory_scope::device,
909+
typename T>
910+
T atomic_fetch_min(T *addr, type_identity<T> operand);
934911

935-
template <typename T,
936-
sycl::access::address_space addressSpace =
937-
sycl::access::address_space::global_space,
912+
template <sycl::access::address_space addressSpace =
913+
sycl::access::address_space::generic_space,
938914
sycl::memory_order memoryOrder = sycl::memory_order::relaxed,
939-
sycl::memory_scope memoryScope = sycl::memory_scope::device>
940-
T atomic_fetch_max(T *addr, T operand);
941-
template <typename T,
942-
sycl::access::address_space addressSpace =
943-
sycl::access::address_space::global_space,
944-
sycl::memory_scope memoryScope = sycl::memory_scope::device>
945-
T atomic_fetch_max(T *addr, T operand, sycl::memory_order memoryOrder);
915+
sycl::memory_scope memoryScope = sycl::memory_scope::device,
916+
typename T>
917+
T atomic_fetch_max(T *addr, type_identity<T> operand);
946918

947919
template <sycl::access::address_space addressSpace =
948-
sycl::access::address_space::global_space,
920+
sycl::access::address_space::generic_space,
949921
sycl::memory_order memoryOrder = sycl::memory_order::relaxed,
950922
sycl::memory_scope memoryScope = sycl::memory_scope::device>
951923
unsigned int atomic_fetch_compare_inc(unsigned int *addr,
952924
unsigned int operand);
925+
953926
template <sycl::access::address_space addressSpace =
954-
sycl::access::address_space::global_space,
927+
sycl::access::address_space::generic_space,
928+
sycl::memory_order memoryOrder = sycl::memory_order::relaxed,
955929
sycl::memory_scope memoryScope = sycl::memory_scope::device>
956-
unsigned int atomic_fetch_compare_inc(unsigned int *addr,
957-
unsigned int operand,
958-
sycl::memory_order memoryOrder);
930+
unsigned int atomic_fetch_compare_dec(unsigned int *addr,
931+
unsigned int operand);
959932

960-
template <typename T,
961-
sycl::access::address_space addressSpace =
962-
sycl::access::address_space::global_space,
933+
template <sycl::access::address_space addressSpace =
934+
sycl::access::address_space::generic_space,
963935
sycl::memory_order memoryOrder = sycl::memory_order::relaxed,
964-
sycl::memory_scope memoryScope = sycl::memory_scope::device>
965-
T atomic_exchange(T *addr, T operand);
966-
template <typename T,
967-
sycl::access::address_space addressSpace =
968-
sycl::access::address_space::global_space,
969-
sycl::memory_scope memoryScope = sycl::memory_scope::device>
970-
T atomic_exchange(T *addr, T operand, sycl::memory_order memoryOrder);
936+
sycl::memory_scope memoryScope = sycl::memory_scope::device,
937+
typename T>
938+
T atomic_exchange(T *addr, type_identity<T> operand);
971939

972-
template <typename T,
973-
sycl::access::address_space addressSpace =
974-
sycl::access::address_space::global_space,
940+
template <sycl::access::address_space addressSpace =
941+
sycl::access::address_space::generic_space,
975942
sycl::memory_order memoryOrder = sycl::memory_order::relaxed,
976-
sycl::memory_scope memoryScope = sycl::memory_scope::device>
943+
sycl::memory_scope memoryScope = sycl::memory_scope::device,
944+
typename T>
977945
T atomic_compare_exchange_strong(
978-
sycl::multi_ptr<T, sycl::access::address_space::global_space> addr,
946+
sycl::multi_ptr<T, sycl::access::address_space::generic_space> addr,
979947
T expected, T desired,
980948
sycl::memory_order success = sycl::memory_order::relaxed,
981949
sycl::memory_order fail = sycl::memory_order::relaxed);
982-
template <typename T,
983-
sycl::access::address_space addressSpace =
984-
sycl::access::address_space::global_space,
950+
template <sycl::access::address_space addressSpace =
951+
sycl::access::address_space::generic_space,
985952
sycl::memory_order memoryOrder = sycl::memory_order::relaxed,
986-
sycl::memory_scope memoryScope = sycl::memory_scope::device>
953+
sycl::memory_scope memoryScope = sycl::memory_scope::device,
954+
typename T>
987955
T atomic_compare_exchange_strong(
988956
T *addr, T expected, T desired,
989957
sycl::memory_order success = sycl::memory_order::relaxed,

0 commit comments

Comments
 (0)