Repository navigation
Conversation
Signed-off-by: Evgeny <etsykunov@nvidia.com>
for more information, see https://pre-commit.ci
Signed-off-by: Evgeny <etsykunov@nvidia.com>
Signed-off-by: Evgeny <etsykunov@nvidia.com>
for more information, see https://pre-commit.ci
Signed-off-by: Evgeny <etsykunov@nvidia.com>
Signed-off-by: Evgeny <etsykunov@nvidia.com>
Signed-off-by: Evgeny <etsykunov@nvidia.com>
for more information, see https://pre-commit.ci
Signed-off-by: Evgeny <etsykunov@nvidia.com>
for more information, see https://pre-commit.ci
Signed-off-by: Evgeny <etsykunov@nvidia.com>
Signed-off-by: Evgeny <etsykunov@nvidia.com>
Signed-off-by: Evgeny <etsykunov@nvidia.com>
for more information, see https://pre-commit.ci
Signed-off-by: Evgeny <etsykunov@nvidia.com>
Signed-off-by: Evgeny <etsykunov@nvidia.com>
for more information, see https://pre-commit.ci
Signed-off-by: Evgeny <etsykunov@nvidia.com>
Signed-off-by: Evgeny <etsykunov@nvidia.com>
Signed-off-by: Evgeny <etsykunov@nvidia.com>
Signed-off-by: Evgeny <etsykunov@nvidia.com>
Signed-off-by: Evgeny <etsykunov@nvidia.com>
for more information, see https://pre-commit.ci
Signed-off-by: Evgeny <etsykunov@nvidia.com>
for more information, see https://pre-commit.ci
Signed-off-by: Evgeny <etsykunov@nvidia.com>
Signed-off-by: Evgeny <etsykunov@nvidia.com>
Signed-off-by: Evgeny <etsykunov@nvidia.com>
Signed-off-by: Evgeny <etsykunov@nvidia.com>
Signed-off-by: Evgeny <etsykunov@nvidia.com>
Signed-off-by: Evgeny <etsykunov@nvidia.com>
Signed-off-by: Evgeny <etsykunov@nvidia.com>
Signed-off-by: Evgeny <etsykunov@nvidia.com>
Signed-off-by: Evgeny <etsykunov@nvidia.com>
Signed-off-by: Evgeny <etsykunov@nvidia.com>
Signed-off-by: Evgeny <etsykunov@nvidia.com>
Signed-off-by: Evgeny <etsykunov@nvidia.com>
|
/te-ci pytorch L1 |
|
/te-ci pytorch L1 |
|
| if key is None: | ||
| qfactory = getattr(recipe, "qfactory", None) | ||
| name = getattr(qfactory, "__qualname__", None) or repr(qfactory) | ||
| raise ValueError( | ||
| f"CustomRecipe requires a semantic qfactory key for {name}. The key stands in for" | ||
| " the factory's behavior, because callable identity is not stable across processes," | ||
| " ranks or checkpoints. Attach one where the factory is defined:\n" | ||
| ' @quantizer_factory(key=("my_factory", 1))\n' | ||
| " def my_factory(role): ...\n" | ||
| "or pass it with the recipe: CustomRecipe(qfactory=my_factory," | ||
| ' qfactory_key=("my_factory", 1)).\n' | ||
| "Bump the revision whenever the factory's behavior changes, so quantizers built from" | ||
| " the previous behavior are rebuilt instead of silently reused." |
There was a problem hiding this comment.
Unkeyed factories no longer activate
Existing callers can construct CustomRecipe(qfactory=callable) without a semantic key, but the first enabled autocast, calibration, or model initialization now calls quantizer_config() and raises here before invoking the factory. This breaks the previously supported callable-factory contract and prevents existing unkeyed recipes from running unless callers add new metadata.
Knowledge Base Used: PyTorch FP8 and low-precision quantization
| else: | ||
| # Covers DelayedScaling, Float8CurrentScaling and CustomRecipe, whose | ||
| # quantizers are chosen by a factory this check cannot inspect. | ||
| recipe_supported, unsupported_reason = check_fp8_support() |
There was a problem hiding this comment.
If a CUDA environment can run Transformer Engine but fails the generic FP8 availability check, an identity-only CustomRecipe is rejected here before its factory is inspected. The documented high_precision_factory returns only IdentityQuantizers and performs no FP8 work, so this blanket gate prevents a supported high-precision policy from running even though it does not need FP8 kernels.
Knowledge Base Used: PyTorch FP8 and low-precision quantization
zhongbozhu
left a comment
There was a problem hiding this comment.
Why do we even need to dynamically change recipe during training?
| raise RuntimeError( | ||
| "Mid-training recipe updates are not supported for fusible operations. " | ||
| "Recreate the fusible operation or operation pipeline with the new recipe." | ||
| ) |
There was a problem hiding this comment.
Why doesn't this work? Can't we just let the fuser re-fuse the ops if the recipe changes?
| # cannot expose a requested recipe globally. | ||
| for module, update in plans: | ||
| module._apply_recipe_update(update) # pylint: disable=protected-access | ||
| FP8GlobalStateManager.quantization_state.fp8_recipe = recipe |
There was a problem hiding this comment.
This attr is set when entering te.autocast, so we don't expect this to be read if the function is called outside te.autocast. Consider replacing the default recipe instead, or keep the current API where the user has to pass the recipe into te.autocast.
| # owner implementing the pair can participate. | ||
| plans = [] | ||
| for fqn, module in model.named_modules(): | ||
| planner = getattr(module, "_plan_recipe_update", None) |
There was a problem hiding this comment.
I see we have this scheme so that we can process all the modules before actually applying the recipe change, which means we only apply the recipe change after all the modules have had some kind of validation. It adds a lot of complexity though, so skeptical if it is worth it.
| self._declared_output_quantizer_role = _declared_output_quantizer_role | ||
| self._declared_grad_input_quantizer_role = _declared_grad_input_quantizer_role |
There was a problem hiding this comment.
I think these are redundant with the existing logic for _output_quantizer_role and _grad_input_quantizer_role. If I understand, this is intended to allow MHA to change the output/grad input quantizer and detect recipe changes. However, I don't think there's value in having separate paths for users to set output quantizers and MHA to set output quantizers, they should use the same infrastructure.
| # Cached semantic configuration. Lazily populated by ``quantizer_config`` | ||
| # and invalidated together with the cached repr on recipe mutation. | ||
| _cached_quantizer_config: Any = None | ||
| _has_cached_quantizer_config: bool = False |
There was a problem hiding this comment.
The quantizer config infrastructure seems overengineered and redundant. #3717 uses the string representation to detect recipe changes in the op fuser.
Description
Enables recipe updates during training, either lazily through
te.autocast()or atomically across a model withte.apply_recipe().Diff:
TODO - callable compatibility:
Callable factories and algorithms now require explicit semantic metadata, supplied through a decorator or recipe key argument. Consider whether unkeyed callables should remain supported and, if so, what safe fallback identity should be used.
Type of change
Changes
Checklist: