Files
ktransformers/kt-kernel/test/per_commit/test_sft_activation_policy.py
yyj a5d7ad9047 feat(sft) Deepseek v4 flash LoRA (#2216)
* feat(sft): add native MXFP4 routed-expert LoRA kernels

* test(sft): validate DeepSeek V4 MXFP4 routed experts

* feat(sft): AVX2 tier for MXFP4 routed-expert LoRA SFT

MXFP4_SFT_MOE on non-AVX512 builds, same Python contract as the AMX /
AVX512-BF16 kernel from #2185 (KTMoEWrapper(method="MXFP4_SFT")), for
AVX2+FMA+F16C hosts (Zen 2/3 EPYC, older Xeons).

* operators/avx2/sft_mxfp4-moe.hpp: AVX2_SFT_MXFP4_MOE_TP part on top of
  AVX2_MXFP4_MOE_TP (frozen packed E2M1/UE8M0 base, LoRA gate/up/down,
  V4 swiglu clamp, transpose-free packed-weight dX, authoritative LoRA grads).
* operators/moe-sft-tp.hpp: AVX2 result merge; AVX-512 merge loops and the
  block-FP8 staging guarded so the wrapper builds without AVX-512.
* ext_bindings.cpp: bind MXFP4_SFT_MOE -> TP_MOE_SFT<AVX2_SFT_MXFP4_MOE_TP>
  when USE_AMX_AVX_KERNEL is off; MOESFTBindings no longer AMX-only.
* python/sft/backend.py: runtime reports cpu_variant=avx2, kernel avx2-mxfp4-g32.
* test_mxfp4_sft_numerical.py: inference regression uses AVX2MXFP4_MOE when
  AMXFP4_KGroup_MOE is absent.

Validated on 2x EPYC 7452 (AVX2, no AVX-512): test_mxfp4_sft_numerical.py
TP1/TP2 all stages rel-L2 <= 0.4% (limits 3-5%); validate_dsv4_mxfp4_sft_layer.py
on DeepSeek-V4-Flash-0731 layer 3, TP1 and TP2: passed, forward/grad_input/
LoRA grads rel-L2 0.10-0.29%, base weights unchanged.

Note: the build uses -ffast-math, so exp() past the float range is undefined;
the scalar sigmoid tails clamp the argument like the vector path.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011Mgsduzz2fx1gSvfHbR8RZ

* fix(sft): clamp MXFP4 scalar-tail sigmoid exponent

* feat(sft): integrate native V4 experts with LoRA training and export

Wrap only routed experts while preserving V4 routing and shared branches. Validate native checkpoint provenance and stream a BF16 non-expert cache without dequantizing routed experts.

Add audited static SGLang export and reproducible training, resume and generation acceptance helpers. CPU retain/GPU recompute GAS1/GAS4 smoke and 265 KT regression tests pass; long-run quality and resume acceptance remain in progress.

* fix(sft): retain async inference buffers until CUDA work completes

* test(sft): isolate V4 adapter effects with matched-kernel controls

Allow baseline and non-expert-only exports to retain a zero-B expert adapter so all ablations execute the same native forward kernel. Add paired held-out generation reporting with explicitly diagnostic lexical metrics.

* test(sft): compare PEFT targets semantically during V4 resume audits

* test(sft): cancel queued V4 inference checks after a failed request

* test(sft): preserve raw V4 responses before finite-output validation

* feat: prepare V4 cache atomically and package static adapter export

* build: preserve accepted CUDA carriers across Python ABIs

* test: retain FP8 loading contracts after V4 wrapper integration

* test: exclude historical concatenated-sample smoke from delivery

* test(sft): audit unpacked batches and single-GPU resume state

* docs(sft): align April V4 recipe with approved unpacked delivery

* test: keep frozen-parameter audit indices exact for large tensors

* test: record the loaded native backend in acceptance evidence

* test: timestamp training audit events for startup measurements

* docs: pin V4 serving dependencies and account for reserved token slots

* [refactor](sft): keep V4 follow-up focused on runtime integration

---------

Co-authored-by: 05yuki <ceu.azul.samu@gmail.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-30 21:29:43 +08:00

719 lines
23 KiB
Python

# SPDX-License-Identifier: Apache-2.0
import dataclasses
import importlib.util
import os
import sys
from pathlib import Path
from types import ModuleType, SimpleNamespace
from unittest.mock import patch
import pytest
import torch
from torch.utils.checkpoint import checkpoint
SFT_PATH = Path(__file__).resolve().parents[2] / "python" / "sft"
PACKAGE_NAME = "kt_sft_activation_under_test"
package = ModuleType(PACKAGE_NAME)
package.__path__ = [str(SFT_PATH)]
sys.modules[PACKAGE_NAME] = package
def _load_module(filename: str):
name = f"{PACKAGE_NAME}.{Path(filename).stem}"
spec = importlib.util.spec_from_file_location(name, SFT_PATH / filename)
assert spec is not None and spec.loader is not None
module = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = module
spec.loader.exec_module(module)
return module
config = _load_module("config.py")
dist_utils = _load_module("dist_utils.py")
def _make_config(policy=None):
clean_env = {
key: value
for key, value in os.environ.items()
if key
not in {
"ACCELERATE_KT_ACTIVATION_POLICY",
"KT_REUSE_CHECKPOINT_FORWARD",
}
}
kwargs = {} if policy is None else {"kt_activation_policy": policy}
with (
patch.dict(os.environ, clean_env, clear=True),
patch.object(config, "configure_omp_threads", return_value=1),
):
return config.KTConfig(**kwargs)
def _make_rawint4_config(**overrides):
values = {
"kt_backend": "RAWINT4",
"kt_expert_weight_format": "rawint4",
"kt_train_mode": "lora",
"kt_full_weight_grad": False,
"kt_lora_rank": 8,
"kt_lora_dropout": 0.0,
"kt_force_fused_expert_lora": True,
"kt_num_gpu_experts": 0,
"kt_use_lora_experts": False,
"kt_tp_enabled": False,
"kt_threadpool_count": 1,
"kt_activation_policy": {"cpu": "recompute", "gpu": "recompute"},
}
values.update(overrides)
with (
patch.dict(os.environ, {}, clear=True),
patch.object(config, "configure_omp_threads", return_value=1),
):
return config.KTConfig(**values)
def test_activation_policy_defaults_to_recompute_recompute():
policy = _make_config().kt_activation_policy
assert policy == config.KTActivationPolicy(cpu="recompute", gpu="recompute")
def _make_mxfp4_config(**overrides):
values = {
"kt_backend": "auto",
"kt_expert_weight_format": "mxfp4",
"kt_weight_path": "/native-v4",
"kt_non_expert_weight_path": "/validated-cache",
"kt_lora_rank": 8,
"kt_force_fused_expert_lora": True,
"kt_threadpool_count": 2,
"kt_tp_enabled": True,
}
values.update(overrides)
with patch.dict(os.environ, {}, clear=True), patch.object(config, "configure_omp_threads", return_value=1):
return config.KTConfig(**values)
def test_mxfp4_config_keeps_native_experts_and_cpu_activation_reuse():
cfg = _make_mxfp4_config(kt_activation_policy={"cpu": "retain", "gpu": "recompute"})
assert cfg.kt_backend == "MXFP4"
assert cfg.kt_skip_expert_loading
assert not cfg.kt_share_backward_bb
assert cfg.kt_activation_policy.cpu == "retain"
@pytest.mark.parametrize("invalid", [
{"kt_train_mode": "full"}, {"kt_lora_rank": 0}, {"kt_lora_dropout": 0.1},
{"kt_num_gpu_experts": 1}, {"kt_use_lora_experts": True}, {"kt_share_backward_bb": True},
{"kt_skip_expert_loading": False}, {"kt_threadpool_count": 4}, {"kt_weight_path": ""},
])
def test_mxfp4_config_rejects_unsupported_training_modes(invalid):
with pytest.raises(ValueError, match="MXFP4"):
_make_mxfp4_config(**invalid)
def test_config_from_hf_wrapper_preserves_outer_runtime_metadata():
public_config = {
"kt_backend": "AMXBF16",
"kt_num_threads": 7,
"kt_skip_expert_loading": False,
}
checkpoint_files = ["/models/qwen/model-00001-of-00002.safetensors"]
sharded_metadata = {"weight_map": {"expert.weight": checkpoint_files[0]}}
class HfTrainerKTConfig:
config = public_config
_runtime_metadata = {
"kt_checkpoint_files": checkpoint_files,
"kt_sharded_metadata": sharded_metadata,
"kt_skip_expert_loading": True,
}
def __getattr__(self, name):
if name in self._runtime_metadata:
return self._runtime_metadata[name]
try:
return self.config[name]
except KeyError as exc:
raise AttributeError(name) from exc
with (
patch.dict(os.environ, {}, clear=True),
patch.object(config, "configure_omp_threads", return_value=1),
):
cfg = config.KTConfig.from_object(HfTrainerKTConfig())
assert public_config == {
"kt_backend": "AMXBF16",
"kt_num_threads": 7,
"kt_skip_expert_loading": False,
}
assert cfg.kt_backend == "AMXBF16"
assert cfg.kt_num_threads == 7
assert cfg.kt_checkpoint_files is checkpoint_files
assert cfg.kt_sharded_metadata is sharded_metadata
assert cfg.kt_skip_expert_loading is True
@pytest.mark.parametrize("unknown", ["kt_backned", "totally_unknown"])
def test_config_from_hf_wrapper_rejects_unknown_public_fields(unknown):
class HfTrainerKTConfig:
config = {unknown: "FP8"}
kt_checkpoint_files = ["/models/qwen/model.safetensors"]
kt_skip_expert_loading = True
with (
patch.dict(os.environ, {}, clear=True),
patch.object(config, "configure_omp_threads", return_value=1),
pytest.raises(TypeError, match=unknown),
):
config.KTConfig.from_object(HfTrainerKTConfig())
def test_hf_public_mapping_cannot_impersonate_container_attributes():
class HfTrainerKTConfig:
config = {
"kt_config": {"kt_backend": "FP8"},
"kt_backned": "AMXBF16",
}
def __getattr__(self, name):
try:
return self.config[name]
except KeyError as exc:
raise AttributeError(name) from exc
with pytest.raises(TypeError, match="kt_backned"):
config.KTConfig.from_object(HfTrainerKTConfig())
@pytest.mark.parametrize("enabled", [True, False, None])
def test_config_mapping_accepts_framework_enabled_without_mutation(enabled):
payload = {"enabled": enabled, "kt_backend": "AMXBF16"}
with (
patch.dict(os.environ, {}, clear=True),
patch.object(config, "configure_omp_threads", return_value=1),
):
cfg = config.KTConfig.from_object(payload)
assert payload == {"enabled": enabled, "kt_backend": "AMXBF16"}
assert cfg.kt_backend == "AMXBF16"
def test_config_mapping_rejects_invalid_enabled_and_unknown_fields():
with pytest.raises(TypeError, match="enabled"):
config.KTConfig.from_object({"enabled": "yes"})
with pytest.raises(TypeError, match="kt_backned"):
config.KTConfig.from_object({"kt_backned": "FP8"})
with pytest.raises(TypeError, match="field names must be strings"):
config.KTConfig.from_object({1: "AMXBF16"})
def test_nested_typed_config_runtime_overlay_is_copy_only():
base = _make_config()
assert config.KTConfig.from_object(base) is base
assert config.KTConfig.from_object(SimpleNamespace(config=base)) is base
checkpoint_files = []
sharded_metadata = {}
outer = SimpleNamespace(
config=base,
kt_checkpoint_files=checkpoint_files,
kt_sharded_metadata=sharded_metadata,
kt_skip_expert_loading=False,
)
with patch.object(
config,
"configure_omp_threads",
side_effect=AssertionError("typed KTConfig must not be reinitialized"),
):
resolved = config.KTConfig.from_object(outer)
assert resolved is not base
assert base.kt_checkpoint_files is None
assert base.kt_sharded_metadata is None
assert base.kt_skip_expert_loading is None
assert resolved.kt_checkpoint_files is checkpoint_files
assert resolved.kt_sharded_metadata is sharded_metadata
assert resolved.kt_skip_expert_loading is False
def test_nested_config_prefers_kt_config_and_rejects_cycles():
outer = SimpleNamespace(
kt_config={"kt_num_threads": 3},
config={"kt_num_threads": 4},
)
with (
patch.dict(os.environ, {}, clear=True),
patch.object(config, "configure_omp_threads", return_value=1),
):
assert config.KTConfig.from_object(outer).kt_num_threads == 3
cyclic = SimpleNamespace()
cyclic.kt_config = cyclic
with pytest.raises(ValueError, match="Cyclic"):
config.KTConfig.from_object(cyclic)
empty_plugin = SimpleNamespace(enabled=True, kt_config=None)
with (
patch.dict(os.environ, {}, clear=True),
patch.object(config, "configure_omp_threads", return_value=1),
):
assert isinstance(config.KTConfig.from_object(empty_plugin), config.KTConfig)
@pytest.mark.parametrize(
"value",
[object(), SimpleNamespace(), SimpleNamespace(kt_backend="AMXBF16")],
)
def test_config_rejects_objects_without_an_explicit_public_container(value):
with pytest.raises(TypeError, match="public container"):
config.KTConfig.from_object(value)
def test_nested_mapping_only_accepts_outer_runtime_overrides():
checkpoint_files = []
outer = SimpleNamespace(
kt_config={
"kt_backend": "AMXBF16",
"kt_num_threads": 0,
"kt_skip_expert_loading": True,
},
kt_backend="FP8",
kt_num_threads=12,
kt_checkpoint_files=checkpoint_files,
kt_skip_expert_loading=False,
)
with (
patch.dict(os.environ, {}, clear=True),
patch.object(config, "configure_omp_threads", return_value=1),
):
resolved = config.KTConfig.from_object(outer)
assert resolved.kt_backend == "AMXBF16"
assert resolved.kt_num_threads == 0
assert resolved.kt_checkpoint_files is checkpoint_files
assert resolved.kt_skip_expert_loading is False
outer.kt_config = {"kt_backned": "FP8"}
with pytest.raises(TypeError, match="kt_backned"):
config.KTConfig.from_object(outer)
outer.kt_config = {"kt_backend": "AMXBF16"}
outer.kt_backned = "FP8"
with pytest.raises(TypeError, match="kt_backned"):
config.KTConfig.from_object(outer)
@pytest.mark.parametrize(
("cpu", "gpu"),
[
("retain", "retain"),
("retain", "recompute"),
("recompute", "recompute"),
],
)
def test_activation_policy_accepts_supported_combinations(cpu, gpu):
policy = _make_config({"cpu": cpu, "gpu": gpu}).kt_activation_policy
assert (policy.cpu, policy.gpu) == (cpu, gpu)
@pytest.mark.parametrize(
"policy",
[
{"cpu": "retain"},
{"gpu": "retain"},
{"cpu": "retain", "gpu": "retain", "extra": "recompute"},
{"cpu": "drop", "gpu": "recompute"},
{"cpu": "retain", "gpu": "drop"},
],
)
def test_activation_policy_rejects_invalid_shape_or_value(policy):
with pytest.raises((ValueError, TypeError)):
_make_config(policy)
def test_activation_policy_rejects_cpu_recompute_gpu_retain():
with pytest.raises(NotImplementedError, match="not implemented"):
_make_config({"cpu": "recompute", "gpu": "retain"})
def test_activation_policy_is_immutable():
policy = _make_config({"cpu": "retain", "gpu": "recompute"}).kt_activation_policy
with pytest.raises(dataclasses.FrozenInstanceError):
policy.cpu = "recompute"
def test_rawint4_accepts_canonical_and_legacy_backend_alias():
canonical = _make_rawint4_config()
assert canonical.kt_backend == "RAWINT4"
assert canonical.kt_expert_weight_format == "rawint4"
assert canonical.kt_share_backward_bb is False
with pytest.warns(FutureWarning, match="deprecated"):
legacy = _make_rawint4_config(kt_backend="AMXINT4_KGroup")
assert legacy.kt_backend == "RAWINT4"
def test_rawint4_legacy_backend_rejects_conflicting_weight_format():
with (
pytest.warns(FutureWarning, match="deprecated"),
pytest.raises(ValueError, match="conflicts"),
):
_make_rawint4_config(
kt_backend="AMXINT4_KGroup",
kt_expert_weight_format="bf16",
)
@pytest.mark.parametrize("threadpool_count", [1, 2])
def test_rawint4_accepts_tp1_tp2(threadpool_count):
cfg = _make_rawint4_config(
kt_tp_enabled=True,
kt_threadpool_count=threadpool_count,
)
assert cfg.kt_threadpool_count == threadpool_count
def test_rawint4_tp_disabled_has_effective_tp1():
cfg = _make_rawint4_config(
kt_tp_enabled=False,
kt_threadpool_count=8,
)
assert cfg.kt_tp_enabled is False
assert cfg.kt_threadpool_count == 8
@pytest.mark.parametrize(
("overrides", "message"),
[
({"kt_lora_rank": 16}, "rank=8"),
({"kt_lora_dropout": 0.1}, "dropout=0"),
({"kt_tp_enabled": True, "kt_threadpool_count": 4}, "TP1/TP2"),
({"kt_force_fused_expert_lora": False}, "force_fused"),
({"kt_use_lora_experts": True}, "GPU LoRA experts"),
({"kt_share_backward_bb": True}, "directly from packed weights"),
],
)
def test_rawint4_v1_capability_matrix_fails_closed(overrides, message):
with pytest.raises(ValueError, match=message):
_make_rawint4_config(**overrides)
def test_rawint4_allows_ordinary_retain_but_rejects_checkpoint_forward_reuse():
ordinary = _make_rawint4_config(
kt_activation_policy={"cpu": "retain", "gpu": "retain"}
)
assert ordinary.kt_activation_policy == config.KTActivationPolicy(
cpu="retain", gpu="retain"
)
with pytest.raises(ValueError, match="checkpoint-forward reuse"):
_make_rawint4_config(kt_activation_policy={"cpu": "retain", "gpu": "recompute"})
@pytest.mark.parametrize(
("legacy_value", "expected_cpu"),
[("1", "retain"), ("true", "retain"), ("0", "recompute"), ("false", "recompute")],
)
def test_legacy_reuse_env_maps_policy_only_when_policy_is_absent(
legacy_value,
expected_cpu,
):
with (
patch.dict(
os.environ,
{"KT_REUSE_CHECKPOINT_FORWARD": legacy_value},
clear=True,
),
patch.object(config, "configure_omp_threads", return_value=1),
pytest.warns(FutureWarning, match="deprecated"),
):
policy = config.KTConfig().kt_activation_policy
assert (policy.cpu, policy.gpu) == (expected_cpu, "recompute")
def test_explicit_policy_conflicts_with_legacy_reuse_env():
with (
patch.dict(
os.environ,
{"KT_REUSE_CHECKPOINT_FORWARD": "1"},
clear=True,
),
patch.object(config, "configure_omp_threads", return_value=1),
pytest.raises(ValueError, match="conflicts"),
):
config.KTConfig(
kt_activation_policy={"cpu": "retain", "gpu": "recompute"}
)
def test_forwarded_activation_policy_env_is_applied():
with (
patch.dict(
os.environ,
{
"ACCELERATE_KT_ACTIVATION_POLICY": (
'{"cpu":"retain","gpu":"recompute"}'
)
},
clear=True,
),
patch.object(config, "configure_omp_threads", return_value=1),
):
policy = config.KTConfig().kt_activation_policy
assert policy == config.KTActivationPolicy(cpu="retain", gpu="recompute")
def test_forwarded_activation_policy_env_rejects_invalid_json():
with (
patch.dict(
os.environ,
{"ACCELERATE_KT_ACTIVATION_POLICY": "retain/recompute"},
clear=True,
),
patch.object(config, "configure_omp_threads", return_value=1),
pytest.raises(ValueError, match="must be a JSON object"),
):
config.KTConfig()
def test_explicit_policy_conflicts_with_forwarded_policy_env():
with (
patch.dict(
os.environ,
{
"ACCELERATE_KT_ACTIVATION_POLICY": (
'{"cpu":"retain","gpu":"recompute"}'
)
},
clear=True,
),
patch.object(config, "configure_omp_threads", return_value=1),
pytest.raises(ValueError, match="conflicts"),
):
config.KTConfig(
kt_activation_policy={"cpu": "retain", "gpu": "recompute"}
)
def test_forwarded_policy_env_conflicts_with_legacy_reuse_env():
with (
patch.dict(
os.environ,
{
"ACCELERATE_KT_ACTIVATION_POLICY": (
'{"cpu":"retain","gpu":"recompute"}'
),
"KT_REUSE_CHECKPOINT_FORWARD": "1",
},
clear=True,
),
patch.object(config, "configure_omp_threads", return_value=1),
pytest.raises(ValueError, match="conflicts with legacy"),
):
config.KTConfig()
def _make_int8_config(**overrides):
kwargs = {
"kt_expert_weight_format": "int8",
"kt_weight_path": "/dev/shm/kt-int8-test-run",
"kt_train_mode": "lora",
"kt_lora_rank": 8,
"kt_num_gpu_experts": 0,
"kt_share_backward_bb": True,
}
kwargs.update(overrides)
with (
patch.dict(os.environ, {}, clear=True),
patch.object(config, "configure_omp_threads", return_value=1),
):
return config.KTConfig(**kwargs)
def test_int8_format_selects_backend_and_accepts_cpu_activation_retain():
cfg = _make_int8_config(
kt_activation_policy={"cpu": "retain", "gpu": "recompute"}
)
assert cfg.kt_backend == "INT8"
assert cfg.kt_expert_weight_format == "int8"
assert cfg.kt_weight_lifecycle == "persistent"
assert (cfg.kt_activation_policy.cpu, cfg.kt_activation_policy.gpu) == (
"retain",
"recompute",
)
@pytest.mark.parametrize(
("overrides", "message"),
[
({"kt_backend": "AMXBF16"}, "conflicts"),
({"kt_train_mode": "full"}, "frozen-base LoRA"),
({"kt_train_mode": "hybrid"}, "frozen-base LoRA"),
({"kt_num_gpu_experts": 1}, "kt_num_gpu_experts=0"),
({"kt_use_lora_experts": True}, "GPU LoRA experts"),
({"kt_share_backward_bb": False}, "kt_share_backward_bb=true"),
({"kt_expert_checkpoint_path": "/checkpoint"}, "pre-quantized"),
({"kt_weight_path": None}, "kt_weight_path"),
],
)
def test_int8_rejects_unsupported_training_or_weight_sources(overrides, message):
with pytest.raises(ValueError, match=message):
_make_int8_config(**overrides)
def test_legacy_int8_backend_env_infers_format_when_nonconflicting():
with pytest.warns(FutureWarning, match="deprecated"):
with (
patch.dict(
os.environ,
{
"ACCELERATE_KT_BACKEND": "AMXINT8",
"ACCELERATE_KT_WEIGHT_PATH": "/dev/shm/kt-int8-legacy-run",
},
clear=True,
),
patch.object(config, "configure_omp_threads", return_value=1),
):
cfg = config.KTConfig()
assert cfg.kt_expert_weight_format == "int8"
assert cfg.kt_backend == "INT8"
@pytest.mark.parametrize("backend", ["auto", "AUTO", "INT8", "int8"])
def test_int8_accepts_hardware_neutral_backend_names(backend):
cfg = _make_int8_config(kt_backend=backend)
assert cfg.kt_backend == "INT8"
def test_ephemeral_lifecycle_is_int8_only():
with (
patch.dict(os.environ, {}, clear=True),
patch.object(config, "configure_omp_threads", return_value=1),
pytest.raises(ValueError, match="supported only for INT8"),
):
config.KTConfig(
kt_expert_weight_format="bf16",
kt_weight_lifecycle="ephemeral",
)
def _make_fp8_config(**overrides):
kwargs = {
"kt_expert_weight_format": "fp8",
"kt_weight_path": "/models/native-fp8",
"kt_train_mode": "lora",
"kt_lora_rank": 8,
"kt_num_gpu_experts": 0,
"kt_share_backward_bb": True,
}
kwargs.update(overrides)
with (
patch.dict(os.environ, {}, clear=True),
patch.object(config, "configure_omp_threads", return_value=1),
):
return config.KTConfig(**kwargs)
def test_fp8_format_selects_backend_and_accepts_checkpoint_provenance():
cfg = _make_fp8_config(
kt_activation_policy={"cpu": "retain", "gpu": "recompute"}
)
assert cfg.kt_backend == "FP8"
assert cfg.kt_expert_weight_format == "fp8"
assert cfg.kt_weight_path == "/models/native-fp8"
assert cfg.kt_weight_lifecycle == "persistent"
@pytest.mark.parametrize(
("overrides", "message"),
[
({"kt_backend": "AMXBF16"}, "conflicts"),
({"kt_train_mode": "full"}, "frozen-base LoRA"),
({"kt_train_mode": "hybrid"}, "frozen-base LoRA"),
({"kt_lora_rank": 0}, "kt_lora_rank > 0"),
({"kt_num_gpu_experts": 1}, "kt_num_gpu_experts=0"),
({"kt_use_lora_experts": True}, "GPU LoRA experts"),
({"kt_share_backward_bb": False}, "kt_share_backward_bb=true"),
({"kt_weight_lifecycle": "ephemeral"}, "persistent"),
],
)
def test_fp8_rejects_unsupported_training_modes(overrides, message):
with pytest.raises(ValueError, match=message):
_make_fp8_config(**overrides)
def test_unknown_backend_fails_instead_of_falling_back_to_bf16():
with (
patch.dict(os.environ, {}, clear=True),
patch.object(config, "configure_omp_threads", return_value=1),
pytest.raises(ValueError, match="unknown kt_backend"),
):
config.KTConfig(kt_backend="AMXINT8_typo")
def test_explicit_checkpoint_context_takes_precedence_over_hook_probe():
context_fn = dist_utils.get_activation_checkpoint_context_fn()
first_forward, recompute = context_fn()
with patch.object(
dist_utils.torch._C._autograd,
"_top_saved_tensors_default_hooks",
side_effect=AssertionError("fallback must not be queried"),
):
with first_forward:
assert dist_utils._checkpoint_hook_mode() == "first_forward"
with recompute:
assert dist_utils._checkpoint_hook_mode() == "recompute"
def test_explicit_checkpoint_context_marks_real_non_reentrant_checkpoint_phases():
phases = []
def fn(value):
phases.append(dist_utils._checkpoint_hook_mode())
return value.sin()
value = torch.tensor([0.5], requires_grad=True)
output = checkpoint(
fn,
value,
use_reentrant=False,
context_fn=dist_utils.get_activation_checkpoint_context_fn(),
)
output.sum().backward()
assert phases == ["first_forward", "recompute"]
@pytest.mark.parametrize(
("phase", "action"),
[
("none", "normal"),
("first_forward", "cache_first_forward"),
("recompute", "reuse_recompute"),
],
)
def test_checkpoint_state_agreement_supports_single_rank(phase, action):
qlens = dist_utils._all_gather_checkpoint_state(
17,
layer_idx=3,
phase=phase,
action=action,
device=dist_utils.torch.device("cpu"),
world_size=1,
)
assert qlens == [17]
def test_checkpoint_state_agreement_rejects_invalid_action():
with pytest.raises(RuntimeError, match="action=invalid"):
dist_utils._all_gather_checkpoint_state(
17,
layer_idx=3,
phase="none",
action="skip_everything",
device=dist_utils.torch.device("cpu"),
world_size=1,
)