pypi / ultralytics-thop
ultralytics-thop
What changed in ultralytics-thop 2, from its official release notes, upgrade guides and advisories. Sources checked 2026-10-19.
2 breaking1 deprecations3 new APIs and options4 performance7 behavior and defaults1 tooling33 fixes and other
See which of these apply to your code, ranked, in your agent:
npx @unstale/cli initultralytics-thop 251 changes
Breaking changes 2
Rejects modules that already use total_ops for parameters, child modules, or class-level properties, preventing profiling from silently corrupting module structure or reported totals.
The broken, unused fx_profile implementation was removed; code that depends on it must migrate to the standard profile API.
Deprecations 1
Embedding layers using max_norm emit a warning because their data-dependent renormalization is not counted.
New APIs and options 3
Adds the min_cells argument to start proxy measurements at a larger size, which can help when model costs change behavior below a certain input size.
Custom counting rules can be callable objects or functools.partial instances and receive arguments from keyword, positional, or mixed module calls.
Adds an optional stride argument for image models, enabling smaller stride-aligned inputs and more accurate estimates when fixed-cost layers are present.
Performance 4
Explicitly registered as a zero-MAC operation, reducing missing-rule warnings and profiling overhead.
Explicitly registered as a zero-MAC operation, reducing missing-rule warnings and profiling overhead.
Explicitly registered as a zero-MAC operation, reducing missing-rule warnings and profiling overhead.
Profiling overhead is reduced by up to 2.4× while preserving bit-exact results; get_flops is approximately 1.31× faster overall across the tested Ultralytics model configurations.
Behavior and default changes 7
THOP now counts two-operand einsum operations in FLOPs estimates; one-operand calls and calls with more than two operands remain uncounted by this rule.
On PyTorch 1.13 and later, profile() counts functional matrix products and scaled_dot_product_attention when available, without recounting products inside modules with their own counting rule.
For models that may have quadratic costs, profile() uses measurements at several smaller sizes, validates a quadratic estimate, and profiles at the target size if the measurements do not support it.
Adds support for ModuleList, ModuleDict, ParameterList, and ParameterDict containers during profiling.
Stride-based shortcut estimation is disabled for models containing attention; they use exact target-size profiling instead.
THOP counts projection layers, attention matrix operations, and softmax processing for batched and unbatched, cross-attention, and other supported calls.
Rules resolve through a module type’s inheritance hierarchy, allowing custom subclasses, parametrized layers, and many lazy modules to inherit the nearest supported rule.
Tooling 1
Publish runs are queued and failed PyPI uploads retried; workflows can recover partially completed releases, reuse existing tags, and replace incomplete SBOM files.
Fixes and other changes 33
Adaptive max pools and nn.Bilinear are treated as fixed-size operations during extrapolation, preventing FLOPs from being overcounted for affected models.
Custom operations that may have nonlinear computational costs use direct profiling instead of inaccurate linear extrapolation.
Embedding lookups are treated as data gathering rather than arithmetic computation.
Profiling accounts for projection work and reduced recurrent width in LSTM layers with proj_size.
Recognized as performing no arithmetic operations during profiling.
Packed RNN, GRU, and LSTM inputs are counted using their actual processed sequence steps instead of the larger padded shape.
Applies custom profiling rules to composite modules, matching the behavior of profile().
Attention profiling skips MAC counting when older PyTorch versions cannot expose hook keyword arguments, avoiding unsafe calls while preserving accurate counts on PyTorch 2.x.
THOP now counts operations for nn.Bilinear layers instead of treating them as free, improving FLOPs/MACs estimates.
Fixed and adaptive average-pooling counts account for window sizes, padding, boundary behavior, ceil_mode, and count_include_pad.
Now counted, including additional elementwise work and correct handling of empty normalization dimensions.
Now counted, including additional elementwise work and correct handling of empty normalization dimensions.
Now counted, including additional elementwise work and correct handling of empty normalization dimensions.
Explicitly registered as a zero-MAC operation, reducing missing-rule warnings and profiling overhead.
Both profiler entry points count the forward pass that actually executed, including when inference replaces or detaches submodules.
Existing total_ops attributes and buffers are preserved during profiling and restored afterward, preventing model state from being overwritten.
Convolution and RNN/GRU/LSTM profilers correctly interpret channel, batch, and sequence dimensions for batched and unbatched layouts.
Counts follow the integer pooling windows PyTorch uses, improving MAC estimates when output sizes do not evenly divide the input.
Exact powers of 1,000 and negative values receive the correct units.
These module families are handled through shared base classes.
LeakyReLU is explicitly treated as a zero-MAC operation.
Nearest and nearest-exact upsampling are counted as requiring zero arithmetic operations.
GroupNorm and RMSNorm use the existing normalization rule, and lazy normalization modules receive more reliable rule resolution.
Parameter totals come from the model’s parameter tree rather than profiling hooks, correctly handling shared weights, unused branches, unsupported module types, and parent-owned parameters.
ReLU is explicitly treated as a zero-MAC operation.
Model training modes are restored more reliably after profiling.
Profiling restores the model’s previous training or evaluation mode after profiling completes or fails.
Temporary hooks and operation-counting buffers are removed even when the model’s forward pass raises an error, preventing profiling state from remaining attached to the model.
The profiler avoids duplicate operation and parameter totals when the same module is reached through multiple paths.
Modules referenced by multiple parent layers are hooked only once, avoiding orphaned hook handles.
profile() removes temporary hooks and total_ops/total_params buffers from every module it touches, preventing profiling metadata from affecting state_dict() or shared modules while preserving results.
The package now declares Python 3.14 compatibility in its metadata, helping users and tools recognize support for that version.
Profiling now counts a module’s own parameters and avoids double-counting child parameters, improving totals for nested module structures.