Skip to main content

CUDA performance guide

CUDA Memory Coalescing: what to measure and why

Global memory serves a warp through memory transactions. Accesses are efficient when the addresses requested by participating threads can be satisfied with few transactions and the fetched bytes are actually used. Scattered or strided addresses usually require more transactions and waste bandwidth.

The mechanism

What cuda memory coalescing means

When a warp executes a global load or store, the hardware examines the addresses requested by its threads and combines them into the transactions needed for those addresses. Current CUDA guidance discusses global memory in terms of 32-byte transactions. Consecutive threads accessing consecutive 4-byte words can make productive use of each fetched segment; a large stride can make each thread require a different segment while using only a small part of it.

  • Coalescing is a property of the warp’s address pattern for a specific memory instruction.
  • Useful bytes divided by transferred bytes is a practical way to reason about efficiency.
  • Alignment, element size, active lanes, cache behavior, and compute capability affect the observed transactions.
  • A kernel can have high occupancy and still be limited by inefficient global-memory access.

A minimal pattern

Change one thing at a time

The snippets isolate the address or launch pattern being discussed. A real optimization still has to preserve output and be measured in the complete kernel.

Strided access

const int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i < count) {
  output[i] = input[i * stride];
}

Adjacent access

const int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i < count) {
  output[i] = input[i];
}

Profiler evidence

What to measure

Check correctness and required data semantics before changing the layout. Then compare kernel duration, bytes requested, sectors or transactions, memory throughput, and global-load or global-store efficiency. Source correlation is especially valuable because a kernel may contain several memory instructions with very different access patterns.

Reason about the result

How to interpret the measurements

Fewer transactions for the same useful work usually indicate better coalescing. Runtime improves when global-memory service was important enough to limit the kernel. If transaction efficiency improves without a runtime change, another limit—such as instruction throughput, synchronization, latency elsewhere, or insufficient problem size—may dominate the measured run.

Avoid false conclusions

Common mistakes

  • Changing an index expression without preserving the algorithm’s required data mapping.
  • Assuming every non-unit stride has the same cost on every architecture and data type.
  • Looking only at aggregate bandwidth instead of the specific source instruction causing excess transactions.
  • Optimizing one load while introducing scattered stores or additional synchronization elsewhere.

Primary reference

This guide follows NVIDIA's published CUDA programming and performance guidance. Hardware details can change by compute capability, so verify architecture-specific behavior when exact mapping matters.

NVIDIA CUDA Programming Guide: Coalesced Global Memory Access

Measure it yourself

Turn the concept into a GPU experiment

Edit a CUDA problem, run it on managed NVIDIA hardware, and inspect the evidence in GPUFlight.

Explore memory labs in Performance Lab