Inferensys

Glossary

Shared Memory

Shared memory is a small, low-latency, software-managed cache memory on a GPU that is shared between threads within a thread block, enabling high-speed communication and data reuse for cooperative parallel algorithms.
Data scientist building training data pipeline on laptop, data preprocessing visible, technical workspace.
GPU MEMORY OPTIMIZATION

What is Shared Memory?

A definition of shared memory, a critical low-latency memory resource in GPU programming for parallel algorithms.

Shared memory is a small, software-managed, on-chip cache memory on a GPU that is shared by all threads within a thread block, enabling high-speed data sharing and cooperative computation. It acts as a user-programmable scratchpad with latency comparable to an L1 cache, orders of magnitude faster than accessing global memory (device DRAM). Its primary function is to stage data for reuse, drastically reducing redundant global memory accesses and is fundamental to optimizing kernels for algorithms like matrix multiplication and reductions.

Efficient use requires careful design to avoid bank conflicts, where multiple threads contend for the same memory bank, causing serialized access. Programmers explicitly declare and manage data in shared memory using CUDA's __shared__ keyword or its equivalents in other frameworks. Its limited size—typically 16-48 KB per streaming multiprocessor—makes its allocation a key part of the occupancy calculation, balancing the number of concurrent thread blocks against available resources.

GPU MEMORY OPTIMIZATION

Key Characteristics of Shared Memory

Shared memory is a low-latency, programmable cache on a GPU that enables threads within a block to cooperate efficiently. Its unique properties are fundamental to writing high-performance parallel kernels.

01

Block-Local Scope

Shared memory is allocated per thread block and is only visible to the threads within that block. This provides a fast, private workspace for cooperative algorithms. Threads in different blocks cannot directly access each other's shared memory, enforcing a natural data isolation that simplifies synchronization.

  • Example: A block of threads processing a tile of a matrix can load the tile into shared memory, perform all calculations there, and then write the final result back to global memory.
02

Software-Managed Cache

Unlike the automatic L1/L2 hardware caches, shared memory is explicitly managed by the programmer. You control what data is placed into it and when. This requires more effort but allows for predictable, high-performance data reuse patterns that are optimal for a specific algorithm.

  • Contrast: The hardware cache is transparent but subject to unpredictable eviction. Shared memory provides deterministic, algorithm-aware caching.
03

Extremely Low Latency & High Bandwidth

Shared memory resides on-chip, physically close to the streaming multiprocessor (SM) cores. This gives it latency comparable to registers and bandwidth far exceeding global (device) memory. Accessing shared memory is typically orders of magnitude faster than accessing global DRAM.

  • Performance Impact: Kernels that stage data in shared memory for repeated access can see throughput improvements of 10x or more compared to kernels that read repeatedly from global memory.
04

Banked Memory Architecture

To achieve high bandwidth, shared memory is divided into equally sized, independently accessible modules called memory banks. Concurrent accesses to different banks can be serviced simultaneously, but accesses to the same bank cause a bank conflict, serializing the operations and reducing throughput.

  • Optimal Pattern: To avoid conflicts, ensure threads in a warp access addresses that map to different banks (e.g., stride-1 access for 32-bit words).
05

Synchronization Primitive

Shared memory acts as a rendezvous point, requiring explicit synchronization to ensure data written by some threads is visible to others. The __syncthreads() barrier is used to synchronize all threads in a block, guaranteeing memory consistency before proceeding.

  • Critical Use Case: In a parallel reduction or scan algorithm, threads write partial results to shared memory, call __syncthreads(), and then read the results written by their peers for the next computation stage.
06

Limited, Static Capacity

The amount of shared memory per streaming multiprocessor is a fixed hardware resource (e.g., 64KB or 128KB on modern NVIDIA GPUs). This capacity is statically allocated per thread block at kernel launch. Exceeding this limit will prevent the kernel from launching.

  • Trade-off: The programmer must balance shared memory usage against the number of concurrent thread blocks that can reside on an SM (occupancy). Using more shared memory per block can reduce occupancy and vice-versa.
GPU MEMORY OPTIMIZATION

How Shared Memory Works: Mechanism and Programming

Shared memory is a critical, low-latency resource in GPU programming that enables high-speed data sharing and cooperative algorithms within a thread block.

Shared memory is a small, software-managed cache memory on a GPU that is shared between all threads within a single thread block. It provides orders-of-magnitude lower latency and higher bandwidth than global device memory, acting as a programmer-controlled scratchpad for data reuse and inter-thread communication. Its limited size, typically 16-48 KB per Streaming Multiprocessor (SM), necessitates careful allocation and access pattern design to avoid performance pitfalls like bank conflicts.

Programming shared memory involves explicit data movement within a CUDA or HIP kernel using the __shared__ qualifier. Data is first loaded from high-latency global memory into shared memory in a coalesced pattern. Threads within the block can then perform numerous low-latency operations on this cached data. Effective use is fundamental to optimizing algorithms like matrix multiplication, reductions, and convolutional filters, where it dramatically reduces redundant global memory accesses and hides memory latency.

GPU MEMORY OPTIMIZATION

Common Use Cases in AI/ML

Shared memory is a critical low-level optimization for parallel algorithms on GPUs. Its primary use is to enable high-speed, cooperative computation within a thread block by acting as a software-managed cache.

01

Matrix Multiplication (GEMM)

The classic use case for shared memory is in optimizing General Matrix Multiply (GEMM) operations, the foundation of neural network layers. The algorithm proceeds in tiles:

  • Global memory loads a tile of matrix A and a tile of matrix B into shared memory.
  • All threads in the block cooperatively compute partial results from these fast, on-chip tiles.
  • This process repeats, accumulating results, minimizing costly accesses to slower global memory. This tiling strategy is fundamental to high-performance linear algebra libraries like cuBLAS and is directly analogous to the blocked computation in a transformer's attention or feed-forward layers.
02

Reduction Operations (Sum, Max)

Shared memory enables efficient parallel reduction algorithms, essential for operations like computing a sum, maximum, or softmax normalization across a dataset.

  • Threads first load data from global memory into shared memory.
  • A tree-based reduction is then performed within the block, where threads at each step combine partial results stored in shared memory.
  • This avoids repeated global memory accesses, drastically reducing latency. For example, computing the sum of logits for a softmax function across a vocabulary dimension heavily relies on this pattern.
03

Convolutional Neural Network (CNN) Filters

