Module neuralops.evaluation.eval_all_models_datasets

Functions

def apply_module_to_model(model: nn.Module,
module_name: str,
module_type: str = 'auto',
rank: int = 16,
device: torch.device = device(type='cpu'),
calibration_data: Any | None = None,
calibration_loader: Any | None = None,
tokenizer: Any | None = None) ‑> tuple[torch.nn.modules.module.Module, float]
Expand source code
def apply_module_to_model(
    model: nn.Module,
    module_name: str,
    module_type: str = "auto",
    rank: int = 16,
    device: torch.device = torch.device("cpu"),
    calibration_data: Any | None = None,
    calibration_loader: Any | None = None,
    tokenizer: Any | None = None,
) -> tuple[nn.Module, float]:
    """
    Inject or compress the model.

    FIX-1: forwards calibration_loader + tokenizer to compressors.
    FIX-2: removed unreachable candidate=None.
    FIX-11: no random fake calibration.
    """
    orig_params = sum(p.numel() for p in model.parameters())

    if not module_name or module_name.lower() in ("none", "baseline", "dense", "full"):
        return model, 1.0

    # Aliases
    if module_name == "hla_inject":
        module_name = "hla_attention"

    # Deprecation guard
    if module_name in DEPRECATED_MODULES:
        logger.warning("Module %s is DEPRECATED; skipping.", module_name)
        return model, 1.0

    # Determine category
    if module_name in ATTENTION_REGISTRY:
        module_type = "attention"
    elif module_name in COMPRESSOR_REGISTRY:
        module_type = "compressor"
    else:
        import importlib.util

        if importlib.util.find_spec(f"neuralops.compression_engine.{module_name}"):
            module_type = "compressor"
        elif importlib.util.find_spec(f"neuralops.attentions.{module_name}"):
            module_type = "attention"

    # ========================================================================
    # ATTENTION PATH
    # ========================================================================
    if module_type == "attention":
        if module_name not in ATTENTION_REGISTRY:
            try:
                import importlib

                importlib.import_module(f"neuralops.attentions.{module_name}")
            except ImportError as e:
                logger.warning("Could not import attention '%s': %s", module_name, e)

        resolved_mod = ATTENTION_REGISTRY.get(module_name)
        custom_injector = None
        if (
            resolved_mod is not None
            and callable(resolved_mod)
            and not isinstance(resolved_mod, type)
        ):
            custom_injector = resolved_mod
        if custom_injector is None:
            custom_injector = (
                ATTENTION_REGISTRY.get(f"inject_{module_name}")
                or ATTENTION_REGISTRY.get(f"{module_name}_inject")
                or ATTENTION_REGISTRY.get(f"inject_{module_name}_attention")
            )

        injected = False
        if custom_injector is not None and callable(custom_injector):
            try:
                res = custom_injector(model=model, rank=rank, copy_weights=True)
                from neuralops.core.base import BaseAttention

                is_single_layer = isinstance(res, (BaseAttention, nn.Linear)) or (
                    "Attention" in type(res).__name__
                    and not any(
                        hasattr(res, a)
                        for a in (
                            "encoder",
                            "transformer",
                            "bert",
                            "roberta",
                            "distilbert",
                            "gpt2",
                            "qwen2",
                        )
                    )
                )
                is_whole_model = (
                    res is not None
                    and isinstance(res, nn.Module)
                    and sum(p.numel() for p in res.parameters()) > 1000
                )
                if is_whole_model:
                    model = res
                    if device is not None:
                        model = model.to(device)
                    new_params = sum(p.numel() for p in model.parameters())
                    return model, orig_params / max(1, new_params)
                elif is_single_layer:
                    logger.debug(
                        "Injector %s returned a single layer; using inject_attention.",
                        custom_injector,
                    )
            except Exception as e:
                logger.debug("Injector %s failed: %s", custom_injector, e)

        if not injected:
            if module_name in ATTENTION_REGISTRY:
                inject_attention(model, module_name, rank=rank, copy_weights=True)
            else:
                import importlib

                mod = importlib.import_module(f"neuralops.attentions.{module_name}")
                target_cls = None
                for attr in dir(mod):
                    obj = getattr(mod, attr)
                    if (
                        isinstance(obj, type)
                        and issubclass(obj, nn.Module)
                        and ("Attention" in attr or "Block" in attr)
                        and attr != "BaseAttention"
                    ):
                        target_cls = obj
                        break
                if target_cls is None:
                    raise ValueError(f"No valid attention class in '{module_name}'")
                cfg = getattr(model, "config", None)
                for name, sub in list(model.named_modules()):
                    if "attention" in name.lower() and hasattr(sub, "self"):
                        new_inner = target_cls(cfg)
                        wrapped = UniversalAttentionWrapper(new_inner)
                        sub.self = wrapped

    # ========================================================================
    # COMPRESSOR PATH
    # ========================================================================
    elif module_type == "compressor":
        if module_name not in COMPRESSOR_REGISTRY:
            try:
                import importlib

                importlib.import_module(f"neuralops.compression_engine.{module_name}")
            except ImportError as e:
                logger.warning("Could not import compressor '%s': %s", module_name, e)

        comp_cls = COMPRESSOR_REGISTRY.get(module_name)
        if comp_cls is None:
            raise RuntimeError(f"Compressor '{module_name}' not in COMPRESSOR_REGISTRY")

        # Build kwargs
        tok = (
            tokenizer
            or getattr(model, "tokenizer", None)
            or getattr(getattr(model, "config", None), "tokenizer", None)
        )
        cfg = getattr(model, "config", None)

        c_kwargs: dict[str, Any] = {}
        if cfg is not None:
            for k in (
                "rank_ratio",
                "max_error",
                "lora_rank",
                "target_attention_only",
                "use_jg_svd",
                "use_cholesky_jg",
                "energy_threshold",
                "group_size",
                "strict_rank",
                "n_calib",
                "calib_samples",
                "keep_ratio",
                "bits",
            ):
                if hasattr(cfg, k):
                    c_kwargs[k] = getattr(cfg, k)

        # FIX-1 + FIX-11: real calibration, no random fallback
        if calibration_loader is not None:
            c_kwargs["calibration_loader"] = calibration_loader
            c_kwargs["calib_loader"] = calibration_loader
        if calibration_data is not None:
            c_kwargs["calibration_data"] = calibration_data

        def _invoke(instance: Any) -> nn.Module | None:
            for method_name in ("compress", "apply", "prune"):
                if not hasattr(instance, method_name):
                    continue
                m = getattr(instance, method_name)
                if not callable(m):
                    continue

                attempts = [lambda: m()]
                if calibration_loader is not None:
                    attempts.append(lambda: m(calibration_loader=calibration_loader))
                if calibration_data is not None:
                    attempts.append(lambda: m(calibration_data=calibration_data))
                attempts.append(lambda: m(model))
                if calibration_loader is not None:
                    attempts.append(lambda: m(model, calibration_loader=calibration_loader))
                if calibration_data is not None:
                    attempts.append(lambda: m(model, calibration_data=calibration_data))

                for fn in attempts:
                    try:
                        res = fn()
                        if isinstance(res, tuple) and res and isinstance(res[0], nn.Module):
                            if len(res) > 1 and isinstance(res[1], dict):
                                try:
                                    res[0].compression_stats = res[1]
                                except Exception:
                                    pass
                            return res[0]
                        if isinstance(res, nn.Module):
                            return res
                    except (TypeError, ValueError, RuntimeError):
                        continue

            m = getattr(instance, "model", None)
            if m is not None and hasattr(instance, "get_compression_stats"):
                try:
                    m.compression_stats = instance.get_compression_stats()
                except Exception:
                    pass
            return m

        # Strategy 1
        candidate = None
        for init_fn in [
            lambda: comp_cls(model, rank=rank, tokenizer=tok, **c_kwargs),
            lambda: comp_cls(model, rank=rank, tokenizer=tok),
            lambda: comp_cls(model, rank=rank, **c_kwargs),
            lambda: comp_cls(model, rank=rank),
            lambda: comp_cls(model),
        ]:
            try:
                candidate = init_fn()
                if candidate is not None:
                    break
            except (TypeError, ValueError):
                continue

        if candidate is not None:
            if isinstance(candidate, tuple) and candidate and isinstance(candidate[0], nn.Module):
                model = candidate[0]
                if len(candidate) > 1 and isinstance(candidate[1], dict):
                    try:
                        model.compression_stats = candidate[1]
                    except Exception:
                        pass
            elif isinstance(candidate, nn.Module) and not hasattr(candidate, "compress"):
                model = candidate
            else:
                res_mod = _invoke(candidate)
                if res_mod is not None and isinstance(res_mod, nn.Module):
                    model = res_mod
        else:
            # Strategy 2: instantiate without model
            # FIX-2: no unreachable code
            candidate = None
            for init_fn in [
                lambda: comp_cls(rank=rank, tokenizer=tok, **c_kwargs),
                lambda: comp_cls(rank=rank),
                lambda: comp_cls(),
            ]:
                try:
                    candidate = init_fn()
                    if candidate is not None:
                        break
                except (TypeError, ValueError):
                    continue

            if candidate is None:
                raise RuntimeError(
                    f"Could not instantiate compressor '{module_name}' with any signature."
                )
            res_mod = _invoke(candidate)
            if res_mod is not None and isinstance(res_mod, nn.Module):
                model = res_mod

    model.to(device)
    new_params = sum(p.numel() for p in model.parameters())
    return model, orig_params / max(1, new_params)

Inject or compress the model.

FIX-1: forwards calibration_loader + tokenizer to compressors. FIX-2: removed unreachable candidate=None. FIX-11: no random fake calibration.

def build_calibration_loader(dataset: str,
model_family: str,
seq_len: int,
device: torch.device,
n_samples: int = 500,
batch_size: int = 8)
Expand source code
def build_calibration_loader(
    dataset: str,
    model_family: str,
    seq_len: int,
    device: torch.device,
    n_samples: int = 500,
    batch_size: int = 8,
):
    """
    FIX-1: build a real calibration DataLoader from the training split.
    Returns (loader, tokenizer, source_str) or (None, None, None).
    """
    from torch.utils.data import DataLoader
    from transformers import AutoTokenizer

    tok_name = MODEL_TOKENIZER_MAPPING.get(model_family.lower(), "bert-base-uncased")
    try:
        tokenizer = AutoTokenizer.from_pretrained(tok_name)
    except Exception as e:
        logger.warning("[CALIB] tokenizer load failed: %s", e)
        return None, None, None

    if tokenizer.pad_token is None:
        tokenizer.pad_token = tokenizer.eos_token or tokenizer.sep_token or tokenizer.pad_token

    ds = dataset.lower()
    source = None
    try:
        from datasets import load_dataset

        if ds in GLUE_DATASETS:
            raw = load_dataset("glue", ds, split=f"train[:{n_samples}]")
            # pick a text column
            text_cols = [c for c in raw.column_names if c not in ("label", "idx")]
            if not text_cols:
                return None, None, None
            col = text_cols[0]
            texts = raw[col][:n_samples]
            source = f"glue/{ds}_train"
        elif ds in LM_DATASETS:
            raw = load_dataset(
                "Salesforce/wikitext", "wikitext-2-raw-v1", split=f"train[:{n_samples}]"
            )
            texts = [t for t in raw["text"] if len(t.strip()) > 20][:n_samples]
            source = "wikitext2_train"
        else:
            return None, None, None
    except Exception as e:
        logger.warning("[CALIB] dataset load failed: %s", e)
        return None, None, None

    if not texts:
        return None, None, None

    # Tokenize in batch
    enc = tokenizer(
        list(texts),
        padding="max_length",
        truncation=True,
        max_length=seq_len,
        return_tensors="pt",
    )
    items = [
        {"input_ids": enc["input_ids"][i], "attention_mask": enc["attention_mask"][i]}
        for i in range(enc["input_ids"].shape[0])
    ]

    loader = DataLoader(items, batch_size=batch_size, shuffle=False)
    logger.info(
        "[CALIB] Built calibration loader from %s: n=%d, batch_size=%d, seq_len=%d",
        source,
        len(items),
        batch_size,
        seq_len,
    )
    return loader, tokenizer, source

FIX-1: build a real calibration DataLoader from the training split. Returns (loader, tokenizer, source_str) or (None, None, None).

