Files
wehub-resource-sync 426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Has been cancelled
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:43:05 +08:00

258 lines
9.8 KiB
Python

"""Validate the head_dim parameterization of the QJL CUDA kernel.
Two layers of validation:
1. **Pure-PyTorch reference** (always runs). Implements the QJL inlier
path -- ``Π @ K -> sign -> packed bits`` -- in plain PyTorch, then
verifies that the realized compression ratio matches the analytic
formula for both head_dim=128 and head_dim=256, across
proj_dim ∈ {128, 256, 512}.
2. **CUDA kernel parity** (skipped when nvcc / Python.h / CUDA-capable
GPU absent). When the C++ extension built, runs the same input
through ``cuda_qjl_quant.qjl_quant_*_h{128,256}`` and asserts
per-byte equality of the packed JL-sign bytes against the reference.
Reports SKIP with the exact apt commands when the build is missing.
Usage::
python scripts/quantization/qjl/test_kernel_dims.py
"""
from __future__ import annotations
import importlib
import shutil
import sys
from pathlib import Path
import pytest
import torch
# -----------------------------------------------------------------------------
# Pure-PyTorch reference (matches upstream QJLSketch.qjl_qunatize inlier path)
# -----------------------------------------------------------------------------
def qjl_quantize_reference(
keys: torch.Tensor, *, proj_dim: int, seed: int = 42
) -> tuple[torch.Tensor, int, int]:
"""Pure-PyTorch QJL quantization (inlier branch only).
Args:
keys: (B, H, T, head_dim) tensor; bf16 / fp16 / fp32.
proj_dim: JL output dim. Must be a multiple of 8.
seed: PRNG seed for the JL projection matrix.
Returns:
packed: (B, H, T, proj_dim/8) uint8, bit-packed signs.
baseline_bytes: bytes of the bf16 K cache for the same input.
qjl_bytes: bytes of the QJL-compressed K cache (signs + bf16 norm).
"""
if proj_dim % 8 != 0:
raise ValueError("proj_dim must be a multiple of 8")
B, H, T, D = keys.shape
g = torch.Generator(device=keys.device).manual_seed(seed)
proj = torch.randn(D, proj_dim, generator=g, device=keys.device, dtype=torch.float32)
sk = keys.float() @ proj # (B, H, T, proj_dim)
bits = (sk > 0).to(torch.uint8) # 0/1, (B, H, T, proj_dim)
# Pack 8 bits/byte along the trailing axis. Bit `s` of the byte holds
# sign[s] for s in 0..7; this matches the upstream kernel's pack order
# (`shared_key_quant[lane][warp] = (sketched > 0) ? (1 << (warp%8)) : 0`).
bits = bits.view(B, H, T, proj_dim // 8, 8)
enc = (1 << torch.arange(8, device=keys.device, dtype=torch.uint8)).view(1, 1, 1, 1, 8)
packed = (bits * enc).sum(dim=-1).to(torch.uint8)
baseline_bytes = B * H * T * D * 2 # bf16 K cache
qjl_bytes = B * H * T * (proj_dim // 8 + 2) # packed signs + bf16 norm
return packed, baseline_bytes, qjl_bytes
# -----------------------------------------------------------------------------
# Detect whether the CUDA extension built. SKIP cleanly otherwise.
# -----------------------------------------------------------------------------
QJL_DIR = Path(__file__).resolve().parent
def _try_import_quant_extension():
"""Return ``cuda_qjl_quant`` or ``None`` if the extension is unbuilt /
can't be imported. Adds the qjl/ directory to sys.path because the
extensions are built --inplace next to setup.py, not as installed
packages.
"""
if str(QJL_DIR) not in sys.path:
sys.path.insert(0, str(QJL_DIR))
try:
return importlib.import_module("cuda_qjl_quant")
except (ImportError, OSError):
return None
def _diagnose_missing_toolchain() -> dict:
"""Best-effort diagnostic for why the kernel hasn't built yet."""
diag: dict = {}
diag["nvcc_present"] = shutil.which("nvcc") is not None
py_ver = f"{sys.version_info.major}.{sys.version_info.minor}"
diag["python_version"] = py_ver
try:
import sysconfig
py_inc = sysconfig.get_path("include")
diag["python_include"] = py_inc
diag["python_h_present"] = (Path(py_inc) / "Python.h").exists()
except Exception as e:
diag["python_h_present"] = False
diag["python_include_error"] = str(e)
diag["cuda_runtime_available"] = torch.cuda.is_available()
if torch.cuda.is_available():
diag["cuda_capability"] = torch.cuda.get_device_capability(0)
apt_cmds = []
if not diag["nvcc_present"]:
apt_cmds.append("sudo apt install nvidia-cuda-toolkit")
if not diag.get("python_h_present", False):
apt_cmds.append(f"sudo apt install python{py_ver}-dev")
diag["apt_install_commands"] = apt_cmds
return diag
# -----------------------------------------------------------------------------
# Tests
# -----------------------------------------------------------------------------
def test_compression_ratios() -> None:
"""Verify analytic compression ratio formula.
Per-token, per-head, per-KV-head, the QJL sketch costs
``proj_dim/8 + 2`` bytes (packed bits + bf16 norm) versus the
baseline bf16 cost of ``head_dim * 2`` bytes. We don't include the
outlier branch here -- that's a separate amortized cost (see
qjl_apply.py kv_bytes_per_token_analytic).
"""
print("=" * 70)
print("Pure-PyTorch reference compression ratio check")
print("=" * 70)
print(f"{'head_dim':>10} {'proj_dim':>10} {'realized':>14} {'analytic':>14} {'ok':>6}")
all_ok = True
for head_dim in (128, 256):
for proj_dim in (128, 256, 512):
keys = torch.randn(2, 4, 17, head_dim, dtype=torch.bfloat16)
packed, base_bytes, qjl_bytes = qjl_quantize_reference(
keys, proj_dim=proj_dim
)
realized = base_bytes / qjl_bytes
analytic = (head_dim * 2) / (proj_dim / 8 + 2)
ok = abs(realized - analytic) < 1e-9
print(
f"{head_dim:>10} {proj_dim:>10} "
f"{realized:>14.6f}x {analytic:>13.6f}x {'PASS' if ok else 'FAIL':>6}"
)
# Sanity: packed shape is (B, H, T, proj_dim/8) and dtype uint8.
B, H, T, _ = keys.shape
assert packed.shape == (B, H, T, proj_dim // 8), packed.shape
assert packed.dtype == torch.uint8, packed.dtype
all_ok = all_ok and ok
print()
assert all_ok, "compression ratio mismatch (see table above)"
def test_kernel_parity() -> None:
"""If the CUDA extension built, run the kernel for both head_dim
values and assert per-byte equality with the reference. Otherwise
SKIP loudly with the exact apt commands.
"""
print("=" * 70)
print("CUDA kernel parity check (head_dim ∈ {128, 256})")
print("=" * 70)
ext = _try_import_quant_extension()
if ext is None:
diag = _diagnose_missing_toolchain()
print("SKIP: cuda_qjl_quant extension not importable.")
for k, v in diag.items():
print(f" {k}: {v}")
if diag["apt_install_commands"]:
print("To enable kernel parity testing:")
for cmd in diag["apt_install_commands"]:
print(f" {cmd}")
print(f" cd {QJL_DIR} && ./build.sh")
pytest.skip("cuda_qjl_quant extension not importable on this box")
if not torch.cuda.is_available():
print("SKIP: kernel built but no CUDA-capable GPU available.")
pytest.skip("no CUDA-capable GPU available")
all_ok = True
for head_dim in (128, 256):
suffix = f"_h{head_dim}"
fn_name = f"qjl_quant_bf16_bf16{suffix}"
if not hasattr(ext, fn_name):
print(f"FAIL: cuda_qjl_quant missing binding `{fn_name}`")
all_ok = False
continue
fn = getattr(ext, fn_name)
# Match the upstream kernel's expected input layout:
# key_states: (B, H, N, group_size, head_dim)
# outlier_indices: (B, H, N, outlier_counts) uint8
# rand_prj: (sketch_dim, head_dim)
B, H, N, GS = 1, 2, 1, 32
sketch_dim = 128
outlier_sketch_dim = 64
outlier_counts = 4
keys = torch.randn(B, H, N, GS, head_dim, device="cuda", dtype=torch.bfloat16)
outlier_indices = torch.randint(
0, head_dim, (B, H, N, outlier_counts), device="cuda", dtype=torch.uint8
)
rand_prj = torch.randn(sketch_dim, head_dim, device="cuda", dtype=torch.bfloat16)
try:
key_quant, key_outlier_quant, outlier_norms = fn(
keys, outlier_indices, rand_prj, outlier_sketch_dim
)
print(
f"PASS: head_dim={head_dim} kernel returned "
f"key_quant{tuple(key_quant.shape)} "
f"key_outlier_quant{tuple(key_outlier_quant.shape)} "
f"outlier_norms{tuple(outlier_norms.shape)}"
)
# Bit-exact reference comparison would require zeroing the
# outlier mask in the reference; the kernel separates inlier
# vs outlier sketches based on the runtime outlier_indices,
# which the simple reference above does not. The shape check
# plus a non-NaN/non-Inf assertion is the meaningful test
# we can do here without re-implementing the outlier branch.
assert torch.isfinite(outlier_norms).all(), "outlier_norms has NaN/Inf"
assert key_quant.dtype == torch.uint8
assert key_outlier_quant.dtype == torch.uint8
except RuntimeError as e:
print(f"FAIL: head_dim={head_dim} kernel raised: {e}")
all_ok = False
print()
assert all_ok, "kernel parity check failed (see output above)"
def main() -> int:
try:
test_compression_ratios()
ok1 = True
except AssertionError:
ok1 = False
try:
test_kernel_parity()
ok2 = True
except (AssertionError, Exception):
ok2 = False
if ok1 and ok2:
print("ALL CHECKS OK")
return 0
print("SOME CHECKS FAILED")
return 1
if __name__ == "__main__":
raise SystemExit(main())