test_hc_fused.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. """GPU check for adapter/hc_fused.py: the one-walk hc mix stats must equal the stock split-K +
  2. reduce/sinkhorn bit for bit (torch.equal on pre, post and comb) at every row count, plus the
  3. drift guard and the dispatch. Needs the engine image and a GPU:
  4. docker run --rm --gpus all -v $PWD:/ds41 -w /ds41 -e PYTHONPATH=/ds41/adapter \
  5. --entrypoint python3 <image> tests/test_hc_fused.py
  6. """
  7. import os
  8. import types
  9. os.environ["DSV41_HC_FUSED"] = "1"
  10. import torch # noqa: E402
  11. import hc_fused # noqa: E402
  12. if torch.cuda.is_available():
  13. torch.cuda.set_per_process_memory_fraction(min(1.0, 2e9 / torch.cuda.get_device_properties(0).total_memory))
  14. K, MIX, HC, ITERS, RMS_EPS, HC_EPS = 20480, 24, 4, 20, 1e-20, 1e-6
  15. ROWS = list(range(1, 97)) + [127, 128, 255, 256, 511, 512, 513, 1000, 1024, 2047, 2048,
  16. 2049, 3000, 4095, 4096, 4097, 8192]
  17. def _mod():
  18. from sglang.kernels.ops.layernorm import mhc
  19. return mhc
  20. def _weights(seed):
  21. """Checkpoint-like: fn ~ N(0, 0.0225) fp32 (full mantissa), base ~ +-3, scale ~ 0.01-0.06."""
  22. g = torch.Generator(device="cuda").manual_seed(seed)
  23. fn = torch.randn(MIX, K, device="cuda", generator=g) * 0.0225
  24. base = torch.randn(MIX, device="cuda", generator=g) * 3
  25. scale = torch.rand(3, device="cuda", generator=g) * 0.05 + 0.01
  26. return fn, scale, base
  27. def _x(m, seed):
  28. g = torch.Generator(device="cuda").manual_seed(seed)
  29. x = torch.randn(m, K, device="cuda", generator=g) * (0.1 + 4 * (seed % 3))
  30. x[:, :64] *= 300 # a few large channels
  31. if m > 2:
  32. x[1] = 0 # an all-zero row
  33. x[2, ::7] = -0.0
  34. return x.to(torch.bfloat16)
  35. def test_drift_guard():
  36. mod = _mod()
  37. hc_fused.check_engine(mod)
  38. fake = types.SimpleNamespace(**{n: getattr(mod, n) for n in dir(mod) if not n.startswith("__")})
  39. def hc_mix_stats_sinkhorn(*a): # a different body under the same name
  40. return None
  41. fake.hc_mix_stats_sinkhorn = hc_mix_stats_sinkhorn
  42. try:
  43. hc_fused.check_engine(fake)
  44. except RuntimeError:
  45. return
  46. raise AssertionError("drifted engine accepted")
  47. def test_bit_exact_all_rows():
  48. mod = _mod()
  49. for i, m in enumerate(ROWS):
  50. fn, scale, base = _weights(i % 5)
  51. x = _x(m, i)
  52. args = (x, fn, scale, base, HC, ITERS, RMS_EPS, HC_EPS)
  53. assert hc_fused.eligible(x, fn, HC, min_rows=1)
  54. ref = mod.hc_mix_stats_sinkhorn(*args)
  55. got = hc_fused.fused_mix_stats_sinkhorn(mod, *args)
  56. for name, a, b in zip(("pre", "post", "comb"), ref, got):
  57. if not torch.equal(a, b):
  58. raise AssertionError(f"rows {m}: {name} differs, max abs {(a - b).abs().max().item():.3e}")
  59. # strided rows (a view of a wider buffer) and the real checkpoint when it is mounted
  60. wide = _x(600, 99)
  61. fn, scale, base = _weights(7)
  62. view = torch.empty(600, K + 128, dtype=torch.bfloat16, device="cuda")[:, :K]
  63. view.copy_(wide)
  64. args = (view, fn, scale, base, HC, ITERS, RMS_EPS, HC_EPS)
  65. assert all(torch.equal(a, b) for a, b in zip(mod.hc_mix_stats_sinkhorn(*args),
  66. hc_fused.fused_mix_stats_sinkhorn(mod, *args)))
  67. def test_real_checkpoint_weights():
  68. root = "/models/deepseek-ai/DeepSeek-V4.1-Flash"
  69. if not os.path.exists(root):
  70. return
  71. import json
  72. from safetensors import safe_open
  73. mod = _mod()
  74. idx = json.load(open(f"{root}/model.safetensors.index.json"))["weight_map"]
  75. names = sorted(k for k in idx if k.endswith("hc_attn_fn") or k.endswith("hc_ffn_fn"))[:4]
  76. for j, name in enumerate(names):
  77. p = name[:-2]
  78. with safe_open(f"{root}/{idx[name]}", "pt") as f:
  79. fn, scale, base = (f.get_tensor(p + s).float().cuda() for s in ("fn", "scale", "base"))
  80. for m in (6, 96, 4096):
  81. args = (_x(m, 50 + j), fn, scale, base, HC, ITERS, RMS_EPS, HC_EPS)
  82. ref = mod.hc_mix_stats_sinkhorn(*args)
  83. got = hc_fused.fused_mix_stats_sinkhorn(mod, *args)
  84. assert all(torch.equal(a, b) for a, b in zip(ref, got)), (name, m)
  85. def test_dispatch():
  86. calls = []
  87. mod = types.SimpleNamespace(**{n: getattr(_mod(), n) for n in dir(_mod()) if not n.startswith("__")})
  88. stock = mod.hc_mix_stats_sinkhorn
  89. def counting(*a):
  90. calls.append(a[0].shape[0])
  91. return stock(*a)
  92. mod.hc_mix_stats_sinkhorn = counting
  93. hc_fused._state.update(checked=False, disabled=False)
  94. guard = hc_fused.check_engine
  95. hc_fused.check_engine = lambda m: None # the counting stub is not the audited source
  96. try:
  97. hc_fused.install(mod)
  98. finally:
  99. hc_fused.check_engine = guard
  100. fn, scale, base = _weights(1)
  101. small = _x(96, 3)
  102. mod.hc_mix_stats_sinkhorn(small, fn, scale, base, HC, ITERS, RMS_EPS, HC_EPS)
  103. assert calls == [96] # below MIN_ROWS: stock
  104. big = _x(hc_fused.MIN_ROWS, 4)
  105. mod.hc_mix_stats_sinkhorn(big, fn, scale, base, HC, ITERS, RMS_EPS, HC_EPS)
  106. assert calls == [96, hc_fused.MIN_ROWS] and hc_fused._state["checked"] # first: self-check
  107. assert not hc_fused._state["disabled"]
  108. mod.hc_mix_stats_sinkhorn(big, fn, scale, base, HC, ITERS, RMS_EPS, HC_EPS)
  109. assert calls == [96, hc_fused.MIN_ROWS] # then fused only
  110. mod.hc_mix_stats_sinkhorn(big.float(), fn, scale, base, HC, ITERS, RMS_EPS, HC_EPS)
  111. assert calls[-1] == hc_fused.MIN_ROWS and len(calls) == 3 # fp32 activations: stock
  112. if __name__ == "__main__":
  113. test_drift_guard()
  114. test_bit_exact_all_rows()
  115. test_real_checkpoint_weights()
  116. test_dispatch()
  117. print(f"test_hc_fused: ok ({len(ROWS)} row counts bit-exact)")