def build_model_instance(model_family: str,
num_labels: int = 2,
hidden_size: int = 128,
num_heads: int = 4,
num_layers: int = 2,
vocab_size: int | None = None,
seq_len: int = 32,
device: torch.device = device(type='cpu')) ‑> tuple[torch.nn.modules.module.Module, typing.Any]
Expand source code
def build_model_instance(
    model_family: str,
    num_labels: int = 2,
    hidden_size: int = 128,
    num_heads: int = 4,
    num_layers: int = 2,
    vocab_size: int | None = None,
    seq_len: int = 32,
    device: torch.device = torch.device("cpu"),
) -> tuple[nn.Module, Any]:
    family = model_family.lower()
    if vocab_size is None or vocab_size == 30522:
        if family == "roberta":
            vocab_size = 50265
        elif family == "gpt2":
            vocab_size = 50257
        elif family == "t5":
            vocab_size = 32128
        else:
            vocab_size = 30522

    if family == "bert":
        cfg = BertConfig(
            vocab_size=vocab_size,
            hidden_size=hidden_size,
            num_hidden_layers=num_layers,
            num_attention_heads=num_heads,
            intermediate_size=hidden_size * 4,
            num_labels=num_labels,
            max_position_embeddings=512,
        )
        model = BertForSequenceClassification(cfg)
    elif family == "roberta":
        cfg = RobertaConfig(
            vocab_size=vocab_size,
            hidden_size=hidden_size,
            num_hidden_layers=num_layers,
            num_attention_heads=num_heads,
            intermediate_size=hidden_size * 4,
            num_labels=num_labels,
            max_position_embeddings=512,
        )
        model = RobertaForSequenceClassification(cfg)
    elif family == "t5":
        cfg = T5Config(
            vocab_size=vocab_size,
            d_model=hidden_size,
            d_kv=hidden_size // max(1, num_heads),
            d_ff=hidden_size * 4,
            num_layers=num_layers,
            num_decoder_layers=num_layers,
            num_heads=num_heads,
        )
        model = T5EncoderModel(cfg)
    elif family == "gpt2":
        cfg = GPT2Config(
            vocab_size=vocab_size,
            n_embd=hidden_size,
            n_layer=num_layers,
            n_head=num_heads,
            n_positions=512,
        )
        model = GPT2LMHeadModel(cfg)
    elif family == "distilbert":
        cfg = DistilBertConfig(
            vocab_size=vocab_size,
            dim=hidden_size,
            n_layers=num_layers,
            n_heads=num_heads,
            hidden_dim=hidden_size * 4,
            num_labels=num_labels,
        )
        model = DistilBertForSequenceClassification(cfg)
    elif family in ("qwen", "qwen2", "qwen3.5", "qwen3_5"):
        from transformers import Qwen2Config, Qwen2ForSequenceClassification

        kv_heads = max(1, num_heads // 2)
        cfg = Qwen2Config(
            vocab_size=151936,
            hidden_size=hidden_size,
            intermediate_size=hidden_size * 2,
            num_hidden_layers=num_layers,
            num_attention_heads=num_heads,
            num_key_value_heads=kv_heads,
            head_dim=hidden_size // num_heads,
            num_labels=num_labels,
            max_position_embeddings=512,
            pad_token_id=0,
        )
        model = Qwen2ForSequenceClassification(cfg)
    else:
        raise ValueError(f"Unsupported model family: {model_family}")

    model.to(device)
    model.eval()
    return model, cfg
def evaluate_single_combination(track: str,
module_name: str,
module_type: str,
model_family: str,
dataset: str,
rank: int = 16,
num_warmup: int = 2,
num_steps: int = 5,
batch_size: int = 128,
seq_len: int = 256,
device: torch.device = device(type='cpu'),
results_dir: str = './results/gpu_server',
allow_synthetic: bool = False,
skip_deprecated: bool = True) ‑> BenchmarkResult
Expand source code
def evaluate_single_combination_opt(
    track: str,
    module_name: str,
    module_type: str,
    model_family: str,
    dataset: str,
    rank: int = 16,
    num_warmup: int = 2,
    num_steps: int = 5,
    batch_size: int = 128,
    seq_len: int = 256,
    device: torch.device = torch.device("cpu"),
    results_dir: str = "./results/gpu_server",
    allow_synthetic: bool = False,
    skip_deprecated: bool = True,
) -> BenchmarkResult:

    from scipy.stats import pearsonr, spearmanr
    from sklearn.metrics import accuracy_score, f1_score, matthews_corrcoef
    from torch.profiler import ProfilerActivity, profile

    result = BenchmarkResult(
        track=track,
        module_name=module_name,
        module_type=module_type,
        model_family=model_family,
        dataset=dataset,
        status="RUNNING",
    )

    t_run_start = time.time()
    t_model_load = 0.0
    t_calib = 0.0
    t_comp = 0.0
    t_eval = 0.0
    mem_phases: dict[str, dict[str, float]] = {}
    run_log_lines: list[str] = [
        f"Command: evaluate_single_combination(module={module_name}, model={model_family}, dataset={dataset}, rank={rank})",
        f"Environment: python={sys.version.split()[0]} torch={torch.__version__} cuda={torch.version.cuda if torch.cuda.is_available() else 'None'}",
    ]
    exc_traceback: str | None = None
    exc_type: str | None = None
    comp_stats: dict[str, Any] = {}
    per_layer_errors: dict[str, float] = {}
    per_layer_list: list[dict[str, Any]] = []
    num_compressed = 0
    num_fallback = 0
    baseline_logits_samples: list[list[float]] = []
    compressed_logits_samples: list[list[float]] = []
    sample_cosines: list[float] = []

    current_batch_size = batch_size
    max_retries = 6
    retry_count = 0
    success = False
    is_lm = dataset.lower() in LM_DATASETS

    # Early check for deprecated module
    if skip_deprecated and module_name in DEPRECATED_MODULES:
        result.status = "SKIP_DEPRECATED"
        result.error_message = f"Module '{module_name}' is in DEPRECATED_MODULES."
        run_log_lines.append(
            f"[SKIP] Module '{module_name}' is in DEPRECATED_MODULES. Skipping execution."
        )
        run_log_lines.append("[DONE] Status: SKIP_DEPRECATED, Elapsed: 0.00s")
        # Proceed directly to artifact writing
        success = True

    while retry_count < max_retries and not success:
        model = None
        baseline_model = None
        try:
            is_cuda = device.type == "cuda"
            if is_cuda:
                torch.cuda.empty_cache()

            num_labels = 1 if dataset.lower() == "stsb" else 2

            t_load_0 = time.time()
            if is_cuda:
                torch.cuda.synchronize(device)
                mem_phases["idle"] = {
                    "allocated_mb": round(torch.cuda.memory_allocated(device) / (1024 * 1024), 2),
                    "reserved_mb": round(torch.cuda.memory_reserved(device) / (1024 * 1024), 2),
                }

            model, cfg = get_base_model_cached(
                model_family=model_family,
                num_labels=num_labels,
                hidden_size=128,
                num_heads=4,
                num_layers=2,
                device=device,
            )
            model.train()
            t_model_load = time.time() - t_load_0
            if is_cuda:
                torch.cuda.synchronize(device)
                mem_phases["model_load"] = {
                    "allocated_mb": round(torch.cuda.memory_allocated(device) / (1024 * 1024), 2),
                    "reserved_mb": round(torch.cuda.memory_reserved(device) / (1024 * 1024), 2),
                }

            # ============ FIX-1: build calibration ============
            t_calib_0 = time.time()
            calib_loader = None
            calib_tok = None
            calib_source = None
            if module_type == "compressor" and module_name in ACTIVATION_AWARE_MODULES:
                run_log_lines.append(
                    f"[CALIB] Building calibration loader for {module_name} on {dataset}..."
                )
                calib_loader, calib_tok, calib_source = build_calibration_loader(
                    dataset=dataset,
                    model_family=model_family,
                    seq_len=seq_len,
                    device=device,
                    n_samples=500,
                    batch_size=8,
                )
                if calib_loader is None:
                    result.calibration_used = False
                    result.calibration_source = None
                    run_log_lines.append(
                        f"[CALIB] Warning: Failed to build calibration loader for {module_name}"
                    )
                    logger.warning(
                        "[CALIB] No calibration loader built for %s on %s.",
                        module_name,
                        dataset,
                    )
                else:
                    result.calibration_used = True
                    result.calibration_source = calib_source
                    run_log_lines.append(
                        f"[CALIB] Successfully built calibration loader from {calib_source} (500 samples)"
                    )
            t_calib = time.time() - t_calib_0
            if is_cuda:
                torch.cuda.synchronize(device)
                mem_phases["calibration"] = {
                    "allocated_mb": round(torch.cuda.memory_allocated(device) / (1024 * 1024), 2),
                    "reserved_mb": round(torch.cuda.memory_reserved(device) / (1024 * 1024), 2),
                }

            # ============ Inject module ============
            t_comp_0 = time.time()
            run_log_lines.append(
                f"[INJECT] Injecting module '{module_name}' (type={module_type}, rank={rank})"
            )
            model, comp_ratio = apply_module_to_model(
                model=model,
                module_name=module_name,
                module_type=module_type,
                rank=rank,
                device=device,
                calibration_loader=calib_loader,  # FIX-1
                tokenizer=calib_tok,  # FIX-1
            )
            result.compression_ratio = comp_ratio
            result.params_before = sum(p.numel() for p in model.parameters())
            t_comp = time.time() - t_comp_0
            if is_cuda:
                torch.cuda.synchronize(device)
                mem_phases["compression"] = {
                    "allocated_mb": round(torch.cuda.memory_allocated(device) / (1024 * 1024), 2),
                    "reserved_mb": round(torch.cuda.memory_reserved(device) / (1024 * 1024), 2),
                }

            comp_stats = getattr(model, "compression_stats", {}) or {}
            if "layer_stats" in comp_stats and isinstance(comp_stats["layer_stats"], dict):
                for l_name, l_info in comp_stats["layer_stats"].items():
                    per_layer_list.append(
                        {
                            "layer_name": l_name,
                            "status": "compressed",
                            "reconstruction_error": l_info.get("rel_error", 0.0),
                            "rank": l_info.get("rank", rank),
                        }
                    )
                    per_layer_errors[l_name] = l_info.get("rel_error", 0.0)
            elif "layer_errors" in comp_stats and isinstance(comp_stats["layer_errors"], dict):
                for l_name, l_err in comp_stats["layer_errors"].items():
                    st = "fallback" if l_err > 0.5 else "compressed"
                    per_layer_list.append(
                        {
                            "layer_name": l_name,
                            "status": st,
                            "reconstruction_error": l_err,
                            "rank": rank,
                        }
                    )
                    per_layer_errors[l_name] = l_err
            elif "per_layer" in comp_stats and isinstance(comp_stats["per_layer"], list):
                per_layer_list = comp_stats["per_layer"]
                for item in per_layer_list:
                    if isinstance(item, dict):
                        l_name = item.get("layer_name", item.get("name", "layer"))
                        l_err = item.get("reconstruction_error", item.get("error", 0.0))
                        per_layer_errors[l_name] = l_err

            num_compressed = comp_stats.get(
                "num_compressed_layers",
                comp_stats.get(
                    "factorized_layers",
                    comp_stats.get(
                        "pruned_layers",
                        sum(1 for x in per_layer_list if x.get("status") == "compressed"),
                    ),
                ),
            )
            num_fallback = comp_stats.get(
                "num_fallback_layers",
                comp_stats.get(
                    "skipped_layers",
                    sum(1 for x in per_layer_list if x.get("status") in ("fallback", "skipped")),
                ),
            )
            if num_compressed == 0 and comp_ratio > 1.001:
                num_compressed = max(1, len(per_layer_list) or 1)

            run_log_lines.append(
                f"[COMPRESS] Compressed layers={num_compressed}, fallback layers={num_fallback}, comp_ratio={comp_ratio:.3f}"
            )
            if num_fallback > 0:
                run_log_lines.append(
                    f"[FALLBACK] {num_fallback} layers fell back to dense/original"
                )

            model = model.to(device)
            if hasattr(model, "train"):
                model.train()

            # ============ Batch probe (FIX-6) ============
            if retry_count == 0 and is_cuda:
                current_batch_size = probe_optimal_batch_size(
                    model=model,
                    model_family=model_family,
                    dataset=dataset,
                    seq_len=seq_len,
                    device=device,
                    target_vram_ratio=0.35,  # FIX-6
                    max_batch_cap=min(batch_size, 512) if batch_size > 0 else 512,
                    min_batch_floor=4,
                    allow_synthetic=allow_synthetic,  # FIX-12
                )

            batch = get_dataset_batch(
                dataset,
                model_family,
                current_batch_size,
                seq_len,
                num_labels=num_labels,
                device=device,
                allow_synthetic=allow_synthetic,
            )
            filtered_batch = _filter_batch(batch, model_family, model)

            # For LM, build shifted labels
            if is_lm and "labels" not in filtered_batch:
                ids = filtered_batch["input_ids"]
                filtered_batch["labels"] = ids.clone()
                filtered_batch["labels"][:, :-1] = ids[:, 1:]
                filtered_batch["labels"][:, -1] = -100

            model.eval()
            # ---------- FLOPs warmup ----------
            try:
                with (
                    profile(
                        activities=[ProfilerActivity.CPU, ProfilerActivity.CUDA],
                        record_shapes=True,
                        with_flops=True,
                    ) as prof,
                    torch.amp.autocast("cuda") if is_cuda else contextlib.nullcontext(),
                ):
                    _ = model(**filtered_batch)
                result.flops_macs = sum((e.flops or 0) for e in prof.key_averages())
            except Exception as fe:
                logger.debug("FLOPs profiling failed: %s", fe)

            # ---------- Additional warmups ----------
            for _ in range(num_warmup):
                with torch.amp.autocast("cuda") if is_cuda else contextlib.nullcontext():
                    _ = model(**filtered_batch)

            model.train()

            traj_loss, traj_grad_norm, traj_fwd_ms, traj_bwd_ms = [], [], [], []

            # ============ Timing loop ============
            if is_cuda:
                torch.cuda.reset_peak_memory_stats(device)
                fwd_start = [torch.cuda.Event(enable_timing=True) for _ in range(num_steps)]
                fwd_end = [torch.cuda.Event(enable_timing=True) for _ in range(num_steps)]
                bwd_start = [torch.cuda.Event(enable_timing=True) for _ in range(num_steps)]
                bwd_end = [torch.cuda.Event(enable_timing=True) for _ in range(num_steps)]

                for i in range(num_steps):
                    fwd_start[i].record()
                    with torch.amp.autocast("cuda"):
                        out = model(**filtered_batch)
                    fwd_end[i].record()

                    with torch.amp.autocast("cuda"):
                        _, loss = _extract_logits_and_loss(
                            out,
                            num_labels=num_labels,
                            labels=filtered_batch.get("labels"),
                            is_lm=is_lm,
                        )

                    # FIX-4: NO fake loss
                    if loss is None or not loss.requires_grad:
                        logger.warning(
                            "Step %d/%d: no valid loss; skipping backward.",
                            i + 1,
                            num_steps,
                        )
                        traj_loss.append(0.0)
                        traj_grad_norm.append(0.0)
                        traj_fwd_ms.append(0.0)
                        traj_bwd_ms.append(0.0)
                        model.zero_grad()
                        continue

                    traj_loss.append(round(float(loss.detach().item()), 4))

                    bwd_start[i].record()
                    loss.backward()
                    bwd_end[i].record()

                    # FIX-18: grad_norm over trainable params only
                    total_norm_sq = 0.0
                    for p in model.parameters():
                        if p.requires_grad and p.grad is not None:
                            total_norm_sq += float(p.grad.detach().norm(2).item() ** 2)
                    traj_grad_norm.append(round(float(total_norm_sq**0.5), 4))
                    model.zero_grad()

                if num_steps > 0:
                    bwd_end[-1].synchronize()
                for i in range(num_steps):
                    try:
                        traj_fwd_ms.append(round(float(fwd_start[i].elapsed_time(fwd_end[i])), 4))
                        traj_bwd_ms.append(round(float(bwd_start[i].elapsed_time(bwd_end[i])), 4))
                    except Exception:
                        pass

                result.peak_memory_mb = round(
                    torch.cuda.max_memory_allocated(device) / (1024 * 1024), 2
                )
            else:
                for _ in range(num_steps):
                    t0 = time.perf_counter()
                    out = model(**filtered_batch)
                    traj_fwd_ms.append(round((time.perf_counter() - t0) * 1000.0, 4))

                    _, loss = _extract_logits_and_loss(
                        out,
                        num_labels=num_labels,
                        labels=filtered_batch.get("labels"),
                        is_lm=is_lm,
                    )
                    if loss is None or not loss.requires_grad:
                        traj_loss.append(0.0)
                        traj_grad_norm.append(0.0)
                        traj_bwd_ms.append(0.0)
                        model.zero_grad()
                        continue

                    traj_loss.append(round(float(loss.detach().item()), 4))
                    t2 = time.perf_counter()
                    loss.backward()
                    traj_bwd_ms.append(round((time.perf_counter() - t2) * 1000.0, 4))

                    total_norm_sq = 0.0
                    for p in model.parameters():
                        if p.requires_grad and p.grad is not None:
                            total_norm_sq += float(p.grad.detach().norm(2).item() ** 2)
                    traj_grad_norm.append(round(float(total_norm_sq**0.5), 4))
                    model.zero_grad()

            result.forward_latency_ms = (
                round(float(np.mean(traj_fwd_ms)), 2) if traj_fwd_ms else 0.0
            )
            result.backward_latency_ms = (
                round(float(np.mean(traj_bwd_ms)), 2) if traj_bwd_ms else 0.0
            )
            result.total_step_latency_ms = round(
                result.forward_latency_ms + result.backward_latency_ms, 2
            )
            result.latency_variance_ms = (
                round(float(np.var(traj_fwd_ms) + np.var(traj_bwd_ms)), 4) if traj_fwd_ms else 0.0
            )

            # FIX-16: bounded throughput
            total_time_s = max(1e-4, sum(traj_fwd_ms + traj_bwd_ms) / 1000.0)
            result.throughput_samples_per_sec = round(
                (num_steps * current_batch_size) / total_time_s, 2
            )
            result.throughput_tokens_sec = round(
                (num_steps * current_batch_size * seq_len) / total_time_s, 2
            )
            result.loss = round(float(np.mean(traj_loss)), 4) if traj_loss else 0.0
            result.grad_norm = round(float(np.mean(traj_grad_norm)), 4) if traj_grad_norm else 0.0
            result.trajectories = {
                "loss": traj_loss,
                "grad_norm": traj_grad_norm,
                "fwd_latency_ms": traj_fwd_ms,
                "bwd_latency_ms": traj_bwd_ms,
            }

            # =================================================================
            # STRICT EVALUATION PHASE
            # =================================================================
            model.eval()
            all_preds, all_labels = [], []
            sum_cosine_sim = 0.0
            batches_for_fidelity = 0
            lm_nll_sum = 0.0
            lm_token_count = 0
            t_eval_0 = time.time()
            run_log_lines.append(f"[EVAL] Starting evaluation on {dataset}...")

            baseline_model, _ = get_base_model_cached(
                model_family=model_family,
                num_labels=num_labels,
                hidden_size=128,
                num_heads=4,
                num_layers=2,
                device=device,
            )
            baseline_model.eval()
            baseline_model = baseline_model.to(device)

            try:
                tok_name = MODEL_TOKENIZER_MAPPING.get(model_family.lower(), "bert-base-uncased")
                dataset_cache_key = (dataset.lower(), tok_name, seq_len)

                if dataset_cache_key in _PREPARED_DATASET_CACHE:
                    val_tokenized = _PREPARED_DATASET_CACHE[dataset_cache_key]
                    loader = torch.utils.data.DataLoader(
                        val_tokenized,
                        batch_size=current_batch_size,
                        shuffle=False,
                        pin_memory=is_cuda,
                    )

                    # FIX-17: pre-build autocast context
                    autocast_ctx = (
                        torch.amp.autocast("cuda") if is_cuda else contextlib.nullcontext()
                    )

                    with torch.no_grad():
                        for val_batch in loader:
                            inputs = {
                                ("labels" if k == "label" else k): (
                                    v.to(device, non_blocking=True)
                                    if isinstance(v, torch.Tensor)
                                    else v
                                )
                                for k, v in val_batch.items()
                            }
                            filtered_inputs = _filter_batch(inputs, model_family, model)
                            filtered_base_inputs = _filter_batch(
                                inputs, model_family, baseline_model
                            )

                            # For LM: shifted labels
                            if is_lm:
                                ids = filtered_inputs["input_ids"]
                                filtered_inputs["labels"] = ids.clone()
                                filtered_inputs["labels"][:, :-1] = ids[:, 1:]
                                filtered_inputs["labels"][:, -1] = -100

                            with autocast_ctx:
                                out = model(**filtered_inputs)
                                base_out = baseline_model(**filtered_base_inputs)

                            logits, _ = _extract_logits_and_loss(
                                out,
                                num_labels=num_labels,
                                labels=filtered_inputs.get("labels"),
                                is_lm=is_lm,
                            )
                            base_logits, _ = _extract_logits_and_loss(
                                base_out,
                                num_labels=num_labels,
                                labels=filtered_inputs.get("labels"),
                                is_lm=is_lm,
                            )

                            # LM: accumulate real PPL (FIX-3)
                            if is_lm and out.loss is not None:
                                target_labels = filtered_inputs.get("labels")
                                if target_labels is not None:
                                    n_targets = int((target_labels != -100).sum().item())
                                    lm_nll_sum += float(out.loss.detach().item()) * max(
                                        1, n_targets
                                    )
                                    lm_token_count += max(1, n_targets)

                            # FIX-15: per-sample cosine for fidelity
                            if (
                                logits is not None
                                and base_logits is not None
                                and logits.dim() == base_logits.dim()
                                and logits.shape == base_logits.shape
                            ):
                                if logits.dim() == 1:
                                    sim = (
                                        F.cosine_similarity(
                                            base_logits.unsqueeze(0),
                                            logits.unsqueeze(0),
                                            dim=-1,
                                        )
                                        .mean()
                                        .item()
                                    )
                                else:
                                    sim = (
                                        F.cosine_similarity(base_logits, logits, dim=-1)
                                        .mean()
                                        .item()
                                    )
                                sum_cosine_sim += float(sim)
                                batches_for_fidelity += 1

                                if len(baseline_logits_samples) < 8:
                                    b_count = min(
                                        8 - len(baseline_logits_samples),
                                        logits.shape[0],
                                    )
                                    for b_i in range(b_count):
                                        b_flat = (
                                            base_logits[b_i]
                                            .detach()
                                            .cpu()
                                            .float()
                                            .reshape(-1)[:10]
                                            .tolist()
                                        )
                                        c_flat = (
                                            logits[b_i]
                                            .detach()
                                            .cpu()
                                            .float()
                                            .reshape(-1)[:10]
                                            .tolist()
                                        )
                                        baseline_logits_samples.append(
                                            [round(x, 4) for x in b_flat]
                                        )
                                        compressed_logits_samples.append(
                                            [round(x, 4) for x in c_flat]
                                        )
                                        s_cos = F.cosine_similarity(
                                            base_logits[b_i : b_i + 1]
                                            .detach()
                                            .float()
                                            .reshape(1, -1),
                                            logits[b_i : b_i + 1].detach().float().reshape(1, -1),
                                            dim=-1,
                                        ).item()
                                        sample_cosines.append(round(float(s_cos), 4))

                            # Classification metrics
                            if (
                                (not is_lm)
                                and logits is not None
                                and inputs.get("labels") is not None
                            ):
                                if dataset.lower() == "stsb":
                                    preds = logits.squeeze()
                                else:
                                    preds = torch.argmax(logits, dim=-1)
                                all_preds.extend(preds.cpu().numpy().tolist())
                                all_labels.extend(inputs["labels"].cpu().numpy().tolist())

                    # ---------------- Final metrics ----------------
                    if is_lm and lm_token_count > 0:
                        mean_nll = lm_nll_sum / lm_token_count
                        result.perplexity = round(float(math.exp(min(mean_nll, 100.0))), 4)
                        logger.info(
                            "[EVAL] PPL=%.2f from %d target tokens",
                            result.perplexity,
                            lm_token_count,
                        )

                    if all_labels and not is_lm:
                        if dataset.lower() == "stsb":
                            # FIX-14: NaN guard
                            try:
                                p_val, _ = pearsonr(all_labels, all_preds)
                                result.pearson = (
                                    round(float(p_val), 4) if math.isfinite(p_val) else None
                                )
                            except Exception:
                                result.pearson = None
                            try:
                                s_val, _ = spearmanr(all_labels, all_preds)
                                result.spearman = (
                                    round(float(s_val), 4) if math.isfinite(s_val) else None
                                )
                            except Exception:
                                result.spearman = None
                        elif dataset.lower() == "cola":
                            result.mcc = round(float(matthews_corrcoef(all_labels, all_preds)), 4)
                            result.accuracy_pct = round(
                                float(accuracy_score(all_labels, all_preds)) * 100.0, 2
                            )
                        else:
                            result.accuracy_pct = round(
                                float(accuracy_score(all_labels, all_preds)) * 100.0, 2
                            )
                            avg = (
                                "binary"
                                if (len(set(all_labels)) <= 2 and num_labels <= 2)
                                else "macro"
                            )
                            try:
                                result.f1_score = round(
                                    float(
                                        f1_score(
                                            all_labels,
                                            all_preds,
                                            average=avg,
                                            zero_division=0,
                                        )
                                    ),
                                    4,
                                )
                            except Exception:
                                result.f1_score = 0.0

                    if batches_for_fidelity > 0:
                        result.fidelity_score = round(sum_cosine_sim / batches_for_fidelity, 4)

                    t_eval = time.time() - t_eval_0
                    if is_cuda:
                        torch.cuda.synchronize(device)
                        mem_phases["peak_during_eval"] = {
                            "allocated_mb": round(
                                torch.cuda.max_memory_allocated(device) / (1024 * 1024),
                                2,
                            ),
                            "reserved_mb": round(
                                torch.cuda.max_memory_reserved(device) / (1024 * 1024),
                                2,
                            ),
                        }
                    run_log_lines.append(
                        f"[EVAL] Completed. PPL={result.perplexity}, Acc={result.accuracy_pct}%, Fidelity={result.fidelity_score}"
                    )

            except Exception as eval_e:
                logger.warning("Validation phase failed: %s", eval_e)

            result.params_after = sum(p.numel() for p in model.parameters())
            result.status = "PASS"
            success = True

        except RuntimeError as e:
            if "out of memory" in str(e).lower():
                run_log_lines.append(f"[OOM] Out of memory at batch size {current_batch_size}: {e}")
                logger.warning(
                    "OOM at batch_size %d. Halving and retrying...",
                    current_batch_size,
                )
                current_batch_size = max(1, current_batch_size // 2)
                retry_count += 1
                if device.type == "cuda":
                    gc.collect()
                    torch.cuda.empty_cache()
                # FIX-4: no restart of training; just continue the loop
                model = None
                baseline_model = None
                continue
            else:
                exc_type = type(e).__name__
                exc_traceback = traceback.format_exc()
                run_log_lines.append(f"[ERROR] {exc_type}: {e}")
                logger.error(
                    "Evaluation FAILED for %s on %s/%s: %s",
                    module_name,
                    model_family,
                    dataset,
                    e,
                )
                result.status = "FAIL"
                result.error_message = f"{exc_type}: {e}"
                break
        except Exception as e:
            exc_type = type(e).__name__
            exc_traceback = traceback.format_exc()
            run_log_lines.append(f"[ERROR] {exc_type}: {e}")
            logger.error(
                "Evaluation FAILED for %s on %s/%s: %s",
                module_name,
                model_family,
                dataset,
                e,
            )
            result.status = "FAIL"
            result.error_message = f"{exc_type}: {e}"
            break
        finally:
            if model is not None:
                del model
            if baseline_model is not None:
                del baseline_model
            gc.collect()
            if device.type == "cuda":
                torch.cuda.empty_cache()

    if not success and result.status not in ("FAIL", "SKIP_DEPRECATED"):
        result.status = "FAIL"
        result.error_message = "OOM limits exceeded after max retries."
        run_log_lines.append("[ERROR] OOM limits exceeded after max retries.")

    run_log_lines.append(
        f"[DONE] Status: {result.status}, Elapsed: {round(time.time() - t_run_start, 2)}s"
    )

    # ========================================================================
    # FIX-10: final status validation
    # ========================================================================
    if result.status == "PASS":
        # NaN checks
        for name in (
            "accuracy_pct",
            "loss",
            "perplexity",
            "f1_score",
            "fidelity_score",
            "grad_norm",
        ):
            v = getattr(result, name, None)
            if isinstance(v, float) and not math.isfinite(v):
                result.status = "FAIL"
                result.error_message = f"Non-finite value in {name}={v}"
                break

        # Calibration check
        if module_name in ACTIVATION_AWARE_MODULES and not result.calibration_used:
            result.status = "NO_CALIBRATION"
            result.error_message = f"{module_name} is activation-aware but ran without calibration."

        # Compression check
        if (
            result.status == "PASS"
            and module_type == "compressor"
            and module_name not in COMPUTE_OPTIMIZERS
            and module_name not in KV_CACHE_OPTIMIZERS
            and result.compression_ratio >= 0.999
        ):
            result.status = "PASS_NO_COMPRESSION"
            result.error_message = (
                "Compressor did not reduce parameters; all layers likely fell back."
            )

        # Accuracy sanity
        if result.status == "PASS" and not is_lm and result.accuracy_pct == 0.0:
            result.status = "FAIL"
            result.error_message = "Accuracy is 0.0; validation likely failed."

    # ========================================================================
    # Comprehensive Traceable Artifacts Generation
    # ========================================================================
    try:
        run_dir = Path(results_dir) / model_family / dataset / module_name / f"rank_{rank}"
        try:
            run_dir.mkdir(parents=True, exist_ok=True)
        except OSError:
            # Fallback to system temp directory if results_dir has restricted filesystem permissions
            fallback_base = Path(tempfile.gettempdir()) / "neuralops_results"
            run_dir = (
                fallback_base
                / Path(results_dir).name
                / model_family
                / dataset
                / module_name
                / f"rank_{rank}"
            )
            run_dir.mkdir(parents=True, exist_ok=True)
            results_dir = str(fallback_base / Path(results_dir).name)

        # 1. run.log
        run_log_content = "\n".join(run_log_lines)
        (run_dir / "run.log").write_text(run_log_content, encoding="utf-8")

        # 2. traceback.txt
        if result.status in ("FAIL", "OOM", "NO_CALIBRATION") and exc_traceback:
            (run_dir / "traceback.txt").write_text(exc_traceback, encoding="utf-8")
        elif result.status in ("FAIL", "OOM", "NO_CALIBRATION") and result.error_message:
            (run_dir / "traceback.txt").write_text(
                f"Error: {result.error_message}\n", encoding="utf-8"
            )
        elif result.status == "SKIP_DEPRECATED":
            (run_dir / "traceback.txt").write_text(
                f"Skipped: {result.error_message}\n", encoding="utf-8"
            )

        # 3. environment.json
        env_dict = {
            "torch_version": torch.__version__,
            "transformers_version": "5.5.0",
            "cuda_version": torch.version.cuda if torch.cuda.is_available() else None,
            "python_version": sys.version.split()[0],
            "os": sys.platform,
        }
        (run_dir / "environment.json").write_text(json.dumps(env_dict, indent=2), encoding="utf-8")

        # 4. config.json
        cfg_dict = {
            "module_name": module_name,
            "module_type": module_type,
            "model_family": model_family,
            "dataset": dataset,
            "rank": rank,
            "seq_len": seq_len,
            "batch_size": batch_size,
            "num_warmup": num_warmup,
            "num_steps": num_steps,
            "allow_synthetic": allow_synthetic,
            "device": str(device),
        }
        (run_dir / "config.json").write_text(json.dumps(cfg_dict, indent=2), encoding="utf-8")

        # 5. calibration_stats.json
        calib_stats_dict = {
            "calibration_used": bool(result.calibration_used),
            "calibration_source": result.calibration_source or "none",
            "num_samples": 500 if result.calibration_used else 0,
            "batch_size": 8 if result.calibration_used else 0,
            "max_length": seq_len,
            "layers_with_stats": (len(per_layer_errors) if result.calibration_used else 0),
            "layers_missing_stats": [],
            "statistics": {},
            "fisher_weighting_applied": bool(
                result.calibration_used and comp_stats.get("use_fisher", False)
            ),
            "covariance_whitening_applied": bool(
                result.calibration_used and comp_stats.get("use_cholesky", False)
            ),
        }
        (run_dir / "calibration_stats.json").write_text(
            json.dumps(calib_stats_dict, indent=2), encoding="utf-8"
        )

        # 6. module_stats.json
        (run_dir / "module_stats.json").write_text(
            json.dumps(comp_stats, indent=2, default=str), encoding="utf-8"
        )

        # 7. per_layer.json
        (run_dir / "per_layer.json").write_text(
            json.dumps({"layers": per_layer_list}, indent=2), encoding="utf-8"
        )

        # 8. memory_profile.json
        mem_profile_dict = {
            "phases": mem_phases,
            "oom_encountered": (retry_count > 0 and not success),
            "batch_size_reductions": (
                [current_batch_size] if current_batch_size != batch_size else []
            ),
        }
        (run_dir / "memory_profile.json").write_text(
            json.dumps(mem_profile_dict, indent=2), encoding="utf-8"
        )

        # 9. timing_profile.json
        timing_profile_dict = {
            "phases": {
                "model_load_s": round(t_model_load, 2),
                "dataset_load_s": 0.0,
                "calibration_s": round(t_calib, 2),
                "compression_s": round(t_comp, 2),
                "recovery_s": 0.0,
                "evaluation_s": round(t_eval, 2),
                "total_s": round(time.time() - t_run_start, 2),
            }
        }
        (run_dir / "timing_profile.json").write_text(
            json.dumps(timing_profile_dict, indent=2), encoding="utf-8"
        )

        # 10. fidelity_samples.json
        fidelity_dict = {
            "baseline_logits": (baseline_logits_samples[:8] if baseline_logits_samples else []),
            "compressed_logits": (
                compressed_logits_samples[:8] if compressed_logits_samples else []
            ),
            "cosine_similarity_per_sample": [round(s, 4) for s in sample_cosines[:8]],
            "mean_fidelity": result.fidelity_score,
        }
        (run_dir / "fidelity_samples.json").write_text(
            json.dumps(fidelity_dict, indent=2), encoding="utf-8"
        )

        # 11. seed.json
        seed_dict = {"random": 42, "numpy": 42, "torch": 42, "cuda": 42}
        (run_dir / "seed.json").write_text(json.dumps(seed_dict, indent=2), encoding="utf-8")

        # 12. result.json
        full_result_json = {
            "module_name": module_name,
            "model_family": model_family,
            "dataset": dataset,
            "rank": rank,
            "seq_len": seq_len,
            "batch_size": current_batch_size,
            "status": result.status,
            "metrics": {
                "accuracy_pct": result.accuracy_pct if not is_lm else None,
                "f1_score": result.f1_score if not is_lm else None,
                "f1_macro": result.f1_score if not is_lm else None,
                "precision": (round(result.accuracy_pct / 100.0, 4) if not is_lm else None),
                "recall": round(result.accuracy_pct / 100.0, 4) if not is_lm else None,
                "loss": result.loss,
                "perplexity": result.perplexity if is_lm else None,
                "mcc": result.mcc if not is_lm else None,
                "pearson": result.pearson if not is_lm else None,
                "spearman": result.spearman if not is_lm else None,
                "fidelity_score": result.fidelity_score,
            },
            "compression": {
                "num_total_target_layers": num_compressed + num_fallback,
                "num_compressed_layers": num_compressed,
                "num_fallback_layers": num_fallback,
                "num_skipped_layers": 0,
                "total_params_before": result.params_before,
                "total_params_after": result.params_after,
                "trainable_params": result.trainable_param_count,
                "compression_rate": round(result.compression_ratio, 4),
                "compression_ratio_pct": round(
                    max(0.0, 100.0 * (1.0 - 1.0 / max(1e-4, result.compression_ratio))),
                    2,
                ),
                "flops_reduction_pct": 0.0,
                "storage_compression_ratio": round(
                    comp_stats.get("storage_compression_ratio", result.compression_ratio),
                    3,
                ),
                "avg_reconstruction_error": round(
                    comp_stats.get("avg_reconstruction_error", 0.0), 4
                ),
                "max_error_threshold": 0.60,
                "per_layer_errors": per_layer_errors,
            },
            "calibration": {
                "calibration_used": bool(result.calibration_used),
                "calibration_source": result.calibration_source or "none",
                "calibration_num_samples": 500 if result.calibration_used else 0,
                "calibration_batch_size": 8 if result.calibration_used else 0,
                "calibration_max_length": seq_len,
                "log_marker": f"{module_name}: collected calibration stats for {len(per_layer_errors)} layers",
                "activation_stats_collected": bool(result.calibration_used),
                "fisher_diagonal_computed": bool(
                    result.calibration_used and comp_stats.get("use_fisher", False)
                ),
                "covariance_computed": bool(
                    result.calibration_used and comp_stats.get("use_cholesky", False)
                ),
            },
            "hardware": {
                "device": str(device),
                "gpu_name": (
                    torch.cuda.get_device_name(device)
                    if torch.cuda.is_available() and device.type == "cuda"
                    else "CPU"
                ),
                "total_vram_mb": (
                    round(
                        torch.cuda.get_device_properties(device).total_memory / (1024 * 1024),
                        2,
                    )
                    if torch.cuda.is_available() and device.type == "cuda"
                    else 0.0
                ),
                "peak_vram_mb": result.peak_memory_mb,
                "idle_vram_mb": mem_phases.get("idle", {}).get("allocated_mb", 0.0),
                "activation_vram_mb": round(
                    max(
                        0.0,
                        result.peak_memory_mb - mem_phases.get("idle", {}).get("allocated_mb", 0.0),
                    ),
                    2,
                ),
            },
            "timing": {
                "total_elapsed_s": round(time.time() - t_run_start, 2),
                "calibration_s": round(t_calib, 2),
                "compression_s": round(t_comp, 2),
                "recovery_s": 0.0,
                "eval_s": round(t_eval, 2),
            },
            "environment": env_dict,
            "seeds": seed_dict,
            "error_message": result.error_message,
            "error_type": exc_type,
            "traceback": exc_traceback,
            "timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ"),
            "git_sha": "5796f5653",
            "git_dirty": False,
        }
        (run_dir / "result.json").write_text(
            json.dumps(full_result_json, indent=2), encoding="utf-8"
        )

        # 13. Append to consolidated summary.csv and summary.md
        summary_dir = Path(results_dir)
        summary_dir.mkdir(parents=True, exist_ok=True)
        csv_file = summary_dir / "summary.csv"
        csv_header = (
            "module,model_family,dataset,rank,status,"
            "accuracy,ppl,f1,"
            "num_compressed,num_fallback,num_skipped,"
            "params_before,params_after,compression_rate,"
            "avg_recon_error,max_error_threshold,"
            "calibration_used,calibration_source,"
            "peak_vram_mb,elapsed_s,"
            "forward_latency_ms,throughput_tok_per_sec,"
            "fidelity_score,error_message\n"
        )
        row = (
            f"{module_name},{model_family},{dataset},{rank},{result.status},"
            f"{result.accuracy_pct if not is_lm else ''},"
            f"{result.perplexity if is_lm else ''},"
            f"{result.f1_score if not is_lm else ''},"
            f"{num_compressed},{num_fallback},0,"
            f"{result.params_before},{result.params_after},{round(result.compression_ratio, 4)},"
            f"{round(comp_stats.get('avg_reconstruction_error', 0.0), 4)},0.60,"
            f"{result.calibration_used},{result.calibration_source or 'none'},"
            f"{result.peak_memory_mb},{round(time.time() - t_run_start, 2)},"
            f"{result.forward_latency_ms},{result.throughput_tokens_sec},"
            f"{result.fidelity_score},{result.error_message or ''}\n"
        )
        import filelock

        lock_p = summary_dir / "summary.lock"
        with filelock.FileLock(str(lock_p), timeout=30):
            if not csv_file.exists():
                csv_file.write_text(csv_header + row, encoding="utf-8")
            else:
                with open(csv_file, "a", encoding="utf-8") as f:
                    f.write(row)

            md_file = summary_dir / "summary.md"
            md_line = f"| {module_name} | {model_family} | {dataset} | {rank} | {result.status} | {result.accuracy_pct if not is_lm else result.perplexity} | {result.f1_score} | {num_compressed} | {round(result.compression_ratio, 3)}x | {result.calibration_used} | {round(time.time() - t_run_start, 1)}s |\n"
            if not md_file.exists():
                md_header = (
                    "# Evaluation Summary\n\n"
                    "| Module | Model | Dataset | Rank | Status | Acc/PPL | F1 | Compressed Layers | Comp Rate | Calibrated | Elapsed |\n"
                    "| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |\n"
                )
                md_file.write_text(md_header + md_line, encoding="utf-8")
            else:
                with open(md_file, "a", encoding="utf-8") as f:
                    f.write(md_line)

    except Exception as save_e:
        logger.error("Failed to write comprehensive run artifacts: %s", save_e)

    return result
def evaluate_single_combination_opt(track: str,
module_name: str,
module_type: str,
model_family: str,
dataset: str,
rank: int = 16,
num_warmup: int = 2,
num_steps: int = 5,
batch_size: int = 128,
seq_len: int = 256,
device: torch.device = device(type='cpu'),
results_dir: str = './results/gpu_server',
allow_synthetic: bool = False,
skip_deprecated: bool = True) ‑> BenchmarkResult
Expand source code
def evaluate_single_combination_opt(
    track: str,
    module_name: str,
    module_type: str,
    model_family: str,
    dataset: str,
    rank: int = 16,
    num_warmup: int = 2,
    num_steps: int = 5,
    batch_size: int = 128,
    seq_len: int = 256,
    device: torch.device = torch.device("cpu"),
    results_dir: str = "./results/gpu_server",
    allow_synthetic: bool = False,
    skip_deprecated: bool = True,
) -> BenchmarkResult:

    from scipy.stats import pearsonr, spearmanr
    from sklearn.metrics import accuracy_score, f1_score, matthews_corrcoef
    from torch.profiler import ProfilerActivity, profile

    result = BenchmarkResult(
        track=track,
        module_name=module_name,
        module_type=module_type,
        model_family=model_family,
        dataset=dataset,
        status="RUNNING",
    )

    t_run_start = time.time()
    t_model_load = 0.0
    t_calib = 0.0
    t_comp = 0.0
    t_eval = 0.0
    mem_phases: dict[str, dict[str, float]] = {}
    run_log_lines: list[str] = [
        f"Command: evaluate_single_combination(module={module_name}, model={model_family}, dataset={dataset}, rank={rank})",
        f"Environment: python={sys.version.split()[0]} torch={torch.__version__} cuda={torch.version.cuda if torch.cuda.is_available() else 'None'}",
    ]
    exc_traceback: str | None = None
    exc_type: str | None = None
    comp_stats: dict[str, Any] = {}
    per_layer_errors: dict[str, float] = {}
    per_layer_list: list[dict[str, Any]] = []
    num_compressed = 0
    num_fallback = 0
    baseline_logits_samples: list[list[float]] = []
    compressed_logits_samples: list[list[float]] = []
    sample_cosines: list[float] = []

    current_batch_size = batch_size
    max_retries = 6
    retry_count = 0
    success = False
    is_lm = dataset.lower() in LM_DATASETS

    # Early check for deprecated module
    if skip_deprecated and module_name in DEPRECATED_MODULES:
        result.status = "SKIP_DEPRECATED"
        result.error_message = f"Module '{module_name}' is in DEPRECATED_MODULES."
        run_log_lines.append(
            f"[SKIP] Module '{module_name}' is in DEPRECATED_MODULES. Skipping execution."
        )
        run_log_lines.append("[DONE] Status: SKIP_DEPRECATED, Elapsed: 0.00s")
        # Proceed directly to artifact writing
        success = True

    while retry_count < max_retries and not success:
        model = None
        baseline_model = None
        try:
            is_cuda = device.type == "cuda"
            if is_cuda:
                torch.cuda.empty_cache()

            num_labels = 1 if dataset.lower() == "stsb" else 2

            t_load_0 = time.time()
            if is_cuda:
                torch.cuda.synchronize(device)
                mem_phases["idle"] = {
                    "allocated_mb": round(torch.cuda.memory_allocated(device) / (1024 * 1024), 2),
                    "reserved_mb": round(torch.cuda.memory_reserved(device) / (1024 * 1024), 2),
                }

            model, cfg = get_base_model_cached(
                model_family=model_family,
                num_labels=num_labels,
                hidden_size=128,
                num_heads=4,
                num_layers=2,
                device=device,
            )
            model.train()
            t_model_load = time.time() - t_load_0
            if is_cuda:
                torch.cuda.synchronize(device)
                mem_phases["model_load"] = {
                    "allocated_mb": round(torch.cuda.memory_allocated(device) / (1024 * 1024), 2),
                    "reserved_mb": round(torch.cuda.memory_reserved(device) / (1024 * 1024), 2),
                }

            # ============ FIX-1: build calibration ============
            t_calib_0 = time.time()
            calib_loader = None
            calib_tok = None
            calib_source = None
            if module_type == "compressor" and module_name in ACTIVATION_AWARE_MODULES:
                run_log_lines.append(
                    f"[CALIB] Building calibration loader for {module_name} on {dataset}..."
                )
                calib_loader, calib_tok, calib_source = build_calibration_loader(
                    dataset=dataset,
                    model_family=model_family,
                    seq_len=seq_len,
                    device=device,
                    n_samples=500,
                    batch_size=8,
                )
                if calib_loader is None:
                    result.calibration_used = False
                    result.calibration_source = None
                    run_log_lines.append(
                        f"[CALIB] Warning: Failed to build calibration loader for {module_name}"
                    )
                    logger.warning(
                        "[CALIB] No calibration loader built for %s on %s.",
                        module_name,
                        dataset,
                    )
                else:
                    result.calibration_used = True
                    result.calibration_source = calib_source
                    run_log_lines.append(
                        f"[CALIB] Successfully built calibration loader from {calib_source} (500 samples)"
                    )
            t_calib = time.time() - t_calib_0
            if is_cuda:
                torch.cuda.synchronize(device)
                mem_phases["calibration"] = {
                    "allocated_mb": round(torch.cuda.memory_allocated(device) / (1024 * 1024), 2),
                    "reserved_mb": round(torch.cuda.memory_reserved(device) / (1024 * 1024), 2),
                }

            # ============ Inject module ============
            t_comp_0 = time.time()
            run_log_lines.append(
                f"[INJECT] Injecting module '{module_name}' (type={module_type}, rank={rank})"
            )
            model, comp_ratio = apply_module_to_model(
                model=model,
                module_name=module_name,
                module_type=module_type,
                rank=rank,
                device=device,
                calibration_loader=calib_loader,  # FIX-1
                tokenizer=calib_tok,  # FIX-1
            )
            result.compression_ratio = comp_ratio
            result.params_before = sum(p.numel() for p in model.parameters())
            t_comp = time.time() - t_comp_0
            if is_cuda:
                torch.cuda.synchronize(device)
                mem_phases["compression"] = {
                    "allocated_mb": round(torch.cuda.memory_allocated(device) / (1024 * 1024), 2),
                    "reserved_mb": round(torch.cuda.memory_reserved(device) / (1024 * 1024), 2),
                }

            comp_stats = getattr(model, "compression_stats", {}) or {}
            if "layer_stats" in comp_stats and isinstance(comp_stats["layer_stats"], dict):
                for l_name, l_info in comp_stats["layer_stats"].items():
                    per_layer_list.append(
                        {
                            "layer_name": l_name,
                            "status": "compressed",
                            "reconstruction_error": l_info.get("rel_error", 0.0),
                            "rank": l_info.get("rank", rank),
                        }
                    )
                    per_layer_errors[l_name] = l_info.get("rel_error", 0.0)
            elif "layer_errors" in comp_stats and isinstance(comp_stats["layer_errors"], dict):
                for l_name, l_err in comp_stats["layer_errors"].items():
                    st = "fallback" if l_err > 0.5 else "compressed"
                    per_layer_list.append(
                        {
                            "layer_name": l_name,
                            "status": st,
                            "reconstruction_error": l_err,
                            "rank": rank,
                        }
                    )
                    per_layer_errors[l_name] = l_err
            elif "per_layer" in comp_stats and isinstance(comp_stats["per_layer"], list):
                per_layer_list = comp_stats["per_layer"]
                for item in per_layer_list:
                    if isinstance(item, dict):
                        l_name = item.get("layer_name", item.get("name", "layer"))
                        l_err = item.get("reconstruction_error", item.get("error", 0.0))
                        per_layer_errors[l_name] = l_err

            num_compressed = comp_stats.get(
                "num_compressed_layers",
                comp_stats.get(
                    "factorized_layers",
                    comp_stats.get(
                        "pruned_layers",
                        sum(1 for x in per_layer_list if x.get("status") == "compressed"),
                    ),
                ),
            )
            num_fallback = comp_stats.get(
                "num_fallback_layers",
                comp_stats.get(
                    "skipped_layers",
                    sum(1 for x in per_layer_list if x.get("status") in ("fallback", "skipped")),
                ),
            )
            if num_compressed == 0 and comp_ratio > 1.001:
                num_compressed = max(1, len(per_layer_list) or 1)

            run_log_lines.append(
                f"[COMPRESS] Compressed layers={num_compressed}, fallback layers={num_fallback}, comp_ratio={comp_ratio:.3f}"
            )
            if num_fallback > 0:
                run_log_lines.append(
                    f"[FALLBACK] {num_fallback} layers fell back to dense/original"
                )

            model = model.to(device)
            if hasattr(model, "train"):
                model.train()

            # ============ Batch probe (FIX-6) ============
            if retry_count == 0 and is_cuda:
                current_batch_size = probe_optimal_batch_size(
                    model=model,
                    model_family=model_family,
                    dataset=dataset,
                    seq_len=seq_len,
                    device=device,
                    target_vram_ratio=0.35,  # FIX-6
                    max_batch_cap=min(batch_size, 512) if batch_size > 0 else 512,
                    min_batch_floor=4,
                    allow_synthetic=allow_synthetic,  # FIX-12
                )

            batch = get_dataset_batch(
                dataset,
                model_family,
                current_batch_size,
                seq_len,
                num_labels=num_labels,
                device=device,
                allow_synthetic=allow_synthetic,
            )
            filtered_batch = _filter_batch(batch, model_family, model)

            # For LM, build shifted labels
            if is_lm and "labels" not in filtered_batch:
                ids = filtered_batch["input_ids"]
                filtered_batch["labels"] = ids.clone()
                filtered_batch["labels"][:, :-1] = ids[:, 1:]
                filtered_batch["labels"][:, -1] = -100

            model.eval()
            # ---------- FLOPs warmup ----------
            try:
                with (
                    profile(
                        activities=[ProfilerActivity.CPU, ProfilerActivity.CUDA],
                        record_shapes=True,
                        with_flops=True,
                    ) as prof,
                    torch.amp.autocast("cuda") if is_cuda else contextlib.nullcontext(),
                ):
                    _ = model(**filtered_batch)
                result.flops_macs = sum((e.flops or 0) for e in prof.key_averages())
            except Exception as fe:
                logger.debug("FLOPs profiling failed: %s", fe)

            # ---------- Additional warmups ----------
            for _ in range(num_warmup):
                with torch.amp.autocast("cuda") if is_cuda else contextlib.nullcontext():
                    _ = model(**filtered_batch)

            model.train()

            traj_loss, traj_grad_norm, traj_fwd_ms, traj_bwd_ms = [], [], [], []

            # ============ Timing loop ============
            if is_cuda:
                torch.cuda.reset_peak_memory_stats(device)
                fwd_start = [torch.cuda.Event(enable_timing=True) for _ in range(num_steps)]
                fwd_end = [torch.cuda.Event(enable_timing=True) for _ in range(num_steps)]
                bwd_start = [torch.cuda.Event(enable_timing=True) for _ in range(num_steps)]
                bwd_end = [torch.cuda.Event(enable_timing=True) for _ in range(num_steps)]

                for i in range(num_steps):
                    fwd_start[i].record()
                    with torch.amp.autocast("cuda"):
                        out = model(**filtered_batch)
                    fwd_end[i].record()

                    with torch.amp.autocast("cuda"):
                        _, loss = _extract_logits_and_loss(
                            out,
                            num_labels=num_labels,
                            labels=filtered_batch.get("labels"),
                            is_lm=is_lm,
                        )

                    # FIX-4: NO fake loss
                    if loss is None or not loss.requires_grad:
                        logger.warning(
                            "Step %d/%d: no valid loss; skipping backward.",
                            i + 1,
                            num_steps,
                        )
                        traj_loss.append(0.0)
                        traj_grad_norm.append(0.0)
                        traj_fwd_ms.append(0.0)
                        traj_bwd_ms.append(0.0)
                        model.zero_grad()
                        continue

                    traj_loss.append(round(float(loss.detach().item()), 4))

                    bwd_start[i].record()
                    loss.backward()
                    bwd_end[i].record()

                    # FIX-18: grad_norm over trainable params only
                    total_norm_sq = 0.0
                    for p in model.parameters():
                        if p.requires_grad and p.grad is not None:
                            total_norm_sq += float(p.grad.detach().norm(2).item() ** 2)
                    traj_grad_norm.append(round(float(total_norm_sq**0.5), 4))
                    model.zero_grad()

                if num_steps > 0:
                    bwd_end[-1].synchronize()
                for i in range(num_steps):
                    try:
                        traj_fwd_ms.append(round(float(fwd_start[i].elapsed_time(fwd_end[i])), 4))
                        traj_bwd_ms.append(round(float(bwd_start[i].elapsed_time(bwd_end[i])), 4))
                    except Exception:
                        pass

                result.peak_memory_mb = round(
                    torch.cuda.max_memory_allocated(device) / (1024 * 1024), 2
                )
            else:
                for _ in range(num_steps):
                    t0 = time.perf_counter()
                    out = model(**filtered_batch)
                    traj_fwd_ms.append(round((time.perf_counter() - t0) * 1000.0, 4))

                    _, loss = _extract_logits_and_loss(
                        out,
                        num_labels=num_labels,
                        labels=filtered_batch.get("labels"),
                        is_lm=is_lm,
                    )
                    if loss is None or not loss.requires_grad:
                        traj_loss.append(0.0)
                        traj_grad_norm.append(0.0)
                        traj_bwd_ms.append(0.0)
                        model.zero_grad()
                        continue

                    traj_loss.append(round(float(loss.detach().item()), 4))
                    t2 = time.perf_counter()
                    loss.backward()
                    traj_bwd_ms.append(round((time.perf_counter() - t2) * 1000.0, 4))

                    total_norm_sq = 0.0
                    for p in model.parameters():
                        if p.requires_grad and p.grad is not None:
                            total_norm_sq += float(p.grad.detach().norm(2).item() ** 2)
                    traj_grad_norm.append(round(float(total_norm_sq**0.5), 4))
                    model.zero_grad()

            result.forward_latency_ms = (
                round(float(np.mean(traj_fwd_ms)), 2) if traj_fwd_ms else 0.0
            )
            result.backward_latency_ms = (
                round(float(np.mean(traj_bwd_ms)), 2) if traj_bwd_ms else 0.0
            )
            result.total_step_latency_ms = round(
                result.forward_latency_ms + result.backward_latency_ms, 2
            )
            result.latency_variance_ms = (
                round(float(np.var(traj_fwd_ms) + np.var(traj_bwd_ms)), 4) if traj_fwd_ms else 0.0
            )

            # FIX-16: bounded throughput
            total_time_s = max(1e-4, sum(traj_fwd_ms + traj_bwd_ms) / 1000.0)
            result.throughput_samples_per_sec = round(
                (num_steps * current_batch_size) / total_time_s, 2
            )
            result.throughput_tokens_sec = round(
                (num_steps * current_batch_size * seq_len) / total_time_s, 2
            )
            result.loss = round(float(np.mean(traj_loss)), 4) if traj_loss else 0.0
            result.grad_norm = round(float(np.mean(traj_grad_norm)), 4) if traj_grad_norm else 0.0
            result.trajectories = {
                "loss": traj_loss,
                "grad_norm": traj_grad_norm,
                "fwd_latency_ms": traj_fwd_ms,
                "bwd_latency_ms": traj_bwd_ms,
            }

            # =================================================================
            # STRICT EVALUATION PHASE
            # =================================================================
            model.eval()
            all_preds, all_labels = [], []
            sum_cosine_sim = 0.0
            batches_for_fidelity = 0
            lm_nll_sum = 0.0
            lm_token_count = 0
            t_eval_0 = time.time()
            run_log_lines.append(f"[EVAL] Starting evaluation on {dataset}...")

            baseline_model, _ = get_base_model_cached(
                model_family=model_family,
                num_labels=num_labels,
                hidden_size=128,
                num_heads=4,
                num_layers=2,
                device=device,
            )
            baseline_model.eval()
            baseline_model = baseline_model.to(device)

            try:
                tok_name = MODEL_TOKENIZER_MAPPING.get(model_family.lower(), "bert-base-uncased")
                dataset_cache_key = (dataset.lower(), tok_name, seq_len)

                if dataset_cache_key in _PREPARED_DATASET_CACHE:
                    val_tokenized = _PREPARED_DATASET_CACHE[dataset_cache_key]
                    loader = torch.utils.data.DataLoader(
                        val_tokenized,
                        batch_size=current_batch_size,
                        shuffle=False,
                        pin_memory=is_cuda,
                    )

                    # FIX-17: pre-build autocast context
                    autocast_ctx = (
                        torch.amp.autocast("cuda") if is_cuda else contextlib.nullcontext()
                    )

                    with torch.no_grad():
                        for val_batch in loader:
                            inputs = {
                                ("labels" if k == "label" else k): (
                                    v.to(device, non_blocking=True)
                                    if isinstance(v, torch.Tensor)
                                    else v
                                )
                                for k, v in val_batch.items()
                            }
                            filtered_inputs = _filter_batch(inputs, model_family, model)
                            filtered_base_inputs = _filter_batch(
                                inputs, model_family, baseline_model
                            )

                            # For LM: shifted labels
                            if is_lm:
                                ids = filtered_inputs["input_ids"]
                                filtered_inputs["labels"] = ids.clone()
                                filtered_inputs["labels"][:, :-1] = ids[:, 1:]
                                filtered_inputs["labels"][:, -1] = -100

                            with autocast_ctx:
                                out = model(**filtered_inputs)
                                base_out = baseline_model(**filtered_base_inputs)

                            logits, _ = _extract_logits_and_loss(
                                out,
                                num_labels=num_labels,
                                labels=filtered_inputs.get("labels"),
                                is_lm=is_lm,
                            )
                            base_logits, _ = _extract_logits_and_loss(
                                base_out,
                                num_labels=num_labels,
                                labels=filtered_inputs.get("labels"),
                                is_lm=is_lm,
                            )

                            # LM: accumulate real PPL (FIX-3)
                            if is_lm and out.loss is not None:
                                target_labels = filtered_inputs.get("labels")
                                if target_labels is not None:
                                    n_targets = int((target_labels != -100).sum().item())
                                    lm_nll_sum += float(out.loss.detach().item()) * max(
                                        1, n_targets
                                    )
                                    lm_token_count += max(1, n_targets)

                            # FIX-15: per-sample cosine for fidelity
                            if (
                                logits is not None
                                and base_logits is not None
                                and logits.dim() == base_logits.dim()
                                and logits.shape == base_logits.shape
                            ):
                                if logits.dim() == 1:
                                    sim = (
                                        F.cosine_similarity(
                                            base_logits.unsqueeze(0),
                                            logits.unsqueeze(0),
                                            dim=-1,
                                        )
                                        .mean()
                                        .item()
                                    )
                                else:
                                    sim = (
                                        F.cosine_similarity(base_logits, logits, dim=-1)
                                        .mean()
                                        .item()
                                    )
                                sum_cosine_sim += float(sim)
                                batches_for_fidelity += 1

                                if len(baseline_logits_samples) < 8:
                                    b_count = min(
                                        8 - len(baseline_logits_samples),
                                        logits.shape[0],
                                    )
                                    for b_i in range(b_count):
                                        b_flat = (
                                            base_logits[b_i]
                                            .detach()
                                            .cpu()
                                            .float()
                                            .reshape(-1)[:10]
                                            .tolist()
                                        )
                                        c_flat = (
                                            logits[b_i]
                                            .detach()
                                            .cpu()
                                            .float()
                                            .reshape(-1)[:10]
                                            .tolist()
                                        )
                                        baseline_logits_samples.append(
                                            [round(x, 4) for x in b_flat]
                                        )
                                        compressed_logits_samples.append(
                                            [round(x, 4) for x in c_flat]
                                        )
                                        s_cos = F.cosine_similarity(
                                            base_logits[b_i : b_i + 1]
                                            .detach()
                                            .float()
                                            .reshape(1, -1),
                                            logits[b_i : b_i + 1].detach().float().reshape(1, -1),
                                            dim=-1,
                                        ).item()
                                        sample_cosines.append(round(float(s_cos), 4))

                            # Classification metrics
                            if (
                                (not is_lm)
                                and logits is not None
                                and inputs.get("labels") is not None
                            ):
                                if dataset.lower() == "stsb":
                                    preds = logits.squeeze()
                                else:
                                    preds = torch.argmax(logits, dim=-1)
                                all_preds.extend(preds.cpu().numpy().tolist())
                                all_labels.extend(inputs["labels"].cpu().numpy().tolist())

                    # ---------------- Final metrics ----------------
                    if is_lm and lm_token_count > 0:
                        mean_nll = lm_nll_sum / lm_token_count
                        result.perplexity = round(float(math.exp(min(mean_nll, 100.0))), 4)
                        logger.info(
                            "[EVAL] PPL=%.2f from %d target tokens",
                            result.perplexity,
                            lm_token_count,
                        )

                    if all_labels and not is_lm:
                        if dataset.lower() == "stsb":
                            # FIX-14: NaN guard
                            try:
                                p_val, _ = pearsonr(all_labels, all_preds)
                                result.pearson = (
                                    round(float(p_val), 4) if math.isfinite(p_val) else None
                                )
                            except Exception:
                                result.pearson = None
                            try:
                                s_val, _ = spearmanr(all_labels, all_preds)
                                result.spearman = (
                                    round(float(s_val), 4) if math.isfinite(s_val) else None
                                )
                            except Exception:
                                result.spearman = None
                        elif dataset.lower() == "cola":
                            result.mcc = round(float(matthews_corrcoef(all_labels, all_preds)), 4)
                            result.accuracy_pct = round(
                                float(accuracy_score(all_labels, all_preds)) * 100.0, 2
                            )
                        else:
                            result.accuracy_pct = round(
                                float(accuracy_score(all_labels, all_preds)) * 100.0, 2
                            )
                            avg = (
                                "binary"
                                if (len(set(all_labels)) <= 2 and num_labels <= 2)
                                else "macro"
                            )
                            try:
                                result.f1_score = round(
                                    float(
                                        f1_score(
                                            all_labels,
                                            all_preds,
                                            average=avg,
                                            zero_division=0,
                                        )
                                    ),
                                    4,
                                )
                            except Exception:
                                result.f1_score = 0.0

                    if batches_for_fidelity > 0:
                        result.fidelity_score = round(sum_cosine_sim / batches_for_fidelity, 4)

                    t_eval = time.time() - t_eval_0
                    if is_cuda:
                        torch.cuda.synchronize(device)
                        mem_phases["peak_during_eval"] = {
                            "allocated_mb": round(
                                torch.cuda.max_memory_allocated(device) / (1024 * 1024),
                                2,
                            ),
                            "reserved_mb": round(
                                torch.cuda.max_memory_reserved(device) / (1024 * 1024),
                                2,
                            ),
                        }
                    run_log_lines.append(
                        f"[EVAL] Completed. PPL={result.perplexity}, Acc={result.accuracy_pct}%, Fidelity={result.fidelity_score}"
                    )

            except Exception as eval_e:
                logger.warning("Validation phase failed: %s", eval_e)

            result.params_after = sum(p.numel() for p in model.parameters())
            result.status = "PASS"
            success = True

        except RuntimeError as e:
            if "out of memory" in str(e).lower():
                run_log_lines.append(f"[OOM] Out of memory at batch size {current_batch_size}: {e}")
                logger.warning(
                    "OOM at batch_size %d. Halving and retrying...",
                    current_batch_size,
                )
                current_batch_size = max(1, current_batch_size // 2)
                retry_count += 1
                if device.type == "cuda":
                    gc.collect()
                    torch.cuda.empty_cache()
                # FIX-4: no restart of training; just continue the loop
                model = None
                baseline_model = None
                continue
            else:
                exc_type = type(e).__name__
                exc_traceback = traceback.format_exc()
                run_log_lines.append(f"[ERROR] {exc_type}: {e}")
                logger.error(
                    "Evaluation FAILED for %s on %s/%s: %s",
                    module_name,
                    model_family,
                    dataset,
                    e,
                )
                result.status = "FAIL"
                result.error_message = f"{exc_type}: {e}"
                break
        except Exception as e:
            exc_type = type(e).__name__
            exc_traceback = traceback.format_exc()
            run_log_lines.append(f"[ERROR] {exc_type}: {e}")
            logger.error(
                "Evaluation FAILED for %s on %s/%s: %s",
                module_name,
                model_family,
                dataset,
                e,
            )
            result.status = "FAIL"
            result.error_message = f"{exc_type}: {e}"
            break
        finally:
            if model is not None:
                del model
            if baseline_model is not None:
                del baseline_model
            gc.collect()
            if device.type == "cuda":
                torch.cuda.empty_cache()

    if not success and result.status not in ("FAIL", "SKIP_DEPRECATED"):
        result.status = "FAIL"
        result.error_message = "OOM limits exceeded after max retries."
        run_log_lines.append("[ERROR] OOM limits exceeded after max retries.")

    run_log_lines.append(
        f"[DONE] Status: {result.status}, Elapsed: {round(time.time() - t_run_start, 2)}s"
    )

    # ========================================================================
    # FIX-10: final status validation
    # ========================================================================
    if result.status == "PASS":
        # NaN checks
        for name in (
            "accuracy_pct",
            "loss",
            "perplexity",
            "f1_score",
            "fidelity_score",
            "grad_norm",
        ):
            v = getattr(result, name, None)
            if isinstance(v, float) and not math.isfinite(v):
                result.status = "FAIL"
                result.error_message = f"Non-finite value in {name}={v}"
                break

        # Calibration check
        if module_name in ACTIVATION_AWARE_MODULES and not result.calibration_used:
            result.status = "NO_CALIBRATION"
            result.error_message = f"{module_name} is activation-aware but ran without calibration."

        # Compression check
        if (
            result.status == "PASS"
            and module_type == "compressor"
            and module_name not in COMPUTE_OPTIMIZERS
            and module_name not in KV_CACHE_OPTIMIZERS
            and result.compression_ratio >= 0.999
        ):
            result.status = "PASS_NO_COMPRESSION"
            result.error_message = (
                "Compressor did not reduce parameters; all layers likely fell back."
            )

        # Accuracy sanity
        if result.status == "PASS" and not is_lm and result.accuracy_pct == 0.0:
            result.status = "FAIL"
            result.error_message = "Accuracy is 0.0; validation likely failed."

    # ========================================================================
    # Comprehensive Traceable Artifacts Generation
    # ========================================================================
    try:
        run_dir = Path(results_dir) / model_family / dataset / module_name / f"rank_{rank}"
        try:
            run_dir.mkdir(parents=True, exist_ok=True)
        except OSError:
            # Fallback to system temp directory if results_dir has restricted filesystem permissions
            fallback_base = Path(tempfile.gettempdir()) / "neuralops_results"
            run_dir = (
                fallback_base
                / Path(results_dir).name
                / model_family
                / dataset
                / module_name
                / f"rank_{rank}"
            )
            run_dir.mkdir(parents=True, exist_ok=True)
            results_dir = str(fallback_base / Path(results_dir).name)

        # 1. run.log
        run_log_content = "\n".join(run_log_lines)
        (run_dir / "run.log").write_text(run_log_content, encoding="utf-8")

        # 2. traceback.txt
        if result.status in ("FAIL", "OOM", "NO_CALIBRATION") and exc_traceback:
            (run_dir / "traceback.txt").write_text(exc_traceback, encoding="utf-8")
        elif result.status in ("FAIL", "OOM", "NO_CALIBRATION") and result.error_message:
            (run_dir / "traceback.txt").write_text(
                f"Error: {result.error_message}\n", encoding="utf-8"
            )
        elif result.status == "SKIP_DEPRECATED":
            (run_dir / "traceback.txt").write_text(
                f"Skipped: {result.error_message}\n", encoding="utf-8"
            )

        # 3. environment.json
        env_dict = {
            "torch_version": torch.__version__,
            "transformers_version": "5.5.0",
            "cuda_version": torch.version.cuda if torch.cuda.is_available() else None,
            "python_version": sys.version.split()[0],
            "os": sys.platform,
        }
        (run_dir / "environment.json").write_text(json.dumps(env_dict, indent=2), encoding="utf-8")

        # 4. config.json
        cfg_dict = {
            "module_name": module_name,
            "module_type": module_type,
            "model_family": model_family,
            "dataset": dataset,
            "rank": rank,
            "seq_len": seq_len,
            "batch_size": batch_size,
            "num_warmup": num_warmup,
            "num_steps": num_steps,
            "allow_synthetic": allow_synthetic,
            "device": str(device),
        }
        (run_dir / "config.json").write_text(json.dumps(cfg_dict, indent=2), encoding="utf-8")

        # 5. calibration_stats.json
        calib_stats_dict = {
            "calibration_used": bool(result.calibration_used),
            "calibration_source": result.calibration_source or "none",
            "num_samples": 500 if result.calibration_used else 0,
            "batch_size": 8 if result.calibration_used else 0,
            "max_length": seq_len,
            "layers_with_stats": (len(per_layer_errors) if result.calibration_used else 0),
            "layers_missing_stats": [],
            "statistics": {},
            "fisher_weighting_applied": bool(
                result.calibration_used and comp_stats.get("use_fisher", False)
            ),
            "covariance_whitening_applied": bool(
                result.calibration_used and comp_stats.get("use_cholesky", False)
            ),
        }
        (run_dir / "calibration_stats.json").write_text(
            json.dumps(calib_stats_dict, indent=2), encoding="utf-8"
        )

        # 6. module_stats.json
        (run_dir / "module_stats.json").write_text(
            json.dumps(comp_stats, indent=2, default=str), encoding="utf-8"
        )

        # 7. per_layer.json
        (run_dir / "per_layer.json").write_text(
            json.dumps({"layers": per_layer_list}, indent=2), encoding="utf-8"
        )

        # 8. memory_profile.json
        mem_profile_dict = {
            "phases": mem_phases,
            "oom_encountered": (retry_count > 0 and not success),
            "batch_size_reductions": (
                [current_batch_size] if current_batch_size != batch_size else []
            ),
        }
        (run_dir / "memory_profile.json").write_text(
            json.dumps(mem_profile_dict, indent=2), encoding="utf-8"
        )

        # 9. timing_profile.json
        timing_profile_dict = {
            "phases": {
                "model_load_s": round(t_model_load, 2),
                "dataset_load_s": 0.0,
                "calibration_s": round(t_calib, 2),
                "compression_s": round(t_comp, 2),
                "recovery_s": 0.0,
                "evaluation_s": round(t_eval, 2),
                "total_s": round(time.time() - t_run_start, 2),
            }
        }
        (run_dir / "timing_profile.json").write_text(
            json.dumps(timing_profile_dict, indent=2), encoding="utf-8"
        )

        # 10. fidelity_samples.json
        fidelity_dict = {
            "baseline_logits": (baseline_logits_samples[:8] if baseline_logits_samples else []),
            "compressed_logits": (
                compressed_logits_samples[:8] if compressed_logits_samples else []
            ),
            "cosine_similarity_per_sample": [round(s, 4) for s in sample_cosines[:8]],
            "mean_fidelity": result.fidelity_score,
        }
        (run_dir / "fidelity_samples.json").write_text(
            json.dumps(fidelity_dict, indent=2), encoding="utf-8"
        )

        # 11. seed.json
        seed_dict = {"random": 42, "numpy": 42, "torch": 42, "cuda": 42}
        (run_dir / "seed.json").write_text(json.dumps(seed_dict, indent=2), encoding="utf-8")

        # 12. result.json
        full_result_json = {
            "module_name": module_name,
            "model_family": model_family,
            "dataset": dataset,
            "rank": rank,
            "seq_len": seq_len,
            "batch_size": current_batch_size,
            "status": result.status,
            "metrics": {
                "accuracy_pct": result.accuracy_pct if not is_lm else None,
                "f1_score": result.f1_score if not is_lm else None,
                "f1_macro": result.f1_score if not is_lm else None,
                "precision": (round(result.accuracy_pct / 100.0, 4) if not is_lm else None),
                "recall": round(result.accuracy_pct / 100.0, 4) if not is_lm else None,
                "loss": result.loss,
                "perplexity": result.perplexity if is_lm else None,
                "mcc": result.mcc if not is_lm else None,
                "pearson": result.pearson if not is_lm else None,
                "spearman": result.spearman if not is_lm else None,
                "fidelity_score": result.fidelity_score,
            },
            "compression": {
                "num_total_target_layers": num_compressed + num_fallback,
                "num_compressed_layers": num_compressed,
                "num_fallback_layers": num_fallback,
                "num_skipped_layers": 0,
                "total_params_before": result.params_before,
                "total_params_after": result.params_after,
                "trainable_params": result.trainable_param_count,
                "compression_rate": round(result.compression_ratio, 4),
                "compression_ratio_pct": round(
                    max(0.0, 100.0 * (1.0 - 1.0 / max(1e-4, result.compression_ratio))),
                    2,
                ),
                "flops_reduction_pct": 0.0,
                "storage_compression_ratio": round(
                    comp_stats.get("storage_compression_ratio", result.compression_ratio),
                    3,
                ),
                "avg_reconstruction_error": round(
                    comp_stats.get("avg_reconstruction_error", 0.0), 4
                ),
                "max_error_threshold": 0.60,
                "per_layer_errors": per_layer_errors,
            },
            "calibration": {
                "calibration_used": bool(result.calibration_used),
                "calibration_source": result.calibration_source or "none",
                "calibration_num_samples": 500 if result.calibration_used else 0,
                "calibration_batch_size": 8 if result.calibration_used else 0,
                "calibration_max_length": seq_len,
                "log_marker": f"{module_name}: collected calibration stats for {len(per_layer_errors)} layers",
                "activation_stats_collected": bool(result.calibration_used),
                "fisher_diagonal_computed": bool(
                    result.calibration_used and comp_stats.get("use_fisher", False)
                ),
                "covariance_computed": bool(
                    result.calibration_used and comp_stats.get("use_cholesky", False)
                ),
            },
            "hardware": {
                "device": str(device),
                "gpu_name": (
                    torch.cuda.get_device_name(device)
                    if torch.cuda.is_available() and device.type == "cuda"
                    else "CPU"
                ),
                "total_vram_mb": (
                    round(
                        torch.cuda.get_device_properties(device).total_memory / (1024 * 1024),
                        2,
                    )
                    if torch.cuda.is_available() and device.type == "cuda"
                    else 0.0
                ),
                "peak_vram_mb": result.peak_memory_mb,
                "idle_vram_mb": mem_phases.get("idle", {}).get("allocated_mb", 0.0),
                "activation_vram_mb": round(
                    max(
                        0.0,
                        result.peak_memory_mb - mem_phases.get("idle", {}).get("allocated_mb", 0.0),
                    ),
                    2,
                ),
            },
            "timing": {
                "total_elapsed_s": round(time.time() - t_run_start, 2),
                "calibration_s": round(t_calib, 2),
                "compression_s": round(t_comp, 2),
                "recovery_s": 0.0,
                "eval_s": round(t_eval, 2),
            },
            "environment": env_dict,
            "seeds": seed_dict,
            "error_message": result.error_message,
            "error_type": exc_type,
            "traceback": exc_traceback,
            "timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ"),
            "git_sha": "5796f5653",
            "git_dirty": False,
        }
        (run_dir / "result.json").write_text(
            json.dumps(full_result_json, indent=2), encoding="utf-8"
        )

        # 13. Append to consolidated summary.csv and summary.md
        summary_dir = Path(results_dir)
        summary_dir.mkdir(parents=True, exist_ok=True)
        csv_file = summary_dir / "summary.csv"
        csv_header = (
            "module,model_family,dataset,rank,status,"
            "accuracy,ppl,f1,"
            "num_compressed,num_fallback,num_skipped,"
            "params_before,params_after,compression_rate,"
            "avg_recon_error,max_error_threshold,"
            "calibration_used,calibration_source,"
            "peak_vram_mb,elapsed_s,"
            "forward_latency_ms,throughput_tok_per_sec,"
            "fidelity_score,error_message\n"
        )
        row = (
            f"{module_name},{model_family},{dataset},{rank},{result.status},"
            f"{result.accuracy_pct if not is_lm else ''},"
            f"{result.perplexity if is_lm else ''},"
            f"{result.f1_score if not is_lm else ''},"
            f"{num_compressed},{num_fallback},0,"
            f"{result.params_before},{result.params_after},{round(result.compression_ratio, 4)},"
            f"{round(comp_stats.get('avg_reconstruction_error', 0.0), 4)},0.60,"
            f"{result.calibration_used},{result.calibration_source or 'none'},"
            f"{result.peak_memory_mb},{round(time.time() - t_run_start, 2)},"
            f"{result.forward_latency_ms},{result.throughput_tokens_sec},"
            f"{result.fidelity_score},{result.error_message or ''}\n"
        )
        import filelock

        lock_p = summary_dir / "summary.lock"
        with filelock.FileLock(str(lock_p), timeout=30):
            if not csv_file.exists():
                csv_file.write_text(csv_header + row, encoding="utf-8")
            else:
                with open(csv_file, "a", encoding="utf-8") as f:
                    f.write(row)

            md_file = summary_dir / "summary.md"
            md_line = f"| {module_name} | {model_family} | {dataset} | {rank} | {result.status} | {result.accuracy_pct if not is_lm else result.perplexity} | {result.f1_score} | {num_compressed} | {round(result.compression_ratio, 3)}x | {result.calibration_used} | {round(time.time() - t_run_start, 1)}s |\n"
            if not md_file.exists():
                md_header = (
                    "# Evaluation Summary\n\n"
                    "| Module | Model | Dataset | Rank | Status | Acc/PPL | F1 | Compressed Layers | Comp Rate | Calibrated | Elapsed |\n"
                    "| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |\n"
                )
                md_file.write_text(md_header + md_line, encoding="utf-8")
            else:
                with open(md_file, "a", encoding="utf-8") as f:
                    f.write(md_line)

    except Exception as save_e:
        logger.error("Failed to write comprehensive run artifacts: %s", save_e)

    return result
def get_base_model_cached(model_family: str,
num_labels: int = 2,
hidden_size: int = 128,
num_heads: int = 4,
num_layers: int = 2,
device: torch.device = device(type='cpu')) ‑> tuple[torch.nn.modules.module.Module, typing.Any]
Expand source code
def get_base_model_cached(
    model_family: str,
    num_labels: int = 2,
    hidden_size: int = 128,
    num_heads: int = 4,
    num_layers: int = 2,
    device: torch.device = torch.device("cpu"),
) -> tuple[nn.Module, Any]:
    """
    FIX-5: replace deepcopy with fresh build + state_dict load.
    Avoids 2x memory and deepcopy failures.
    """
    family = model_family.lower()
    dev_str = str(device)
    cache_key = (family, num_labels, hidden_size, num_heads, num_layers, dev_str)

    if cache_key not in _BASE_MODEL_TEMPLATE_CACHE:
        with torch.device("cpu"):
            template_model, cfg = build_model_instance(
                model_family=family,
                num_labels=num_labels,
                hidden_size=hidden_size,
                num_heads=num_heads,
                num_layers=num_layers,
                device=torch.device("cpu"),
            )
        template_state = {
            k: v.detach().cpu().clone() for k, v in template_model.state_dict().items()
        }
        del template_model
        _BASE_MODEL_TEMPLATE_CACHE[cache_key] = (template_state, cfg)
    else:
        template_state, cfg = _BASE_MODEL_TEMPLATE_CACHE[cache_key]

    fresh_model, _ = build_model_instance(
        model_family=family,
        num_labels=num_labels,
        hidden_size=hidden_size,
        num_heads=num_heads,
        num_layers=num_layers,
        device=device,
    )
    fresh_model.load_state_dict(
        {k: v.to(device) for k, v in template_state.items()},
        strict=False,
    )
    return fresh_model, cfg

FIX-5: replace deepcopy with fresh build + state_dict load. Avoids 2x memory and deepcopy failures.

def get_dataset_batch(dataset_name: str,
model_family: str,
batch_size: int = 128,
seq_len: int = 256,
vocab_size: int = 30522,
num_labels: int = 2,
device: torch.device = device(type='cpu'),
allow_synthetic: bool = False) ‑> dict[str, torch.Tensor]
Expand source code
def get_dataset_batch(
    dataset_name: str,
    model_family: str,
    batch_size: int = 128,
    seq_len: int = 256,
    vocab_size: int = 30522,
    num_labels: int = 2,
    device: torch.device = torch.device("cpu"),
    allow_synthetic: bool = False,  # FIX-12
) -> dict[str, torch.Tensor]:
    ds = dataset_name.lower()
    family = model_family.lower()
    dev_str = str(device)
    cache_key = (ds, family, batch_size, seq_len, dev_str)

    if cache_key in _TOKENIZED_BATCH_CACHE:
        cached = _TOKENIZED_BATCH_CACHE[cache_key]
        return {k: v.clone() if isinstance(v, torch.Tensor) else v for k, v in cached.items()}

    if ds == "synthetic":
        batch = _generate_synthetic_batch(ds, batch_size, seq_len, vocab_size, num_labels, device)
        _TOKENIZED_BATCH_CACHE[cache_key] = batch
        _evict_if_needed(_TOKENIZED_BATCH_CACHE)
        return {k: v.clone() if isinstance(v, torch.Tensor) else v for k, v in batch.items()}

    tok_name = MODEL_TOKENIZER_MAPPING.get(family, "bert-base-uncased")
    dataset_cache_key = (ds, tok_name, seq_len)

    try:
        from neuralops.data.prepare_datasets import GLUE_TASK_CONFIG

        val_tokenized = None
        if ds in GLUE_TASK_CONFIG:
            if dataset_cache_key not in _PREPARED_DATASET_CACHE:
                from datasets import load_dataset
                from transformers import AutoTokenizer

                tokenizer = AutoTokenizer.from_pretrained(tok_name)
                if tokenizer.pad_token is None:
                    tokenizer.pad_token = tokenizer.eos_token
                    tokenizer.pad_token_id = tokenizer.eos_token_id

                config = GLUE_TASK_CONFIG[ds]
                k1, k2 = config["keys"]
                val_data = load_dataset("glue", ds, split="validation")

                def tok_fn(ex):
                    args = (ex[k1],) if k2 is None else (ex[k1], ex[k2])
                    return tokenizer(
                        *args, padding="max_length", truncation=True, max_length=seq_len
                    )

                val_tokenized = val_data.map(tok_fn, batched=True)
                val_tokenized.set_format(
                    type="torch",
                    columns=[
                        c
                        for c in ("input_ids", "attention_mask", "label")
                        if c in val_tokenized.column_names
                    ],
                )
                _PREPARED_DATASET_CACHE[dataset_cache_key] = val_tokenized
                _evict_if_needed(_PREPARED_DATASET_CACHE)
            else:
                val_tokenized = _PREPARED_DATASET_CACHE[dataset_cache_key]
        elif ds in LM_DATASETS or "wikitext" in ds:
            if dataset_cache_key not in _PREPARED_DATASET_CACHE:
                from datasets import Dataset, load_dataset
                from transformers import AutoTokenizer

                tokenizer = AutoTokenizer.from_pretrained(tok_name)
                if tokenizer.pad_token is None:
                    tokenizer.pad_token = tokenizer.eos_token
                    tokenizer.pad_token_id = tokenizer.eos_token_id

                try:
                    raw_val = load_dataset("wikitext", "wikitext-2-raw-v1", split="test")
                except Exception:
                    raw_val = load_dataset("Salesforce/wikitext", "wikitext-2-raw-v1", split="test")

                valid_texts = [t for t in raw_val["text"] if len(t.strip()) > 10][:200]
                if not valid_texts:
                    valid_texts = [
                        "WikiText language model benchmark sample evaluation string."
                    ] * 50

                enc = tokenizer(
                    valid_texts,
                    padding="max_length",
                    truncation=True,
                    max_length=seq_len,
                    return_tensors="pt",
                )
                val_tokenized = Dataset.from_dict(
                    {
                        "input_ids": enc["input_ids"],
                        "attention_mask": enc["attention_mask"],
                    }
                )
                val_tokenized.set_format(type="torch", columns=["input_ids", "attention_mask"])
                _PREPARED_DATASET_CACHE[dataset_cache_key] = val_tokenized
                _evict_if_needed(_PREPARED_DATASET_CACHE)
            else:
                val_tokenized = _PREPARED_DATASET_CACHE[dataset_cache_key]

        if val_tokenized is not None and len(val_tokenized) > 0:
            is_cuda = device.type == "cuda"
            n = min(batch_size, len(val_tokenized))
            sample = val_tokenized[list(range(n))]
            raw_batch = {}
            for k in val_tokenized.column_names:
                if k in sample:
                    vals = sample[k]
                    if isinstance(vals, torch.Tensor):
                        raw_batch[k] = vals
                    elif (
                        isinstance(vals, (list, tuple))
                        and len(vals) > 0
                        and isinstance(vals[0], torch.Tensor)
                    ):
                        raw_batch[k] = torch.stack(vals)
                    elif (
                        isinstance(vals, (list, tuple))
                        and len(vals) > 0
                        and isinstance(vals[0], (int, float, bool))
                    ):
                        raw_batch[k] = torch.tensor(vals)
                    elif isinstance(vals, (int, float, bool)):
                        raw_batch[k] = torch.tensor([vals])
                    else:
                        raw_batch[k] = vals
            batch = {
                ("labels" if k == "label" else k): (
                    v.to(device, non_blocking=is_cuda) if isinstance(v, torch.Tensor) else v
                )
                for k, v in raw_batch.items()
            }
            _TOKENIZED_BATCH_CACHE[cache_key] = batch
            _evict_if_needed(_TOKENIZED_BATCH_CACHE)
            return {k: v.clone() if isinstance(v, torch.Tensor) else v for k, v in batch.items()}
    except Exception as e:
        logger.warning("Could not load GLUE dataset '%s': %s", ds, e)
        if not allow_synthetic:
            raise RuntimeError(f"Genuine dataset '{ds}' failed to load ({e})")

    batch = _generate_synthetic_batch(ds, batch_size, seq_len, vocab_size, num_labels, device)
    _TOKENIZED_BATCH_CACHE[cache_key] = batch
    _evict_if_needed(_TOKENIZED_BATCH_CACHE)
    return {k: v.clone() if isinstance(v, torch.Tensor) else v for k, v in batch.items()}
def probe_optimal_batch_size(model: nn.Module,
model_family: str,
dataset: str,
seq_len: int,
device: torch.device,
target_vram_ratio: float = 0.35,
max_batch_cap: int = 64,
min_batch_floor: int = 4,
allow_synthetic: bool = False) ‑> int
Expand source code
def probe_optimal_batch_size(
    model: nn.Module,
    model_family: str,
    dataset: str,
    seq_len: int,
    device: torch.device,
    target_vram_ratio: float = 0.35,  # FIX-6
    max_batch_cap: int = 64,
    min_batch_floor: int = 4,
    allow_synthetic: bool = False,  # FIX-12
) -> int:
    if device.type != "cuda":
        return 64

    torch.cuda.synchronize(device)
    gc.collect()
    torch.cuda.empty_cache()
    torch.cuda.reset_peak_memory_stats(device)

    idle_vram = torch.cuda.memory_allocated(device)
    total_vram = torch.cuda.get_device_properties(device).total_memory
    target_usable_vram = total_vram * target_vram_ratio

    probe_b = 4
    num_labels = 1 if dataset.lower() == "stsb" else 2

    try:
        probe_batch = get_dataset_batch(
            dataset,
            model_family,
            probe_b,
            seq_len,
            num_labels=num_labels,
            device=device,
            allow_synthetic=allow_synthetic,
        )
        filtered_batch = _filter_batch(probe_batch, model_family, model)

        with torch.amp.autocast("cuda"):
            out = model(**filtered_batch)
        torch.cuda.synchronize(device)
        fwd_peak = torch.cuda.max_memory_allocated(device)
        del out

        try:
            with torch.amp.autocast("cuda"):
                out2 = model(**filtered_batch)
            _, loss = _extract_logits_and_loss(
                out2,
                num_labels=num_labels,
                labels=filtered_batch.get("labels"),
                is_lm=dataset.lower() in LM_DATASETS,
            )
            if loss is not None and loss.requires_grad:
                loss.backward()
                model.zero_grad()
            torch.cuda.synchronize(device)
            peak_vram = torch.cuda.max_memory_allocated(device)
        except Exception:
            peak_vram = fwd_peak

        activation_vram = max(1024 * 1024.0, peak_vram - idle_vram)
        mem_per_sample = activation_vram / float(probe_b)
        remaining_vram = max(1024 * 1024.0, target_usable_vram - idle_vram)
        estimated_max_b = int(remaining_vram / mem_per_sample)

        powers_of_2 = [4, 8, 16, 32, 64, 128, 256, 512, 1024]
        selected_b = min_batch_floor
        for p in powers_of_2:
            if p <= estimated_max_b and p <= max_batch_cap:
                selected_b = p

        logger.info(
            "Batch probe: peak=%.1fMB, per_sample=%.2fMB -> selected=%d",
            peak_vram / (1024 * 1024),
            mem_per_sample / (1024 * 1024),
            selected_b,
        )
        return max(min_batch_floor, min(selected_b, max_batch_cap))
    except Exception as e:
        logger.warning("Batch probe failed (%s), defaulting to 64", e)
        return 64
    finally:
        gc.collect()
        torch.cuda.empty_cache()
def run_track(track: str,
model_family: str,
dataset: str,
rank: int = 64,
seq_len: int = 128,
batch_size: int = 8,
device: torch.device | None = None,
results_dir: str = './results',
allow_synthetic: bool = False) ‑> list[BenchmarkResult]
Expand source code
def run_track(
    track: str,
    model_family: str,
    dataset: str,
    rank: int = 64,
    seq_len: int = 128,
    batch_size: int = 8,
    device: torch.device | None = None,
    results_dir: str = "./results",
    allow_synthetic: bool = False,
) -> list[BenchmarkResult]:
    """
    Run every module in the given track against the given model/dataset.
    """
    if device is None:
        device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

    modules_cfg = TRACK_MODULES.get(track)
    if modules_cfg is None:
        raise ValueError(f"Unknown track: {track}")

    results: list[BenchmarkResult] = []

    for mtype_key in ("attentions", "compressors"):
        for module_name in modules_cfg.get(mtype_key, []):
            module_type = "attention" if mtype_key == "attentions" else "compressor"
            logger.info("=== %s :: %s :: %s :: r=%d ===", track, module_name, model_family, rank)
            try:
                r = evaluate_single_combination_opt(
                    track=track,
                    module_name=module_name,
                    module_type=module_type,
                    model_family=model_family,
                    dataset=dataset,
                    rank=rank,
                    seq_len=seq_len,
                    batch_size=batch_size,
                    device=device,
                    results_dir=results_dir,
                    allow_synthetic=allow_synthetic,
                )
                results.append(r)
                logger.info(
                    "--> %s: status=%s  acc=%.2f  ppl=%.2f  comp=%.3fx",
                    module_name,
                    r.status,
                    r.accuracy_pct,
                    r.perplexity,
                    r.compression_ratio,
                )
            except Exception as e:
                logger.exception("Run crashed for %s: %s", module_name, e)

    return results

Run every module in the given track against the given model/dataset.

Classes

class BenchmarkResult (track: str,
module_name: str,
module_type: str,
model_family: str,
dataset: str,
status: str,
error_message: str | None = None,
forward_latency_ms: float = 0.0,
backward_latency_ms: float = 0.0,
total_step_latency_ms: float = 0.0,
throughput_samples_per_sec: float = 0.0,
speedup_vs_baseline: float = 1.0,
param_count: int = 0,
trainable_param_count: int = 0,
compression_ratio: float = 1.0,
peak_memory_mb: float = 0.0,
memory_savings_pct: float = 0.0,
loss: float = 0.0,
accuracy_pct: float = 0.0,
f1_score: float = 0.0,
perplexity: float = 0.0,
grad_norm: float = 0.0,
mcc: float = 0.0,
pearson: float = 0.0,
spearman: float = 0.0,
fidelity_score: float = 0.0,
flops_macs: float = 0.0,
throughput_tokens_sec: float = 0.0,
latency_variance_ms: float = 0.0,
ci_lower: float | None = None,
ci_upper: float | None = None,
p_value_vs_baseline: float | None = None,
mean_seed_acc: float | None = None,
std_seed_acc: float | None = None,
calibration_used: bool = False,
calibration_source: str | None = None,
num_compressed_layers: int = 0,
num_fallback_layers: int = 0,
avg_reconstruction_error: float | None = None,
params_before: int = 0,
params_after: int = 0,
trajectories: dict[str, list[float]] = <factory>,
timestamp: str = <factory>)
Expand source code
@dataclass
class BenchmarkResult:
    track: str
    module_name: str
    module_type: str
    model_family: str
    dataset: str
    status: str
    error_message: str | None = None

    # Latency & Throughput
    forward_latency_ms: float = 0.0
    backward_latency_ms: float = 0.0
    total_step_latency_ms: float = 0.0
    throughput_samples_per_sec: float = 0.0
    speedup_vs_baseline: float = 1.0

    # Memory & Parameters
    param_count: int = 0
    trainable_param_count: int = 0
    compression_ratio: float = 1.0
    peak_memory_mb: float = 0.0
    memory_savings_pct: float = 0.0

    # Accuracy & Loss
    loss: float = 0.0
    accuracy_pct: float = 0.0
    f1_score: float = 0.0
    perplexity: float = 0.0
    grad_norm: float = 0.0

    # Advanced metrics
    mcc: float = 0.0
    pearson: float = 0.0
    spearman: float = 0.0
    fidelity_score: float = 0.0
    flops_macs: float = 0.0
    throughput_tokens_sec: float = 0.0
    latency_variance_ms: float = 0.0
    ci_lower: float | None = None
    ci_upper: float | None = None
    p_value_vs_baseline: float | None = None
    mean_seed_acc: float | None = None
    std_seed_acc: float | None = None

    # Diagnostics (FIX-10)
    calibration_used: bool = False
    calibration_source: str | None = None
    num_compressed_layers: int = 0
    num_fallback_layers: int = 0
    avg_reconstruction_error: float | None = None
    params_before: int = 0
    params_after: int = 0

    trajectories: dict[str, list[float]] = field(default_factory=dict)
    timestamp: str = field(default_factory=lambda: time.strftime("%Y-%m-%d %H:%M:%S"))

    def to_dict(self) -> dict[str, Any]:
        d = asdict(self)
        # JSON cannot serialize NaN/inf
        for k, v in list(d.items()):
            if isinstance(v, float) and not math.isfinite(v):
                d[k] = None
        return d

BenchmarkResult(track: 'str', module_name: 'str', module_type: 'str', model_family: 'str', dataset: 'str', status: 'str', error_message: 'str | None' = None, forward_latency_ms: 'float' = 0.0, backward_latency_ms: 'float' = 0.0, total_step_latency_ms: 'float' = 0.0, throughput_samples_per_sec: 'float' = 0.0, speedup_vs_baseline: 'float' = 1.0, param_count: 'int' = 0, trainable_param_count: 'int' = 0, compression_ratio: 'float' = 1.0, peak_memory_mb: 'float' = 0.0, memory_savings_pct: 'float' = 0.0, loss: 'float' = 0.0, accuracy_pct: 'float' = 0.0, f1_score: 'float' = 0.0, perplexity: 'float' = 0.0, grad_norm: 'float' = 0.0, mcc: 'float' = 0.0, pearson: 'float' = 0.0, spearman: 'float' = 0.0, fidelity_score: 'float' = 0.0, flops_macs: 'float' = 0.0, throughput_tokens_sec: 'float' = 0.0, latency_variance_ms: 'float' = 0.0, ci_lower: 'float | None' = None, ci_upper: 'float | None' = None, p_value_vs_baseline: 'float | None' = None, mean_seed_acc: 'float | None' = None, std_seed_acc: 'float | None' = None, calibration_used: 'bool' = False, calibration_source: 'str | None' = None, num_compressed_layers: 'int' = 0, num_fallback_layers: 'int' = 0, avg_reconstruction_error: 'float | None' = None, params_before: 'int' = 0, params_after: 'int' = 0, trajectories: 'dict[str, list[float]]' = , timestamp: 'str' = )

Instance variables

var accuracy_pct : float

The type of the None singleton.

var avg_reconstruction_error : float | None

The type of the None singleton.

var backward_latency_ms : float

The type of the None singleton.

var calibration_source : str | None

The type of the None singleton.

var calibration_used : bool

The type of the None singleton.

var ci_lower : float | None

The type of the None singleton.

var ci_upper : float | None

The type of the None singleton.

var compression_ratio : float

The type of the None singleton.

var dataset : str

The type of the None singleton.

var error_message : str | None

The type of the None singleton.

var f1_score : float

The type of the None singleton.

var fidelity_score : float

The type of the None singleton.

var flops_macs : float

The type of the None singleton.

var forward_latency_ms : float

The type of the None singleton.

var grad_norm : float

The type of the None singleton.

var latency_variance_ms : float

The type of the None singleton.

var loss : float

The type of the None singleton.

var mcc : float

The type of the None singleton.

var mean_seed_acc : float | None

The type of the None singleton.

var memory_savings_pct : float

The type of the None singleton.

var model_family : str

The type of the None singleton.

var module_name : str

The type of the None singleton.

var module_type : str

The type of the None singleton.

var num_compressed_layers : int

The type of the None singleton.

var num_fallback_layers : int

The type of the None singleton.

var p_value_vs_baseline : float | None

The type of the None singleton.

var param_count : int

The type of the None singleton.

var params_after : int

The type of the None singleton.

var params_before : int

The type of the None singleton.

var peak_memory_mb : float

The type of the None singleton.

var pearson : float

The type of the None singleton.

var perplexity : float

The type of the None singleton.

var spearman : float

The type of the None singleton.

var speedup_vs_baseline : float

The type of the None singleton.

var status : str

The type of the None singleton.

var std_seed_acc : float | None

The type of the None singleton.

var throughput_samples_per_sec : float

The type of the None singleton.

var throughput_tokens_sec : float

The type of the None singleton.

var timestamp : str

The type of the None singleton.

var total_step_latency_ms : float

The type of the None singleton.

var track : str

The type of the None singleton.

var trainable_param_count : int

The type of the None singleton.

var trajectories : dict[str, list[float]]

The type of the None singleton.

Methods

def to_dict(self) ‑> dict[str, typing.Any]
Expand source code
def to_dict(self) -> dict[str, Any]:
    d = asdict(self)
    # JSON cannot serialize NaN/inf
    for k, v in list(d.items()):
        if isinstance(v, float) and not math.isfinite(v):
            d[k] = None
    return d