Skip to main content

Module occupancy

Module occupancy 

Source
Expand description

CUDA Occupancy Calculator (CPU-side, analytical).

This module implements the standard NVIDIA occupancy model: given a kernel’s per-thread/per-block resource usage and the architectural limits of a streaming multiprocessor (SM), it computes how many thread blocks and warps can be co-resident on a single SM, the resulting occupancy (the ratio of resident warps to the hardware maximum), and which resource is the binding constraint. It also provides an optimal_block_size search analogous to cudaOccupancyMaxPotentialBlockSize.

Nothing here queries a GPU — every value is derived from documented architectural constants and integer arithmetic, so the calculator is deterministic and works on any host.

§Model

For a block of threads_per_block threads on an SM with warp_size threads per warp:

warps_per_block      = ceil(threads_per_block / warp_size)
blocks_by_warps      = max_warps_per_sm / warps_per_block
blocks_by_registers  = registers_per_sm
                       / round_up(registers_per_thread * threads_per_block,
                                  register_alloc_granularity)
blocks_by_shared_mem = shared_mem_per_sm / shared_mem_per_block
blocks_by_cap        = max_blocks_per_sm

active_blocks = min(blocks_by_warps, blocks_by_registers,
                    blocks_by_shared_mem, blocks_by_cap)
active_warps  = active_blocks * warps_per_block
occupancy     = active_warps / max_warps_per_sm

The register term uses a per-block allocation rounded up to register_alloc_granularity (256 32-bit registers on every architecture modelled here). This is a deliberately simple approximation of the hardware’s per-warp register allocation; for block sizes that are whole multiples of the warp size (the common case) it coincides with the per-warp model.

A registers_per_thread of 0 is treated as “no register pressure” (unlimited), and a shared_mem_per_block of 0 is treated as “no shared memory pressure” (unlimited), so those resources never bound occupancy.

§Example

use optirs_gpu::{calculate_occupancy, KernelResourceUsage, SmResourceLimits};

let limits = SmResourceLimits::sm_80();
let usage = KernelResourceUsage::new(32, 0, 256);
let result = calculate_occupancy(&usage, &limits).expect("valid configuration");
assert_eq!(result.active_blocks_per_sm, 8);
assert!((result.occupancy - 1.0).abs() < 1e-9);

Structs§

KernelResourceUsage
Per-kernel resource usage that drives the occupancy calculation.
OccupancyResult
Result of an occupancy calculation for a single SM.
SmResourceLimits
Architectural per-SM resource limits for a streaming multiprocessor.

Enums§

OccupancyLimiter
The resource that bounds occupancy for a given kernel/SM combination.

Functions§

calculate_occupancy
Compute SM occupancy for a kernel with the given resource usage.
occupancy_for_launch
Convenience wrapper computing occupancy for a crate::backends::LaunchConfig.
optimal_block_size
Search for the block size that maximises occupancy (à la cudaOccupancyMaxPotentialBlockSize).