Skip to content

Commit ab2f083

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 68ca26c commit ab2f083

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
@@ -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: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,17 @@ GPUhdi() constexpr int32_t GPUCommonMath::Abs<int32_t>(int32_t x)
475475
return GPUCA_CHOICE(abs(x), abs(x), abs(x));
476476
}
477477

478+
#ifdef __METAL__
479+
// The counters these operate on are plain integers in the transferred structures,
480+
// as they are for CUDA and HIP. MSL's atomic operations want metal::atomic, which
481+
// has the same size and alignment; the overloads keep the address space, which a
482+
// generic pointer would not carry into atomic_*_explicit.
483+
template <class T>
484+
GPUdi() threadgroup metal::atomic<T>* GPUCommonMathMetalAtomic(threadgroup T* p) { return reinterpret_cast<threadgroup metal::atomic<T>*>(p); }
485+
template <class T>
486+
GPUdi() device metal::atomic<T>* GPUCommonMathMetalAtomic(T* p) { return (device metal::atomic<T>*)p; }
487+
#endif
488+
478489
template <class S, class T>
479490
GPUdi() uint32_t GPUCommonMath::AtomicExchInternal(S* addr, T val)
480491
{
@@ -485,7 +496,7 @@ GPUdi() uint32_t GPUCommonMath::AtomicExchInternal(S* addr, T val)
485496
#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
486497
return ::atomicExch(addr, val);
487498
#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
488-
return atomic_exchange_explicit(addr, val, memory_order_relaxed);
499+
return atomic_exchange_explicit(GPUCommonMathMetalAtomic(addr), val, memory_order_relaxed);
489500
#elif defined(WITH_OPENMP)
490501
uint32_t old;
491502
__atomic_exchange(addr, &val, &old, __ATOMIC_SEQ_CST);
@@ -505,7 +516,7 @@ GPUdi() bool GPUCommonMath::AtomicCASInternal(S* addr, T cmp, T val)
505516
#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
506517
return ::atomicCAS(addr, cmp, val) == cmp;
507518
#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
508-
return atomic_compare_exchange_weak_explicit(addr, &cmp, val, memory_order_relaxed, memory_order_relaxed);
519+
return atomic_compare_exchange_weak_explicit(GPUCommonMathMetalAtomic(addr), &cmp, val, memory_order_relaxed, memory_order_relaxed);
509520
#elif defined(WITH_OPENMP)
510521
return __atomic_compare_exchange(addr, &cmp, &val, true, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
511522
#else
@@ -523,7 +534,7 @@ GPUdi() uint32_t GPUCommonMath::AtomicAddInternal(S* addr, T val)
523534
#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
524535
return ::atomicAdd(addr, val);
525536
#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
526-
return atomic_fetch_add_explicit(addr, val, memory_order_relaxed);
537+
return atomic_fetch_add_explicit(GPUCommonMathMetalAtomic(addr), val, memory_order_relaxed);
527538
#elif defined(WITH_OPENMP)
528539
return __atomic_add_fetch(addr, val, __ATOMIC_SEQ_CST) - val;
529540
#else
@@ -541,7 +552,7 @@ GPUdi() void GPUCommonMath::AtomicMaxInternal(S* addr, T val)
541552
#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
542553
::atomicMax(addr, val);
543554
#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
544-
atomic_fetch_max_explicit(addr, val, memory_order_relaxed);
555+
atomic_fetch_max_explicit(GPUCommonMathMetalAtomic(addr), val, memory_order_relaxed);
545556
#else
546557
S current;
547558
while ((current = *(volatile S*)addr) < val && !AtomicCASInternal(addr, current, val)) {
@@ -559,7 +570,7 @@ GPUdi() void GPUCommonMath::AtomicMinInternal(S* addr, T val)
559570
#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
560571
::atomicMin(addr, val);
561572
#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
562-
atomic_fetch_min_explicit(addr, val, memory_order_relaxed);
573+
atomic_fetch_min_explicit(GPUCommonMathMetalAtomic(addr), val, memory_order_relaxed);
563574
#else
564575
S current;
565576
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)