Cache NaFlex patch interpolation and expose variable-patch capabilities#2721
Open
chenghuichen wants to merge 1 commit into
Open
Cache NaFlex patch interpolation and expose variable-patch capabilities#2721chenghuichen wants to merge 1 commit into
chenghuichen wants to merge 1 commit into
Conversation
|
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
While fixing variable patch-size integration in mlfoundations/open_clip#1195, I noticed a few generic improvements that belong in timm. In particular, every non-base patch-size forward rebuilt the resize basis and ran
torch.linalg.pinv, even though training usually cycles through a small fixed set of patch sizes.The existing
PatchEmbedResamplerFixedOrigSizealready had most of the required caching logic, butPatchEmbedInterpolatordid not use it and the cached matrices were persistent buffers. Downstream integrations also had no reliable way to discover whether a NaFlex model supports variable patches, while eval transforms always flattened patches before the model could infer their spatial size.Changes
Cached interpolation and prewarming
PatchEmbedInterpolatornow shares aPatchEmbedResamplerFixedOrigSizebetween linear and convolutional weight resampling. Each matrix is computed once per target patch size and device, then kept in a runtime-only cache. Cache misses produce regular float32 tensors even under inference mode or autocast; device or dtype conversion clears stale entries. The cache adds no parameters or persistent buffers, so checkpoint keys remain unchanged; the standaloneresample_patch_embedfunction and both linear patch layouts continue to behave as before.The cache can be populated before
torch.compileor another captured execution path:Prewarming should happen after moving the model to its execution device. The base patch size is a no-op. Each unique non-base patch size retains one float32 resampling matrix; there is intentionally no eviction policy because NaFlex training normally uses a small configured set of patch sizes.
Capability discovery and evaluation layout
NaFlexVit.supports_patch_interpolationreports the resolved capability: a linear projection with an enabled interpolator and no incompatible input normalization.create_transformandtransforms_imagenet_evalnow acceptpatchify_flatten=False, returning spatial patches such as[N, Ph, Pw, C]. The default remainsTrue, so existing transform calls retain their flattened output.Benchmark
Both benchmarks ran on an NVIDIA A10 with PyTorch 2.11.0+cu128.
Patch-resampling cache
benchmark_patch_interpolator_cache.py compares a float32 channels-last projection (
embed_dim=768,in_chans=3, base patch 16x16). Values are median latency per call.Cache misses match the previous path, while repeated sizes avoid resize-matrix construction and
torch.linalg.pinv.Synthetic OpenCLIP training step
benchmark_open_clip_patch_interpolation_e2e.py compares forced misses and cache hits over a full single-GPU OpenCLIP training step. The run used
naflex_ViT-B-16, BF16 autocast, batch size 32, sequence length 196, and 32x32 patches; ten pairs were measured after warmup.This synthetic workload shows a 7.25% latency reduction and 7.82% throughput increase with a 1 MiB cache. End-to-end gains will vary with workload and patch-size distribution.
Tests
46 targeted tests passed, covering cache reuse and dtype, gradients and checkpoint state, prewarming with
torch.compile, capability reporting, non-base patch forwards, and spatial eval patchification.