Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
4849cda
GPU: Apple Metal backend, off by default
ktf Sep 25, 2026
4f7beb0
GPU: give Metal its own definitions of the double math helpers
ktf Sep 25, 2026
2d85bbd
GPU: give Metal a column in the tuning parameter table
ktf Sep 25, 2026
b645c0b
GPU: give Metal its own spellings for three math helpers
ktf Sep 25, 2026
9a36019
GPU: extend two existing OpenCL device workarounds to Metal
ktf Sep 25, 2026
75b4170
GPU: make the kernel entry-point signature work on Metal
ktf Sep 25, 2026
0c0a01a
GPU: number the kernel arguments so Metal can bind them
ktf Sep 25, 2026
9f296a3
GPU: give Metal an IEEE-754 binary64 in software
ktf Sep 25, 2026
bf75199
GPU: give Metal an entry in the no-fast-math table
ktf Sep 25, 2026
219acc9
GPU: take the work-item indices from the kernel parameters
ktf Sep 25, 2026
00909d6
MathUtils: extend the OpenCL sincos workaround to Metal
ktf Sep 25, 2026
68ca26c
GPU: reach global memory through the generic address space on Metal
ktf Sep 25, 2026
ab2f083
GPU: make the Metal atomics operate on plain counters
ktf Sep 25, 2026
1b3f1da
GPUTracking: declare the resolve kernel's shared memory as shared
ktf Sep 25, 2026
c8ce55e
GPUTracking: rename the cluster finder's fragment to frag
ktf Sep 25, 2026
7d75d71
GPU: let the constant-address-space constants be built on Metal
ktf Sep 25, 2026
f97c908
GPU: make std::is_pointer address-space aware on Metal
ktf Sep 25, 2026
f7d0bbc
GPUTracking: replace the merger's goto with a flag
ktf Sep 25, 2026
ba3e057
MathUtils: let bringTo* deduce the type of the call they forward to
ktf Sep 25, 2026
935e863
ReconstructionDataFormats: use the MatrixD5 alias in the Kalman gain …
ktf Sep 25, 2026
926fc42
GPU: hand the kernel pointers to Thread() as generic pointers
ktf Sep 25, 2026
2743450
MathUtils: make getMean()'s ternary unambiguous for an emulated double
ktf Sep 25, 2026
743edc9
MathUtils: declare fastATan2's Pi where its lambdas can use it
ktf Sep 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
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.
  • Loading branch information
ktf committed Sep 25, 2026
commit ab2f08346036b94feef3a71c7f2ff9e4456c6458
2 changes: 1 addition & 1 deletion GPU/Common/GPUCommonDefAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@
#define GPUdouble() float
#define GPUbarrier() threadgroup_barrier(mem_flags::mem_device | mem_flags::mem_threadgroup)
#define GPUbarrierWarp() simdgroup_barrier(mem_flags::mem_device | mem_flags::mem_threadgroup)
#define GPUAtomic(type) atomic<type> // atomic variable type
#define GPUAtomic(type) type // atomic variable type
#elif defined(__HIPCC__) //Defines for HIP
#define GPUd() __device__
#define GPUdDefault() __device__
Expand Down
21 changes: 16 additions & 5 deletions GPU/Common/GPUCommonMath.h
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,17 @@ GPUhdi() constexpr int32_t GPUCommonMath::Abs<int32_t>(int32_t x)
return GPUCA_CHOICE(abs(x), abs(x), abs(x));
}

#ifdef __METAL__
// The counters these operate on are plain integers in the transferred structures,
// as they are for CUDA and HIP. MSL's atomic operations want metal::atomic, which
// has the same size and alignment; the overloads keep the address space, which a
// generic pointer would not carry into atomic_*_explicit.
template <class T>
GPUdi() threadgroup metal::atomic<T>* GPUCommonMathMetalAtomic(threadgroup T* p) { return reinterpret_cast<threadgroup metal::atomic<T>*>(p); }
template <class T>
GPUdi() device metal::atomic<T>* GPUCommonMathMetalAtomic(T* p) { return (device metal::atomic<T>*)p; }
#endif

