Skip to content

Commit bb585c3

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 f249a4d commit bb585c3

4 files changed

Lines changed: 21 additions & 10 deletions

File tree

‎GPU/Common/GPUCommonDefAPI.h‎

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

‎GPU/Common/GPUCommonMath.h‎

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,17 @@ GPUhdi() constexpr int32_t GPUCommonMath::Abs<int32_t>(int32_t x)
477477
return GPUCA_CHOICE(abs(x), abs(x), abs(x));
478478
}
479479

480+
#ifdef __METAL__
481+
// The counters these operate on are plain integers in the transferred structures,
482+
// as they are for CUDA and HIP. MSL's atomic operations want metal::atomic, which
483+
// has the same size and alignment; the overloads keep the address space, which a
484+
// generic pointer would not carry into atomic_*_explicit.
485+
template <class T>
486+
GPUdi() threadgroup metal::atomic<T>* GPUCommonMathMetalAtomic(threadgroup T* p) { return reinterpret_cast<threadgroup metal::atomic<T>*>(p); }
487+
template <class T>
488+
GPUdi() device metal::atomic<T>* GPUCommonMathMetalAtomic(T* p) { return (device metal::atomic<T>*)p; }
489+
#endif
490+
480491
template <class S, class T>
481492
GPUdi() uint32_t GPUCommonMath::AtomicExchInternal(S* addr, T val)
482493
{
@@ -487,7 +498,7 @@ GPUdi() uint32_t GPUCommonMath::AtomicExchInternal(S* addr, T val)
487498
#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
488499
return ::atomicExch(addr, val);
489500
#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
490-
return atomic_exchange_explicit(addr, val, memory_order_relaxed);
501+
return atomic_exchange_explicit(GPUCommonMathMetalAtomic(addr), val, memory_order_relaxed);
491502
#elif defined(WITH_OPENMP)
492503
uint32_t old;
493504
__atomic_exchange(addr, &val, &old, __ATOMIC_SEQ_CST);
@@ -507,7 +518,7 @@ GPUdi() bool GPUCommonMath::AtomicCASInternal(S* addr, T cmp, T val)
507518
#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
508519
return ::atomicCAS(addr, cmp, val) == cmp;
509520
#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
510-
return atomic_compare_exchange_weak_explicit(addr, &cmp, val, memory_order_relaxed, memory_order_relaxed);
521+
return atomic_compare_exchange_weak_explicit(GPUCommonMathMetalAtomic(addr), &cmp, val, memory_order_relaxed, memory_order_relaxed);
511522
#elif defined(WITH_OPENMP)
512523
return __atomic_compare_exchange(addr, &cmp, &val, true, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
513524
#else
@@ -525,7 +536,7 @@ GPUdi() uint32_t GPUCommonMath::AtomicAddInternal(S* addr, T val)
525536
#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
526537
return ::atomicAdd(addr, val);
527538
#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
528-
return atomic_fetch_add_explicit(addr, val, memory_order_relaxed);
539+
return atomic_fetch_add_explicit(GPUCommonMathMetalAtomic(addr), val, memory_order_relaxed);
529540
#elif defined(WITH_OPENMP)
530541
return __atomic_add_fetch(addr, val, __ATOMIC_SEQ_CST) - val;
531542
#else
@@ -543,7 +554,7 @@ GPUdi() void GPUCommonMath::AtomicMaxInternal(S* addr, T val)
543554
#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
544555
::atomicMax(addr, val);
545556
#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
546-
atomic_fetch_max_explicit(addr, val, memory_order_relaxed);
557+
atomic_fetch_max_explicit(GPUCommonMathMetalAtomic(addr), val, memory_order_relaxed);
547558
#else
548559
S current;
549560
while ((current = *(volatile S*)addr) < val && !AtomicCASInternal(addr, current, val)) {
@@ -561,7 +572,7 @@ GPUdi() void GPUCommonMath::AtomicMinInternal(S* addr, T val)
561572
#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
562573
::atomicMin(addr, val);
563574
#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
564-
atomic_fetch_min_explicit(addr, val, memory_order_relaxed);
575+
atomic_fetch_min_explicit(GPUCommonMathMetalAtomic(addr), val, memory_order_relaxed);
565576
#else
566577
S current;
567578
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)