Memory#
pytme computes memory requirements for template matching operations ahead of time, enabling automatic workload splitting across available hardware resources.
Scheduling occurs in three phases:
Predict peak memory consumption for the operation
Determine optimal box decomposition within hardware constraints
Process independent boxes sequentially or in parallel
Core Functions#
|
Plan a parallelization schedule that fits |
|
Estimate the memory usage of a given template matching run. |
compute_schedule() determines the box decomposition based on available memory and operation requirements. estimate_memory_usage() predicts peak memory consumption for a given configuration.
Decomposition Strategies#
The scheduler decomposes the search space into boxes that cover the target volume while minimizing computational overhead. Two modes are available:
Uniform: Regular grid decomposition across the entire volume
Masked: Uses binary segmentation to place boxes only where needed, minimizing the number of computations
(Source code, png, hires.png, pdf)
Defining Memory Requirements#
Custom operations register their memory footprint by subclassing MatchingMemoryUsage and implementing the required methods.
|
Strategy class for estimating memory requirements. |
A concrete implementation for methods with uniform array requirements is MemoryProfile.
|
Memory estimator for methods with uniform array requirements. |
Built-in Memory Profiles#
Memory profiles are registered for scoring methods, analyzers, and backends. Some profiles serve multiple method identifiers (e.g., CORRMemoryUsage handles CORR, NCC, CAM, and related variants).
Scoring Methods#
|
|
|
|
|
|
|
|
Analyzers#
|
|
|
|
|
Backends#
|
|
|
|
Registering Custom Profiles#
Use the register_memory() decorator to associate memory profiles with custom methods.
|
Register a |
The decorator accepts multiple method identifiers, allowing a single profile to serve multiple operations:
from tme.memory import MemoryProfile, register_memory
@register_memory("CustomMethod", "CustomMethodVariant")
class CustomMethodMemoryUsage(MemoryProfile):
"""Custom memory estimator."""
#: Number of shared real arrays
base_float = 2
#: Number of shared complex arrays
base_complex = 1
#: Number of real arrays per fork
fork_float = 1
#: Number of complex arrays per fork
fork_complex = 1
The MemoryProfile class simplifies registration for methods with uniform array requirements. For more complex memory patterns, subclass MatchingMemoryUsage directly:
from tme.memory import MatchingMemoryUsage, register_memory
@register_memory("ComplexMethod")
class ComplexMethodMemoryUsage(MatchingMemoryUsage):
"""Memory estimator for methods with non-uniform requirements."""
def base_usage(self):
# Custom implementation for base usage
def per_fork(self):
# Custom implementation per fork
Once registered, the memory profile is automatically used by estimate_memory_usage() and compute_schedule() for the specified method identifiers.