qd.init options#
qd.init(...) accepts a range of keyword options that tune how Quadrants compiles and runs your kernels; most are also settable as an environment variable of the form QD_<UPPERCASE_NAME> (e.g. QD_OFFLINE_CACHE=0). This page walks through the options most commonly tuned in practice; the full list of options is at the bottom.
Caching#
offline_cache#
Whether the compilation caches persist on disk across Python invocations. Default True. The “offline” in the name refers to the fact that this cache outlives the process: it is what makes the second time you start a Python interpreter and run a kernel cheap, by reusing artifacts from the first run.
Setting offline_cache=False is intended to emulate cold-start, i.e. a fresh Python process with no prior on-disk artifacts available. In-process caches operate independently of this flag: while a runtime is alive, identical kernels are not recompiled regardless of its value (though qd.reset() clears that in-process cache, so kernels recompile after a reset). The flag therefore controls only whether the next Python invocation observes a warm or a cold disk.
When offline_cache=True, compilation artifacts persist on disk under offline_cache_file_path (default ~/.cache/quadrants/qdcache), so a later Python process reuses them instead of recompiling. Setting offline_cache=False (or QD_OFFLINE_CACHE=0) forces a cold start: Quadrants recompiles kernels and neither reads nor writes its own on-disk cache. (On CUDA the driver keeps its own separate cache of compiled GPU code at ~/.nv/ComputeCache that this flag does not disable; offline_cache=False only stops that cache from serving results across runs. Set CUDA_CACHE_DISABLE=1 to turn it off entirely.)
The separate source-level cache used by fastcache kernels is controlled by src_ll_cache (on by default), not by offline_cache; with offline_cache=False it still writes its own bookkeeping files to disk, so set src_ll_cache=False as well to stop that too.
When to set it to False:
Taking compile-time profiles where a cached kernel would mask the real cost.
Investigating a stale-cache bug or suspected cache corruption.
Reproducing first-run behavior in CI matrix runs that would otherwise warm the caches across iterations.
For normal use, leave it at True; the caches are the main reason a repeated run starts up quickly.
Compile-time tuning#
cfg_optimization#
Whether to run the control-flow-graph optimization (an internal compile-time optimization of your kernel’s branches and loops). Default True. Setting it to False makes compilation up to 6x faster while costing 1-5% of runtime speed; consider disabling it if compile time is the bottleneck and the runtime delta is acceptable.
fast_math#
Whether to enable relaxed floating-point optimizations (fusing multiply-add operations, and dropping NaN / infinity / signed-zero guarantees). Default True. Disable when investigating numerical anomalies or running deterministic-tolerance tests.
num_compile_threads#
Number of host threads used to compile a single kernel’s internal tasks in parallel. Default 4. When Quadrants compiles a kernel it first splits it into several tasks (roughly one per parallel loop) and hands them to a pool of this many threads, so a kernel that splits into many tasks compiles faster on a machine with idle cores. (Distinct kernels are still each compiled lazily the first time they run; this option speeds up the compilation of one such kernel, not scheduling across kernels.) Lower it, or set 1, on memory-constrained systems where many concurrent compilations would thrash memory. Only the LLVM backends (CPU, CUDA, AMDGPU) use it.
Reverse-mode autodiff#
See Autodiff for the reverse-mode pipeline overview.
ad_stack_experimental_enabled#
Enables the dynamic-loop reverse-mode pipeline (the adstack). Default False. Required when a reverse-mode kernel has a runtime-bounded loop carrying a non-linear primal (a value computed on the forward pass that then feeds a non-linear operation); without it, such kernels either compile-error or produce silently-wrong gradients depending on the loop shape. See Autodiff with dynamic loops for the rules. Adstack-on is safe even when not strictly needed, but it does come with a few drawbacks:
Memory. The reverse pass replays each iteration of the dynamic loop, so the adstack stores per-iteration intermediate values for every thread. See Memory footprint for the exact formula and the knobs that shrink it (
ad_stack_size,ad_stack_sparse_threshold_bytes).Per-launch overhead. Every backward kernel launch incurs a small fixed CPU-to-GPU data transfer. Kernels whose dynamic loop is gated by a sparse predicate (e.g.
for i in range(n): if active[i] > 0: ...) additionally run a fast GPU pre-step that counts how many threads pass the gate so that the adstack can be tightly sized instead of upper-bounded by worst case.
Note. These drawbacks affect only reverse-mode kernels that actually use the adstack; forward-only kernels and reverse-mode kernels without a dynamic non-linear inner loop pay nothing extra. In other words, enabling adstack globally is effectively free except for kernels that need it anyway!
ad_stack_size#
Forces every adstack in the program to exactly N slots and bypasses the launch-time sizer. Default 0, meaning “let the sizer decide” (the recommended setting for day-to-day use). Setting a positive N is meant for stress tests or working around a suspected sizer bug; it defeats the per-launch-exact sizing so every dispatch allocates the full N slots whether or not the kernel actually needs them. Has no effect when ad_stack_experimental_enabled=False.
ad_stack_sparse_threshold_bytes#
Cutoff (in bytes) below which the gate-passing-count sizing path described in Memory footprint is skipped in favor of the eager worst-case heap (sized for the full thread count instead of the gate-passing count). Default 100 MiB. The sparse path saves memory on kernels of the shape for i in range(...): if field[i] cmp literal: <adstack work> but pays a per-launch reducer dispatch; below the threshold that overhead outweighs the savings. Set to 0 to always use the sparse path; lower it if the default still skips kernels you want shrunk. No effect when ad_stack_experimental_enabled=False or when the kernel has no such gate.
Apple Metal#
external_metal_command_queue#
An MTLCommandQueue* pointer (as an integer) to use instead of creating a new Metal command queue. Default 0 (create a new queue). When non-zero, Quadrants dispatches all GPU work on the provided queue, which enables GPU-side ordering with other frameworks that share the same queue (most notably PyTorch MPS).
external_metal_command_queue_is_torch_queue#
Default False. Set to True when the external_metal_command_queue is PyTorch MPS’s command queue. This tells Quadrants that both frameworks share the same Metal queue, so the explicit qd.sync() / torch.mps.synchronize() calls at to_torch / from_torch interop points can be skipped. When False (or when no external queue is set), the interop syncs are preserved.
See Shared Metal command queue for the full setup guide, including how to extract the queue pointer from PyTorch and the synchronization implications.
Debugging#
See Debug mode for runnable examples and a typical develop / benchmark workflow.
debug#
Default False. Turns on every available correctness check. Use while iterating on a kernel that produces wrong numerics; turn off for benchmarks and production.
Enables:
field-bounds check on tensor indexing (out-of-range index raises
RuntimeError);kernel
assertstatements;integer-overflow guards on arithmetic;
extra internal consistency checks throughout compilation.
The adstack-overflow check on reverse-mode autodiff runs unconditionally on every backend regardless of debug; see Autodiff -> What can go wrong for the contract.
Cost. Significant on both compile time (extra checks are inserted and validated throughout compilation; e.g. ~21s of added compile time observed on adstack-heavy kernels) and runtime. For just the field-bounds check in a release build without the rest, use check_out_of_bound below.
check_out_of_bound#
Default False. Enables the field-bounds check on tensor indexing - an out-of-range index raises RuntimeError.
Cost. Scales with how often kernels index into tensors. Cheaper than debug=True. Still leave off for benchmarks.
Interaction with debug:
Flags |
Field bounds |
Other |
|---|---|---|
neither |
off |
off |
|
on |
off |
|
on |
on |
debug=Truealways impliescheck_out_of_bound=True(the field-bounds check fires whenever debug mode is on).
Per-backend support:
Backend |
Field bounds check |
|---|---|
CPU |
with |
CUDA |
with |
AMDGPU |
with |
Metal |
never (no in-kernel assertion mechanism) |
Vulkan |
never (no in-kernel assertion mechanism) |
Metal and Vulkan lack the assertion extension that the field-bounds check relies on; check_out_of_bound=True is silently reset to False on those backends at qd.init time and a warning is logged.
All options#
Most qd.init keywords set a compiler-configuration option. Each option below can be passed as a keyword argument to qd.init(...), and after initializing a compiled backend it is also readable and writable as an attribute on the configuration object qd.cfg (e.g. qd.cfg.opt_level). Because each option is both a qd.init argument and a qd.cfg attribute, the list below documents each as a property of qd.cfg, with its type, default value, and a short description.
These are compiler settings, so most do not apply to the pure-Python qd.python backend, for which qd.cfg is None. A few instead set language defaults (such as the default numeric types default_fp and default_ip) and still take effect on qd.python.
- class CompileConfig#
- property ad_stack_experimental_enabled: bool#
Enable the reverse-mode autodiff pipeline for kernels with runtime-bounded loops (the adstack).
Default:
False.
- property ad_stack_size: int#
Force autodiff stacks to exactly this many slots. 0 lets the launch-time sizer choose automatically. No effect unless ad_stack_experimental_enabled is on.
Default:
0.
- property ad_stack_sparse_threshold_bytes: int#
Byte cutoff below which the sparse adstack sizing path is skipped in favor of eager heap allocation. No effect unless ad_stack_experimental_enabled is on.
Default:
104857600.
- property advanced_optimization: bool#
Run the full advanced optimization pass pipeline.
Default:
True.
- property arch: Arch#
Target backend the kernels run on (e.g. qd.cpu, qd.cuda, qd.vulkan, qd.metal). Defaults to qd.cpu when arch is not specified.
- property auto_mesh_local_default_occupacy: int#
Target occupancy used by the automatic mesh-local optimization. Only used on CUDA when experimental_auto_mesh_local is enabled.
Default:
4.
- property cache_loop_invariant_global_vars: bool#
Cache loop-invariant global loads into locals inside loops.
Default:
True.
- property cfg_optimization: bool#
Run the control-flow-graph optimization pass that simplifies kernel branches and loops. Disabling it speeds up compilation at a small runtime cost. Only runs when advanced_optimization is on and opt_level > 0 (both true by default).
Default:
True.
- property check_out_of_bound: bool#
Enable the field out-of-bounds check on tensor indexing without turning on the rest of debug mode. Reset to off (with a warning) on backends without assertion support, i.e. Vulkan and Metal.
Default:
False.
- property cpu_block_dim_adaptive: bool#
Intended to let the CPU backend choose the parallel-for block size adaptively; currently has no effect, as nothing reads it (the CPU block size is always default_cpu_block_dim).
Default:
True.
- property cpu_max_num_threads: int#
Maximum number of CPU threads used to run kernels (the runtime thread pool and CPU parallel-for loops). Compilation threads are governed separately by num_compile_threads.
Default: the number of available CPU cores.
- property cuda_stack_limit: int#
Per-thread CUDA stack size limit in bytes (0 uses the driver default).
Default:
0.
- property debug: bool#
field out-of-bounds (implies check_out_of_bound) and runtime assertions. Considerably slower; intended for development.
- Type:
Turn on the full suite of correctness checks
Default:
False.
- property debug_dump_path: str#
the IR-printing ones (e.g. print_ir) go to stdout, while the LLVM-IR and assembly ones (e.g. print_kernel_llvm_ir, print_kernel_asm) write files in the current working directory.
- Type:
Directory for IR dumps written and read via the QD_DUMP_IR, QD_DUMP_CFG, and QD_LOAD_IR environment variables. The print_* options ignore this path
Default:
'/tmp/ir/'.
- property default_cpu_block_dim: int#
Number of iterations per CPU parallel-for block.
Default:
32.
- property default_fp: DataTypeCxx#
Default floating-point type for fields and kernels (e.g. qd.f32).
Default:
qd.f32.
- property default_gpu_block_dim: int#
Default GPU thread-block size.
Default:
128.
- property default_ip: DataTypeCxx#
Default signed-integer type for fields and kernels (e.g. qd.i32).
Default:
qd.i32.
- property demote_dense_struct_fors: bool#
Lower dense struct-for loops to ordinary range-for loops. Forced on for the Vulkan/Metal (SPIR-V) backends, where the value you pass is ignored.
Default:
True.
- property demote_no_access_mesh_fors: bool#
Demote mesh-for loops that never access mesh attributes to range-fors.
Default:
True.
- property detect_read_only: bool#
Detect read-only field accesses to enable further optimization.
Default:
True.
- property device_memory_GB: float#
Amount of GPU memory, in gigabytes, to preallocate. Used on the fallback allocator path, and on pool-supporting CUDA/AMDGPU drivers when the program uses sparse (non-dense) fields; for an all-dense program on a pool driver it is ignored (allocation is on demand).
Default:
1.0.
- property device_memory_fraction: float#
the fallback allocator path, plus pool-supporting drivers when the program uses sparse (non-dense) fields.
- Type:
Fraction of total GPU memory to preallocate (overrides device_memory_GB when greater than 0). Same applicability as device_memory_GB
Default:
0.0.
- property experimental_auto_mesh_local: bool#
Enable the experimental automatic mesh-local optimization. CUDA only.
Default:
False.
- property external_metal_command_queue: int#
An MTLCommandQueue pointer (as an integer) to dispatch on instead of creating a new Metal queue. 0 means create a new queue.
Default:
0.
- property external_metal_command_queue_is_torch_queue: bool#
Set True when external_metal_command_queue is PyTorch MPS’s own queue, to skip redundant interop synchronization.
Default:
False.
- property fast_math: bool#
Allow IEEE-relaxed floating-point optimizations (e.g. fused multiply-add). Faster, but drops strict NaN/inf/signed-zero guarantees.
Default:
True.
- property flatten_if: bool#
Flatten simple if statements into predicated (branchless) form.
Default:
False.
- property force_scalarize_matrix: bool#
Always scalarize matrices, even where vectorized code would be legal.
Default:
False.
- property gpu_max_reg: int#
Intended to cap the number of registers per GPU thread (0 = driver default); currently has no effect, as the value is not yet passed to the GPU JIT.
Default:
0.
- property half2_vectorization: bool#
Vectorize pairs of float16 operations into half2 ops. CUDA only, and only when real_matrix_scalarize is also enabled.
Default:
False.
- property kernel_profiler: bool#
Enable the on-device kernel profiler to collect per-kernel timings. Only the CPU, CUDA, and AMDGPU backends emit the timing hooks; on Vulkan/Metal it produces no per-kernel timings.
Default:
False.
- property lower_access: bool#
Intended to lower high-level field accesses to low-level pointer arithmetic; currently has no effect, as nothing reads it (this lowering always runs).
Default:
True.
- property make_block_local: bool#
Enable the block-local optimization, which stages spatially-local field accesses through GPU shared memory. CUDA only (the required BLS extension is CUDA-only). Mesh attribute localization is a separate pass controlled by make_mesh_block_local.
Default:
True.
- property make_cpu_multithreading_loop: bool#
Parallelize outer loops across CPU threads.
Default:
True.
- property make_mesh_block_local: bool#
Enable the block-local optimization for MeshQuadrants attributes. CUDA only (the pass runs only when arch is CUDA).
Default:
True.
- property make_thread_local: bool#
Enable the thread-local optimization for reductions. Honored on the LLVM backends (CPU, CUDA, AMDGPU) only; the Vulkan/Metal (SPIR-V) path forces it off.
Default:
True.
- property max_block_dim: int#
Intended as an upper bound on GPU block size, but currently limits only the block size of internal list-generation kernels; ordinary range-for/struct-for launches use default_gpu_block_dim instead. 0 means no cap.
Default:
0.
- property mesh_localize_all_attr_mappings: bool#
Localize all mesh attribute mappings, not just the ones detected as beneficial. Used by the CUDA-only make_mesh_block_local pass, and ignored when experimental_auto_mesh_local is enabled.
Default:
False.
- property mesh_localize_from_end_mapping: bool#
Cache mesh relation from-end mappings in block-local memory. Only used by the CUDA-only make_mesh_block_local pass.
Default:
False.
- property mesh_localize_to_end_mapping: bool#
Cache mesh relation to-end mappings in block-local memory. Only used by the CUDA-only make_mesh_block_local pass.
Default:
True.
- property move_loop_invariant_outside_if: bool#
Hoist loop-invariant computations out of conditional branches. Runs only within the advanced_optimization pipeline.
Default:
False.
- property num_compile_threads: int#
Number of host threads used to compile kernels on the LLVM backends (CPU, CUDA, AMDGPU); other backends ignore it, and it is forced to 1 when print_ir is set.
Default:
4.
- property offline_cache: bool#
Whether compiled-kernel caches persist on disk and are reused across separate Python processes.
Default:
True.
- property offline_cache_cleaning_factor: float#
Fraction of the compiled-kernel offline cache to evict once it exceeds the size limit. Applied only under the “lru” and “fifo” cleaning policies; “version” does no size-based eviction.
Default:
0.25.
- property offline_cache_cleaning_policy: str#
Eviction policy for the compiled-kernel offline cache (“never”, “version”, “lru”, or “fifo”).
Default:
'lru'.
- property offline_cache_file_path: str#
Directory that holds the on-disk compilation cache.
Default: the per-user Quadrants cache directory (
~/.cache/quadrants/qdcacheon Linux).
- property offline_cache_max_size_of_files: int#
Maximum total size, in bytes, of the compiled-kernel offline cache before cleaning. This bounds only that cache, not the CUDA PTX cache or the source-level fastcache, so the on-disk cache directory can grow beyond it.
Default:
104857600.
- property opt_level: int#
Quadrants IR optimization level. At 0, IR-level optimizations such as common-subexpression elimination are disabled; any value above 0 enables them. This is not an LLVM -O level.
Default:
1.
- property optimize_mesh_reordered_mapping: bool#
Optimize element access through reordered mesh index mappings.
Default:
True.
- property print_accessor_ir: bool#
Also include field accessor kernels in the IR printout. Only has an effect together with print_ir on the LLVM backends, which otherwise suppress accessor kernels.
Default:
False.
- property print_ir: bool#
some passes are not instrumented, so a few intermediate stages are not shown.
- Type:
Trace each kernel’s IR through compilation by printing it at labeled checkpoints across the pipeline (for debugging the compiler), rather than as a single dump at the end. Coverage is not exhaustive
Default:
False.
- property print_ir_dbg_info: bool#
Include source-line debug info in the print_ir checkpoint output. Has no effect on other IR dumps such as print_preprocessed_ir.
Default:
False.
- property print_kernel_amdgcn: bool#
Print the AMDGCN assembly generated for each kernel (AMD backend).
Default:
False.
- property print_kernel_asm: bool#
native assembly on CPU, PTX (not native SASS) on CUDA.
- Type:
Print the assembly generated for each kernel
Default:
False.
- property print_kernel_llvm_ir: bool#
Print the LLVM IR generated for each kernel.
Default:
False.
- property print_kernel_llvm_ir_optimized: bool#
Print each kernel’s LLVM IR after LLVM optimization.
Default:
False.
- property print_preprocessed_ir: bool#
Print each kernel’s IR right after frontend preprocessing. Only prints when print_ir is off (print_ir already shows the initial IR).
Default:
False.
- property print_struct_llvm_ir: bool#
Print the LLVM IR generated for the data-structure (SNode) module.
Default:
False.
- property quant_opt_atomic_demotion: bool#
Demote atomics to plain read-modify-write on quantized fields when safe.
Default:
True.
- property quant_opt_store_fusion: bool#
Fuse consecutive stores to quantized (bit-packed) fields.
Default:
True.
- property raise_on_templated_floats: bool#
Raise an error instead of silently specializing a kernel on a Python float it reads as a templated argument or a captured global variable (each distinct value would otherwise force its own compile).
Default:
False.
- property random_seed: int#
Seed for Quadrants’ random-number generation.
Default:
0.
- property real_matrix_scalarize: bool#
Scalarize matrix/vector operations into per-component scalar ops.
Default:
True.
- property saturating_grid_dim: int#
reverse-mode kernels that carry an autodiff stack launch with a smaller grid, capped so the concurrent thread count stays within 65536. Vulkan/Metal compute their dispatch grid automatically and ignore this.
- Type:
Target GPU grid size (number of blocks) on the CUDA/AMDGPU backends; 0 lets Quadrants pick based on occupancy. It is an upper bound rather than a guarantee
Default:
0.
- property simplify_after_lower_access: bool#
Intended to run the simplify pass after the lower-access pass; currently has no effect, as nothing reads it.
Default:
True.
- property simplify_before_lower_access: bool#
Intended to run the simplify pass before the lower-access pass; currently has no effect, as nothing reads it.
Default:
True.
- property timeline: bool#
Record a chrome-tracing timeline of GPU kernel execution, sourced from the CUDA/AMDGPU kernel profiler (so kernel_profiler must be enabled). Compilation is not recorded.
Default:
False.
- property use_llvm: bool#
Intended to select the LLVM backend for code generation; currently has no effect, as nothing reads it.
Default:
True.
- property verbose: bool#
Intended to print verbose logging during initialization and compilation; currently has no effect.
Default:
True.
- property verbose_kernel_launches: bool#
Intended to log a message on every kernel launch; currently has no effect.
Default:
False.
- property vk_api_version: str#
Vulkan API version to request, as a “major.minor.patch” string (e.g. “1.3.0”). Empty lets Quadrants select a usable version automatically.
Default:
''.
qd.init also accepts a number of options that are handled on the Python side and so do not appear in the generated list above. Some can only be set in the qd.init call; others are also reachable through a QD_ environment variable, as noted per option:
enable_fallback(bool, defaultTrue): fall back to the CPU backend when the requestedarchis unavailable, instead of raising an error. No environment variable equivalent.src_ll_cache(bool, defaultTrue): use an additional source-level on-disk cache that speeds up loading previously compiled kernels. It only applies to kernels declared@qd.kernel(fastcache=True)(or the deprecated@qd.kernel(pure=True); see fastcache). Reusing a kernel’s compiled code across processes also needs the offline cache, so withoffline_cache=Falseit no longer speeds up loading, but it still does source-cache bookkeeping on disk; setsrc_ll_cache=Falseto turn it off entirely. No environment variable equivalent.require_version(str): raise an error unless the installed Quadrants version is compatible with the givenmajor.minor.patchstring (same major version, and at least the given minor and patch). No environment variable equivalent.print_non_pure(bool, defaultFalse): print the name of each executed kernel that is not declared pure, i.e. not marked@qd.kernel(fastcache=True)(or the deprecated@qd.kernel(pure=True)). This is a declaration check, not an analysis of what the kernel actually touches: a plain@qd.kernelis reported even if it only uses its explicit parameters. Only kernels declared pure can use fastcache to speed up load, so use this to find kernels that could opt in. No environment variable equivalent.log_level(str, default"info"): logging verbosity; one of"trace","debug","info","warn","error","critical", or"off"to disable logging (also settable viaQD_LOG_LEVEL).gdb_trigger(bool, defaultFalse): drop into gdb when Quadrants’ compiled C++ runtime crashes (a native crash rather than a Python exception) (also settable viaQD_GDB_TRIGGER).short_circuit_operators(bool, defaultTrue): use short-circuit evaluation forand/orinside kernels (also settable viaQD_SHORT_CIRCUIT_OPERATORS).print_full_traceback(bool, defaultFalse): print the full Python traceback when an exception propagates out of Quadrants (also settable viaQD_PRINT_FULL_TRACEBACK).unrolling_limit(int, default32): maximum number of iterations a static loop may be unrolled before a warning is emitted;0disables the warning (also settable viaQD_UNROLLING_LIMIT).