Skip to content

Commit ad222e0

Browse files
committed
GPU: make the Metal atomics operate on plain counters
GPUAtomic() expanded to metal::atomic, but the counters it guards are plain integers in structures that the host allocates and transfers, and the code reads them directly outside the atomic operations. That is exactly the CUDA and HIP situation, where GPUAtomic() is a no-op and atomicAdd() takes a plain pointer, so Metal now does the same. MSL's atomic_*_explicit do want metal::atomic, which has the same size and alignment, so the operand is cast at the one point where the operation is issued. The cast has to keep the address space, which a generic pointer does not carry into atomic_*_explicit, hence the two overloads: threadgroup stays threadgroup for the *Shared entry points, anything else resolves to device. GPUTPCCFDecodeZS's shared memory had to be declared GPUsharedref() for that to hold; without it the reference is generic by the time AtomicAddShared sees it.
1 parent 27f5bda commit ad222e0

4 files changed

Lines changed: 27 additions & 10 deletions

File tree

‎GPU/Common/GPUCommonDefAPI.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@
173173
#define GPUdouble() float
174174
#define GPUbarrier() threadgroup_barrier(mem_flags::mem_device | mem_flags::mem_threadgroup)
175175
#define GPUbarrierWarp() simdgroup_barrier(mem_flags::mem_device | mem_flags::mem_threadgroup)
176-
#define GPUAtomic(type) atomic<type> // atomic variable type
176+
#define GPUAtomic(type) type // atomic variable type
177177
#elif defined(__HIPCC__) //Defines for HIP
178178
#define GPUd() __device__
179179
#define GPUdDefault() __device__

‎GPU/Common/GPUCommonMath.h‎

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,23 @@ GPUhdi() constexpr int32_t GPUCommonMath::Abs<int32_t>(int32_t x)
489489
return GPUCA_CHOICE(abs(x), abs(x), abs(x));
490490
}
491491