In CNNs, applying a filter (kernel) to an input image or feature map involves reusing input pixels for multiple output computations. Shared memory is used to stage a region of the input image:

  • A block of threads loads an input tile, plus a surrounding halo region (for the filter's overlap), from global memory into shared memory.
  • Each thread then repeatedly reads from this fast, on-chip cache to compute its output pixel, reusing the loaded input data for multiple convolutions.
  • This eliminates redundant global memory fetches, which is critical for the performance of vision models in real-time inference.
04

Attention Mechanism Key-Value Caching

While the full KV cache resides in global memory, shared memory acts as a critical staging area within the attention computation kernel for a single layer and head.

  • During the attention score calculation (Q @ K^T), tiles of the Key cache are loaded into shared memory to be reused by all queries in a block.
  • Similarly, during the output calculation (scores @ V), tiles of the Value cache are loaded.
  • This tiled approach via shared memory is essential for achieving high memory bandwidth utilization when computing self-attention for long sequences, a bottleneck in transformer inference.
05

Sorting and Parallel Primitives

High-performance sorting algorithms on the GPU, like radix sort or merge sort, use shared memory as a temporary workspace for data being rearranged within a block.

  • Bitonic sort and other parallel sorting networks are implemented within a thread block using shared memory for compare-and-swap operations.
  • Scan (prefix sum) operations, another fundamental primitive, are implemented using efficient shared memory algorithms before writing final results back to global memory. These primitives are building blocks for data preprocessing and reordering tasks in ML pipelines.
06

Custom Fused Kernels

To avoid kernel launch overhead and intermediate global memory writes, ML engineers write custom CUDA kernels that fuse multiple operations. Shared memory is the glue in these kernels.

  • Example: A kernel that performs layer normalization immediately after a matrix multiply can hold the intermediate results in shared memory, compute the mean and variance across threads, and apply the normalization—all without a round-trip to global memory.
  • Example: Fusing an activation function (like GELU or SiLU) with a preceding linear layer. This operator fusion, enabled by shared memory staging, is a key technique in inference engines like TensorRT and OpenAI's Triton to minimize latency.
MEMORY TIER COMPARISON

Shared Memory in the GPU Memory Hierarchy

A comparison of key memory types within the GPU memory hierarchy, highlighting the role of shared memory as a software-managed cache for thread block cooperation.

Feature / AttributeShared Memory (L1/SMEM)L2 CacheGlobal Memory (HBM/GDDR)Registers

Primary Function

Low-latency, programmable scratchpad for intra-block communication

Hardware-managed cache for global memory accesses

Primary high-capacity workspace for all GPU threads

Fastest storage for per-thread private variables

Scope / Visibility

Threads within a single thread block

All threads on the GPU (entire Streaming Multiprocessor array)

All threads and host CPU (via Unified Memory)

Private to a single thread

Software Management

Explicitly allocated and managed by programmer

Fully automatic, hardware-controlled

Explicitly allocated (cudaMalloc) or unified

Automatic, managed by compiler

Typical Size (per SM)

16-164 KB (configurable with L1)

Up to tens of MB (shared across GPU)

16-120 GB (total device capacity)

~256 KB (64K 32-bit registers per SM)

Access Latency (approx.)

~20-30 cycles

~200 cycles

~400-800 cycles

1 cycle

Bandwidth

~19 TB/s (on-chip)

~3-5 TB/s

~1-3 TB/s

80 TB/s

Addressable By

Thread block index + thread index

Hardware via cache lines

Global pointer (device pointer)

Thread ID

Key Optimization Concern

Bank conflicts, size limits, data reuse patterns

Cache line utilization, access coalescing

Coalesced access, memory traffic

Register pressure/spilling

Persistence Across Kernels

No (cleared per kernel launch)

No (volatile, data can be evicted)

Yes (persists until freed)

No (per-thread, per-kernel)

Common Use Case

Tiling for matrix multiplication, parallel reductions, fast look-up tables

Caching frequently accessed global data (e.g., model weights)

Storing model parameters, activations, large input/output tensors

Holding loop counters, temporary variables, frequently accessed operands

GPU MEMORY OPTIMIZATION

Frequently Asked Questions

Shared memory is a critical, low-level resource for optimizing parallel algorithms on GPUs. These questions address its core mechanics, performance implications, and practical use.

Shared memory is a small, software-managed, on-chip cache memory on a GPU that is shared between all threads within a single thread block. It operates as a programmer-controlled scratchpad, enabling high-speed data sharing and reuse. Unlike global memory (device DRAM), which has high latency, shared memory provides near-register speed access (approximately 1-2 orders of magnitude faster) but is limited in size (typically 16-48 KB per Streaming Multiprocessor).

Its operation is explicit: a kernel must load data from global memory into shared memory, perform computations using the shared data, and optionally write results back. This pattern, global -> shared -> compute, is fundamental for algorithms like matrix multiplication, reductions, and convolutions where threads within a block cooperate on a common data subset. The memory is partitioned into 32 equally sized memory banks (on most architectures) to enable high bandwidth. Proper management is essential, as incorrect use leads to bank conflicts or capacity exhaustion, negating its performance benefits.

Prasad Kumkar

About the author

Prasad Kumkar

CEO & MD, Inference Systems

Prasad Kumkar is the CEO & MD of Inference Systems and writes about AI systems architecture, LLM infrastructure, model serving, evaluation, and production deployment. Over 5+ years, he has worked across computer vision models, L5 autonomous vehicle systems, and LLM research, with a focus on taking complex AI ideas into real-world engineering systems.

His work and writing cover AI systems, large language models, AI agents, multimodal systems, autonomous systems, inference optimization, RAG, evaluation, and production AI engineering.