Principle:Pyro ppl Pyro Global Configuration
| Knowledge Sources | |
|---|---|
| Domains | Software Architecture, Configuration Management, Probabilistic Programming |
| Last Updated | 2026-02-09 09:00 GMT |
Overview
Global configuration provides a centralized registry of settings that control the behavior of the probabilistic programming system, including validation modes, backend selection, and module resolution.
Description
A probabilistic programming framework must balance several concerns that are best controlled through global settings rather than per-call parameters:
Validation mode: During development, it is valuable to perform extensive validation (checking tensor shapes, distribution support constraints, handler stack integrity). In production or benchmarking, this validation overhead should be disabled. A global validation flag controls this trade-off.
Backend selection: Pyro supports multiple computational backends (e.g., standard PyTorch vs. Funsor for tensor variable elimination). The active backend determines which implementation of key operations is used. This must be a global setting because it affects the behavior of all sample statements.
Module resolution: In a modular system, different components may be swapped in and out. Global configuration provides a registry where components register themselves and consumers look up the active implementation.
Debug settings: Controlling the verbosity of logging, the behavior on numerical errors (NaN, inf), and whether to print trace information during execution.
The configuration system typically supports:
- Thread-safe access: Multiple threads can read settings concurrently.
- Context-manager overrides: Temporarily change a setting within a code block, then restore the original value.
- Validation: Settings are type-checked and range-checked when set.
- Discoverability: All available settings are documented and queryable.
Utility functions complement the settings by providing general-purpose helpers used throughout the codebase: random seed management, device placement, dtype control, and other cross-cutting concerns.
Usage
Use global configuration when:
- Enabling or disabling validation checks during development vs. production.
- Switching between computational backends (e.g., standard vs. Funsor).
- Setting global random seeds for reproducibility.
- Controlling debug output and error handling behavior.
- Managing device placement (CPU vs. GPU) and numeric precision (float32 vs. float64).
Theoretical Basis
Configuration registry pattern:
# Central registry with typed settings:
class Settings:
_defaults = {
"validate_distributions": True,
"validate_poutine": True,
"module_local_params": False,
}
_current = dict(_defaults)
def get(key):
return _current[key]
def set(key, value):
assert key in _defaults # only known settings
assert type(value) == type(_defaults[key]) # type check
_current[key] = value
Context manager override:
# Temporarily change a setting:
class override_setting:
def __init__(self, key, value):
self.key = key
self.value = value
def __enter__(self):
self.old_value = Settings.get(self.key)
Settings.set(self.key, self.value)
def __exit__(self, *args):
Settings.set(self.key, self.old_value)
# Usage:
# with override_setting("validate_distributions", False):
# fast_inference_loop() # no validation overhead
# # validation re-enabled here
Backend dispatch:
# Global backend registry:
BACKENDS = {
"pyro": PyroBackend,
"funsor": FunsorBackend,
}
active_backend = "pyro"
# Backend-dependent operation:
def sample(name, dist, obs=None):
backend = BACKENDS[active_backend]
return backend.sample(name, dist, obs)
# Switching backend changes the semantics of all sample calls
# e.g., Funsor backend enables exact enumeration of discrete variables
Utility function categories:
# Seed management:
def set_rng_seed(seed):
# Set seeds for: Python random, NumPy, PyTorch CPU, PyTorch CUDA
# Ensures reproducibility across all random sources
# Device management:
def get_default_device():
# Returns the device (cpu/cuda) for tensor allocation
# Numeric helpers:
def safe_log(x):
# log(x) with clamping to avoid -inf for x near 0
return log(clamp(x, min=epsilon))