Coverage for strongcoca / compute_config.py: 100%
29 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-07-25 16:26 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-07-25 16:26 +0000
1from dataclasses import dataclass
2from typing import Optional
4_VALID_BACKENDS = ('none', 'torch', 'cupy')
5_VALID_PRECISIONS = ('float32', 'float64')
8@dataclass(frozen=True)
9class ComputeConfig:
10 """Global runtime configuration for the O(N³) linear-algebra operations
11 in :class:`~strongcoca.calculators.PolarizabilityCalculator`.
13 Parameters
14 ----------
15 backend
16 ``'none'`` (CPU only), ``'torch'`` (PyTorch/CUDA), or ``'cupy'`` (CuPy/CUDA).
17 precision
18 Floating-point precision for GPU operations. ``'float32'`` casts to
19 complex64 before the GPU kernel and back to complex128 afterwards
20 (roughly 10x faster on consumer GPUs where FP64 throughput is
21 restricted); ``'float64'`` keeps complex128 throughout.
22 max_solve_mem
23 Memory budget in MiB for intermediate matrices in the CPU linear
24 solve step. The frequency axis is chunked so that the A matrix
25 stays below this limit.
26 gpu_batched_max
27 Maximum value of N3 = 3 x N_particles for which the cuBLAS batched
28 solver is used in GPU kernels. Above this threshold, the code loops
29 over the batch dimension to invoke the non-batched cuSOLVER path,
30 which is faster for large matrices on consumer GPUs. Increase this
31 value (e.g. to 1024 or higher) on A100/H100/H200 cards, where the
32 batched cuSOLVER path performs well at large N.
33 """
35 backend: str
36 precision: str
37 max_solve_mem: float
38 gpu_batched_max: int
41_config = ComputeConfig(backend='none', precision='float32',
42 max_solve_mem=80.0, gpu_batched_max=32)
45def set_compute_config(backend: Optional[str] = None,
46 precision: Optional[str] = None,
47 max_solve_mem: Optional[float] = None,
48 gpu_batched_max: Optional[int] = None) -> None:
49 """Update one or more fields of the global compute configuration.
51 Any argument left as ``None`` keeps its current value.
52 All arguments are validated before anything is written, so an invalid
53 call leaves the configuration completely unchanged.
55 Parameters
56 ----------
57 backend
58 See :class:`ComputeConfig`.
59 precision
60 See :class:`ComputeConfig`.
61 max_solve_mem
62 See :class:`ComputeConfig`.
63 gpu_batched_max
64 See :class:`ComputeConfig`.
66 Examples
67 --------
68 >>> from strongcoca import set_compute_config, get_compute_config
69 >>> set_compute_config(max_solve_mem=200)
70 >>> get_compute_config().max_solve_mem
71 200.0
72 >>> set_compute_config(max_solve_mem=80) # reset to the default
73 """
74 global _config
76 new_backend = _config.backend if backend is None else backend
77 new_precision = _config.precision if precision is None else precision
78 new_max_solve_mem = _config.max_solve_mem if max_solve_mem is None else float(max_solve_mem)
79 new_gpu_batched_max = _config.gpu_batched_max
80 if gpu_batched_max is not None:
81 new_gpu_batched_max = int(gpu_batched_max)
83 if new_backend not in _VALID_BACKENDS:
84 raise ValueError(f'backend must be one of {_VALID_BACKENDS}, got {new_backend!r}')
85 if new_precision not in _VALID_PRECISIONS:
86 raise ValueError(f'precision must be one of {_VALID_PRECISIONS}, got {new_precision!r}')
87 if new_max_solve_mem <= 0:
88 raise ValueError(f'max_solve_mem must be positive, got {new_max_solve_mem}')
89 if new_gpu_batched_max <= 0:
90 raise ValueError(f'gpu_batched_max must be positive, got {new_gpu_batched_max}')
92 _config = ComputeConfig(backend=new_backend,
93 precision=new_precision,
94 max_solve_mem=new_max_solve_mem,
95 gpu_batched_max=new_gpu_batched_max)
98def get_compute_config() -> ComputeConfig:
99 """Return the current global compute configuration."""
100 return _config