492+
#ifdef __METAL__
493+
// The counters these operate on are plain integers in the transferred structures,
494+
// as they are for CUDA and HIP. MSL's atomic operations want metal::atomic, which
495+
// has the same size and alignment; the overloads keep the address space, which a
496+
// generic pointer would not carry into atomic_*_explicit.
497+
template <class T>
498+
GPUdi() threadgroup metal::atomic<T>* GPUCommonMathMetalAtomic(threadgroup T* p)
499+
{
500+
return reinterpret_cast<threadgroup metal::atomic<T>*>(p);
501+
}
502+
template <class T>
503+
GPUdi() device metal::atomic<T>* GPUCommonMathMetalAtomic(T* p)
504+
{
505+
return (device metal::atomic<T>*)p;
506+
}
507+
#endif
508+
492509
template <class S, class T>
493510
GPUdi() uint32_t GPUCommonMath::AtomicExchInternal(S* addr, T val)
494511
{
@@ -499,7 +516,7 @@ GPUdi() uint32_t GPUCommonMath::AtomicExchInternal(S* addr, T val)
499516
#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
500517
return ::atomicExch(addr, val);
501518
#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
502-
return atomic_exchange_explicit(addr, val, memory_order_relaxed);
519+
return atomic_exchange_explicit(GPUCommonMathMetalAtomic(addr), val, memory_order_relaxed);
503520
#elif defined(WITH_OPENMP)
504521
uint32_t old;
505522
__atomic_exchange(addr, &val, &old, __ATOMIC_SEQ_CST);
@@ -519,7 +536,7 @@ GPUdi() bool GPUCommonMath::AtomicCASInternal(S* addr, T cmp, T val)
519536
#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
520537
return ::atomicCAS(addr, cmp, val) == cmp;
521538
#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
522-
return atomic_compare_exchange_weak_explicit(addr, &cmp, val, memory_order_relaxed, memory_order_relaxed);
539+
return atomic_compare_exchange_weak_explicit(GPUCommonMathMetalAtomic(addr), &cmp, val, memory_order_relaxed, memory_order_relaxed);
523540
#elif defined(WITH_OPENMP)
524541
return __atomic_compare_exchange(addr, &cmp, &val, true, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
525542
#else
@@ -537,7 +554,7 @@ GPUdi() uint32_t GPUCommonMath::AtomicAddInternal(S* addr, T val)
537554
#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
538555
return ::atomicAdd(addr, val);
539556
#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
540-
return atomic_fetch_add_explicit(addr, val, memory_order_relaxed);
557+
return atomic_fetch_add_explicit(GPUCommonMathMetalAtomic(addr), val, memory_order_relaxed);
541558
#elif defined(WITH_OPENMP)
542559
return __atomic_add_fetch(addr, val, __ATOMIC_SEQ_CST) - val;
543560
#else
@@ -555,7 +572,7 @@ GPUdi() void GPUCommonMath::AtomicMaxInternal(S* addr, T val)
555572
#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
556573
::atomicMax(addr, val);
557574
#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
558-
atomic_fetch_max_explicit(addr, val, memory_order_relaxed);
575+
atomic_fetch_max_explicit(GPUCommonMathMetalAtomic(addr), val, memory_order_relaxed);
559576
#else
560577
S current;
561578
while ((current = *(volatile S*)addr) < val && !AtomicCASInternal(addr, current, val)) {
@@ -573,7 +590,7 @@ GPUdi() void GPUCommonMath::AtomicMinInternal(S* addr, T val)
573590
#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
574591
::atomicMin(addr, val);
575592
#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
576-
atomic_fetch_min_explicit(addr, val, memory_order_relaxed);
593+
atomic_fetch_min_explicit(GPUCommonMathMetalAtomic(addr), val, memory_order_relaxed);
577594
#else
578595
S current;
579596
while ((current = *(volatile S*)addr) > val && !AtomicCASInternal(addr, current, val)) {

‎GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@ using namespace o2::tpc::constants;
3737
// ===========================================================================
3838

3939
template <>
40-
GPUdii() void GPUTPCCFDecodeZS::Thread<GPUTPCCFDecodeZS::decodeZS>(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUSharedMemory& smem, processorType& clusterer, int32_t firstHBF, int32_t tpcTimeBinCut)
40+
GPUdii() void GPUTPCCFDecodeZS::Thread<GPUTPCCFDecodeZS::decodeZS>(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUsharedref() GPUSharedMemory& smem, processorType& clusterer, int32_t firstHBF, int32_t tpcTimeBinCut)
4141
{
4242
GPUTPCCFDecodeZS::decode(clusterer, smem, nBlocks, nThreads, iBlock, iThread, firstHBF, tpcTimeBinCut);
4343
}
4444

45-
GPUdii() void GPUTPCCFDecodeZS::decode(GPUTPCClusterFinder& clusterer, GPUSharedMemory& s, int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, int32_t firstHBF, int32_t tpcTimeBinCut)
45+
GPUdii() void GPUTPCCFDecodeZS::decode(GPUTPCClusterFinder& clusterer, GPUsharedref() GPUSharedMemory& s, int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, int32_t firstHBF, int32_t tpcTimeBinCut)
4646
{
4747
const uint32_t sector = clusterer.mISector;
4848
#ifdef GPUCA_GPUCODE

‎GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.h‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class GPUTPCCFDecodeZS : public GPUKernelTemplate
4545
decodeZS,
4646
};
4747

48-
static GPUd() void decode(GPUTPCClusterFinder& clusterer, GPUSharedMemory& s, int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, int32_t firstHBF, int32_t tpcTimeBinCut);
48+
static GPUd() void decode(GPUTPCClusterFinder& clusterer, GPUsharedref() GPUSharedMemory& s, int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, int32_t firstHBF, int32_t tpcTimeBinCut);
4949

5050
typedef GPUTPCClusterFinder processorType;
5151
GPUhdi() static processorType* Processor(GPUConstantMem& processors)
@@ -59,7 +59,7 @@ class GPUTPCCFDecodeZS : public GPUKernelTemplate
5959
}
6060

6161
template <int32_t iKernel = defaultKernel, typename... Args>
62-
GPUd() static void Thread(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUSharedMemory& smem, processorType& clusterer, Args... args);
62+
GPUd() static void Thread(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUsharedref() GPUSharedMemory& smem, processorType& clusterer, Args... args);
6363
};
6464

6565
class GPUTPCCFDecodeZSLinkBase : public GPUKernelTemplate

0 commit comments

Comments
 (0)