C.W.K.
Stream
Lesson 05 of 05 · published

CUDA ↔ Metal Cheat Sheet

~10 min · metal, cuda, cheatsheet, comparison

Level 0Beginner
0 XP0/38 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

Same colony, different uniforms

Once you internalize this table, you can read either codebase in five minutes. The hardware concepts are identical; only the spellings differ.

CUDAMetalNotes
__global__ void kernel(...)kernel void kernel(...)GPU entry point launched by CPU.
__device__ float helper()(no qualifier — default for non-kernel)GPU-only helper.
kernel<<<grid, block>>>()encoder.dispatchThreadgroups(grid, threadsPerTG)Same two-level launch geometry.
blockIdx.x / threadIdx.x[[threadgroup_position_in_grid]] / [[thread_index_in_threadgroup]]SIMT indices.
warp (32 threads)SIMD-group (32 threads)Divergence + shuffle math identical.
__shared__ memorythreadgroup memoryOn-chip SRAM scratchpad shared by a (thread)group.
__constant__ memoryconstant address spaceSmall read-only LUTs.
__syncthreads()threadgroup_barrier(mem_flags::mem_threadgroup)Local sync + optional memory fence.
cudaMalloc / cudaMemcpydevice.makeBuffer(.storageModeShared)Apple Silicon: no copy needed.
cuBLASMPSMatrixMultiplicationVendor BLAS, both peak ~80% of theoretical.
nvccxcrun metal + metallibTwo-step build (compile, link to .metallib).

The few real differences:

  • Build pipeline. CUDA: one nvcc command emits an executable. Metal: metal compiles to .air, metallib links to .metallib, swiftc builds the host driver, and the .metallib is loaded at runtime.
  • printf vs buffer. CUDA has GPU printf. Metal forces a buffer round-trip. The buffer pattern is more production-shaped anyway.
  • Tensor units. Both have them — Tensor Cores on NVIDIA (mma.sync), matrix coprocessor on Apple. Both are wrapped by vendor BLAS.
  • Memory model. Discrete VRAM vs unified RAM (lesson 2 of this track).

Code

Same vector add, two languages — read them side by side·cuda
// CUDA
__global__ void vec_add(const float* A, const float* B,
                        float* C, int N) {
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    if (i < N) C[i] = A[i] + B[i];
}
Same vector add, Metal version·metal
// Metal
kernel void vec_add(
    const device float *A [[buffer(0)]],
    const device float *B [[buffer(1)]],
    device       float *C [[buffer(2)]],
    constant     uint  &N [[buffer(3)]],
    uint i                [[thread_position_in_grid]])
{
    if (i < N) C[i] = A[i] + B[i];
}

External links

Exercise

Print this cheat sheet (or save as a markdown file and pin in your editor). Each time you read or write a kernel for the next two lessons, glance at the row that corresponds to the construct you're using. By the end of Track 4 the table should be fully internalized; no print-out needed.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.