template <class S, class T>
GPUdi() uint32_t GPUCommonMath::AtomicExchInternal(S* addr, T val)
{
Expand All @@ -485,7 +496,7 @@ GPUdi() uint32_t GPUCommonMath::AtomicExchInternal(S* addr, T val)
#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
return ::atomicExch(addr, val);
#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
return atomic_exchange_explicit(addr, val, memory_order_relaxed);
return atomic_exchange_explicit(GPUCommonMathMetalAtomic(addr), val, memory_order_relaxed);
#elif defined(WITH_OPENMP)
uint32_t old;
__atomic_exchange(addr, &val, &old, __ATOMIC_SEQ_CST);
Expand All @@ -505,7 +516,7 @@ GPUdi() bool GPUCommonMath::AtomicCASInternal(S* addr, T cmp, T val)
#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
return ::atomicCAS(addr, cmp, val) == cmp;
#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
return atomic_compare_exchange_weak_explicit(addr, &cmp, val, memory_order_relaxed, memory_order_relaxed);
return atomic_compare_exchange_weak_explicit(GPUCommonMathMetalAtomic(addr), &cmp, val, memory_order_relaxed, memory_order_relaxed);
#elif defined(WITH_OPENMP)
return __atomic_compare_exchange(addr, &cmp, &val, true, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
#else
Expand All @@ -523,7 +534,7 @@ GPUdi() uint32_t GPUCommonMath::AtomicAddInternal(S* addr, T val)
#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
return ::atomicAdd(addr, val);
#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
return atomic_fetch_add_explicit(addr, val, memory_order_relaxed);
return atomic_fetch_add_explicit(GPUCommonMathMetalAtomic(addr), val, memory_order_relaxed);
#elif defined(WITH_OPENMP)
return __atomic_add_fetch(addr, val, __ATOMIC_SEQ_CST) - val;
#else
Expand All @@ -541,7 +552,7 @@ GPUdi() void GPUCommonMath::AtomicMaxInternal(S* addr, T val)
#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
::atomicMax(addr, val);
#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
atomic_fetch_max_explicit(addr, val, memory_order_relaxed);
atomic_fetch_max_explicit(GPUCommonMathMetalAtomic(addr), val, memory_order_relaxed);
#else
S current;
while ((current = *(volatile S*)addr) < val && !AtomicCASInternal(addr, current, val)) {
Expand All @@ -559,7 +570,7 @@ GPUdi() void GPUCommonMath::AtomicMinInternal(S* addr, T val)
#elif defined(GPUCA_GPUCODE) && (defined(__CUDACC__) || defined(__HIPCC__))
::atomicMin(addr, val);
#elif defined(GPUCA_GPUCODE) && defined(__METAL__)
atomic_fetch_min_explicit(addr, val, memory_order_relaxed);
atomic_fetch_min_explicit(GPUCommonMathMetalAtomic(addr), val, memory_order_relaxed);
#else
S current;
while ((current = *(volatile S*)addr) > val && !AtomicCASInternal(addr, current, val)) {
Expand Down
4 changes: 2 additions & 2 deletions GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ using namespace o2::tpc::constants;
// ===========================================================================

template <>
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)
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)
{
GPUTPCCFDecodeZS::decode(clusterer, smem, nBlocks, nThreads, iBlock, iThread, firstHBF, tpcTimeBinCut);
}

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)
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)
{
const uint32_t sector = clusterer.mISector;
#ifdef GPUCA_GPUCODE
Expand Down
4 changes: 2 additions & 2 deletions GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class GPUTPCCFDecodeZS : public GPUKernelTemplate
decodeZS,
};

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);
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);

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

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

class GPUTPCCFDecodeZSLinkBase : public GPUKernelTemplate
Expand Down