[PyTorch] Optionally release columnwise copy of frozen FP8 block-scaled weights after dgrad - #3233
[PyTorch] Optionally release columnwise copy of frozen FP8 block-scaled weights after dgrad#32331tex wants to merge 2 commits into
Conversation
d48b05f to
16f4f73
Compare
…ed weights after dgrad Add an opt-in path for frozen 2D-block-scaled FP8 weights to release their columnwise representation after dgrad and rebuild it on demand. The behavior is disabled by default and covers Linear, GroupedLinear, LayerNormLinear, and LayerNormMLP. Preserve trainable-weight, CUDA graph, and FSDP2 behavior, and add unit and distributed coverage for rebuild numerics, workspace caching, activation recompute, CUDA graphs, FSDP2, and TP/SP. Signed-off-by: Tianyu Zhao <tyzhao10@gmail.com>
16f4f73 to
ce88e3c
Compare
Greptile SummaryAdds an opt-in mechanism to release and lazily rebuild columnwise copies of frozen 2D block-scaled FP8 weights.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Backward requires dgrad] --> B[Run dgrad GEMM]
B --> C{Weight gradient required?}
C -- Yes --> D[Keep columnwise representation]
C -- No --> E{Release option enabled?}
E -- No --> D
E -- Yes --> F{2D block-scaled weight with complete rowwise data?}
F -- No --> D
F -- Yes --> G{CUDA graph capture active?}
G -- Yes --> D
G -- No --> H[Release columnwise representation]
H --> I[Rebuild on demand through update_usage]
Reviews (2): Last reviewed commit: "[PyTorch] Add frozen FP8 weight release ..." | Re-trigger Greptile |
Signed-off-by: Tianyu Zhao <tyzhao10@gmail.com>
|
Hi @timmoon10 @yaox12, this is the frozen-weight case of #2168, implemented the way @yaox12 suggested there: release the columnwise copy right after the dgrad GEMM and let the existing update_usage rebuild it. I asked about this in #2168 on Jul 18 but that PR has been quiet since September. Would you rather have this folded into #2168, or keep it as the narrower frozen-only change it is now? Also, the Build/Lint/License/Documentation workflows here are still awaiting approval, so they have never run. Could someone approve them and start /te-ci pytorch L1? Both new test files are registered in the L0 and L1 QA scripts. |
Description
PEFT/LoRA-style fine-tuning keeps a large frozen base model in memory. With primary FP8
parameters (
quantized_model_init) and theFloat8BlockScalingrecipe, each weight holdstwo FP8 copies: rowwise (used by fprop) and columnwise (used only as the dgrad GEMM
operand). For frozen (
requires_grad=False) weights the columnwise copy is needed onlytransiently, yet it stays resident after the first backward pass — up to 1 byte per
locally resident frozen parameter. This is the compute-for-memory trade-off suggested by
@timmoon10 in #1880; #1847 addressed initialization, this PR addresses the steady state
during training.
This PR adds an opt-in environment variable
NVTE_RELEASE_FROZEN_WEIGHT_COLUMNWISE(default off). When enabled, the columnwise copy of frozen 2D-block-scaled weights is
released right after the dgrad GEMM and rebuilt on demand via the existing
update_usagepath — one quantization-aware transpose per frozen layer per step in exchange for the
resident memory.
Known limitation (documented in
envvars.rst): if the weight's quantizer requestscolumnwise usage (e.g. parameters initialized outside
torch.no_grad()), the copy isrebuilt in the next forward, so the option mainly reduces between-step residency; the
peak-memory benefit requires initializing frozen parameters without columnwise usage.
Type of change
Changes
Core library change is ~80 lines; the rest is tests and validation scripts.
release_frozen_weight_columnwisehelper inmodule/base.py(env-var gated; only2D-block-scaled
Float8BlockwiseQTensorStoragewith a full rowwise representation;no-op during CUDA graph capture), called after the dgrad GEMM in
Linear,GroupedLinear,LayerNormLinear, andLayerNormMLP(FC1/FC2), gated on the caller'swgrad-requirement flags.
docs/envvars.rst.non-2D layouts,
backward_override, workspace caching, activation recompute, CUDAgraphs) plus FSDP2/TP+SP multi-GPU validation scripts with a pytest driver.
Relationship with #2168
#2168 proposes a more general on-demand columnwise mechanism for blockwise FP8 weights.
This PR is intentionally narrower: it applies only to frozen weights, reuses the existing
update_usagepath, releases immediately after dgrad, and additionally coversLayerNormMLP.I asked about coordination in #2168 on Jul 18. This PR provides a concrete frozen-only
implementation based on current main; happy to fold this work into #2168 if preferred.
Validation
Everything coverable on H800 (8 GPUs) passes: the 23-test suite (on both the default and
the fused grouped-GEMM paths), the distributed driver
(FSDP2 with both
reshard_after_forwardmodes, TP+SP), and module regressions, all withzero failures. No Blackwell hardware was available locally; a spy-based test provides an
architecture-independent guarantee that non-blockwise layouts are never touched.
On a 16-layer frozen stack (features=4096, tokens=4096, 0.268B params), steady-state and
peak memory drop by 0.25 GiB — matching the theoretical columnwise size — at +3.9% step
time under
torch.no_grad()initialization; with grad-enabled initialization onlybetween-step residency drops (the documented limitation).
Checklist: