From 9df5ac8836e84bfeef2169ba7c7a877c144ed9bc Mon Sep 17 00:00:00 2001 From: tzhouam Date: Thu, 24 Sep 2026 01:12:27 +0800 Subject: [PATCH] Run InternVLA synthetic policy with Radeon Cosmos handoff --- .../experiments/export_internvla_cosmos.py | 93 ++++ .../probe_internvla_cosmos_directml.py | 17 +- .../probe_internvla_hybrid_actions.py | 225 ++++++++++ .../results/e2e_expansion_20260923/README.md | 1 + .../internvla_cosmos_radeon890m/README.md | 94 +++- .../bf16_batch6_probe.log | 1 + .../export_batch6.json | 28 ++ .../export_batch6.log | 28 ++ .../hybrid_profile20.json | 416 ++++++++++++++++++ .../hybrid_profile20.log | 178 ++++++++ .../hybrid_selected_adapter.json | 186 ++++++++ .../hybrid_selected_adapter.log | 181 ++++++++ .../hybrid_smoke.json | 183 ++++++++ .../hybrid_smoke.log | 178 ++++++++ .../profile_batch6_20.json | 114 +++++ .../profile_batch6_20_driver.log | 70 +++ .../evidence/summary/README.md | 6 +- docs/design/omni_edge_e2e_roadmap.md | 12 +- tests/edge/local/external/test_stage.py | 14 + vllm_omni/edge/local/external/client.py | 10 +- vllm_omni/edge/local/external/worker_dml.py | 1 + 21 files changed, 2020 insertions(+), 16 deletions(-) create mode 100644 benchmarks/edge_harness/experiments/export_internvla_cosmos.py create mode 100644 benchmarks/edge_harness/experiments/probe_internvla_hybrid_actions.py create mode 100644 benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/bf16_batch6_probe.log create mode 100644 benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/export_batch6.json create mode 100644 benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/export_batch6.log create mode 100644 benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_profile20.json create mode 100644 benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_profile20.log create mode 100644 benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_selected_adapter.json create mode 100644 benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_selected_adapter.log create mode 100644 benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_smoke.json create mode 100644 benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_smoke.log create mode 100644 benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/profile_batch6_20.json create mode 100644 benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/profile_batch6_20_driver.log diff --git a/benchmarks/edge_harness/experiments/export_internvla_cosmos.py b/benchmarks/edge_harness/experiments/export_internvla_cosmos.py new file mode 100644 index 000000000..0fc1a3103 --- /dev/null +++ b/benchmarks/edge_harness/experiments/export_internvla_cosmos.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 +"""Export the unchanged InternVLA Cosmos encoder as a fixed-shape graph.""" + +from __future__ import annotations + +import argparse +import hashlib +import importlib.util +import json +import sys +import time +import types +from pathlib import Path + + +def sha256(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as source: + for block in iter(lambda: source.read(8 << 20), b""): + digest.update(block) + return digest.hexdigest() + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--encoder", type=Path, required=True) + parser.add_argument("--output", type=Path, required=True) + parser.add_argument("--report", type=Path, required=True) + parser.add_argument("--batch-size", type=int, default=6) + args = parser.parse_args() + + import torch + + source_dir = Path(__file__).resolve().parents[3] / "vllm_omni" / "diffusion" / "models" / "internvla_a1" + package = types.ModuleType("internvla_cosmos_export") + package.__path__ = [str(source_dir)] + sys.modules[package.__name__] = package + spec = importlib.util.spec_from_file_location(f"{package.__name__}.model_cosmos", source_dir / "model_cosmos.py") + if spec is None or spec.loader is None: + raise RuntimeError("cannot load pinned Cosmos source") + module = importlib.util.module_from_spec(spec) + sys.modules[spec.name] = module + spec.loader.exec_module(module) + encoder_path = args.encoder.resolve(strict=True) + encoder_model = module.load_cosmos_component(encoder_path, component="encoder", device="cpu") + + class LatentOnly(torch.nn.Module): + def __init__(self, inner: torch.nn.Module) -> None: + super().__init__() + self.inner = inner + + def forward(self, pixels: torch.Tensor) -> torch.Tensor: + result = self.inner(pixels) + return result if isinstance(result, torch.Tensor) else result[0] + + model = LatentOnly(encoder_model).eval() + image = torch.linspace(-1, 1, args.batch_size * 3 * 256 * 256, dtype=torch.float32).view( + args.batch_size, 3, 256, 256 + ) + started = time.perf_counter() + with torch.no_grad(): + reference = model(image) + exported = torch.export.export(model, (image,), strict=False) + actual = exported.module()(image) + export_s = time.perf_counter() - started + reference_tensor = reference + actual_tensor = actual + if not torch.allclose(reference_tensor, actual_tensor, atol=1e-5, rtol=1e-5): + raise RuntimeError("exported CPU graph does not match source module") + args.output.parent.mkdir(parents=True, exist_ok=True) + torch.export.save(exported, args.output) + report = { + "status": "passed", + "scope": "fixed-shape Cosmos CI8x8 encoder graph; no InternVLA action-policy claim", + "encoder_sha256": sha256(encoder_path), + "source_sha256": {name: sha256(source_dir / name) for name in ("model_cosmos.py", "cosmos_ci_torch.py")}, + "torch": torch.__version__, + "input_shape": list(image.shape), + "input_dtype": str(image.dtype), + "output_shape": list(reference_tensor.shape), + "max_abs_export_error": float((reference_tensor - actual_tensor).abs().max()), + "export_s": export_s, + "artifact_sha256": sha256(args.output), + "artifact_bytes": args.output.stat().st_size, + "artifact_path": str(args.output.resolve()), + } + args.report.parent.mkdir(parents=True, exist_ok=True) + args.report.write_text(json.dumps(report, indent=2) + "\n", encoding="utf-8") + print(json.dumps(report, indent=2)) + + +if __name__ == "__main__": + main() diff --git a/benchmarks/edge_harness/experiments/probe_internvla_cosmos_directml.py b/benchmarks/edge_harness/experiments/probe_internvla_cosmos_directml.py index 180d868e0..e635ee72b 100644 --- a/benchmarks/edge_harness/experiments/probe_internvla_cosmos_directml.py +++ b/benchmarks/edge_harness/experiments/probe_internvla_cosmos_directml.py @@ -54,11 +54,13 @@ def main() -> None: parser.add_argument("--encoder", type=Path, required=True) parser.add_argument("--output", type=Path, required=True) parser.add_argument("--dml-index", type=int, default=1) + parser.add_argument("--batch-size", type=int, default=1) + parser.add_argument("--model-dtype", choices=("float32", "bfloat16"), default="float32") parser.add_argument("--warmups", type=int, default=1) parser.add_argument("--repeats", type=int, default=20) args = parser.parse_args() - if args.warmups < 0 or args.repeats < 1: - parser.error("invalid warmup or measured count") + if args.warmups < 0 or args.repeats < 1 or args.batch_size < 1: + parser.error("invalid batch size, warmup or measured count") import numpy as np import psutil @@ -83,8 +85,8 @@ def main() -> None: "device_name": device_name, "torch": torch.__version__, "torch_directml": __import__("importlib.metadata", fromlist=["version"]).version("torch-directml"), - "input_shape": [1, 3, 256, 256], - "input_dtype": "float32", + "input_shape": [args.batch_size, 3, 256, 256], + "input_dtype": args.model_dtype, "warmups": args.warmups, "repeats": args.repeats, } @@ -94,9 +96,12 @@ def main() -> None: image[:, 0, 48:208, 48:208] = 1 image[:, 1, 48:208, 48:208] = -1 image[:, 2, :, :] = torch.linspace(-1, 1, 256)[None, None, :] + image = image.repeat(args.batch_size, 1, 1, 1) + model_dtype = getattr(torch, args.model_dtype) + image = image.to(model_dtype) started = time.perf_counter() - cpu_model = source.load_cosmos_component(encoder, component="encoder", device="cpu") + cpu_model = source.load_cosmos_component(encoder, component="encoder", device="cpu").to(model_dtype) report["cpu_load_s"] = time.perf_counter() - started with safe_open(str(encoder), framework="pt", device="cpu") as checkpoint: checkpoint_keys = set(checkpoint.keys()) @@ -125,7 +130,7 @@ def main() -> None: set(report["checkpoint_unexpected_keys"]) != set(checkpoint_buffers)): raise RuntimeError("Cosmos encoder checkpoint/state keys do not match") started = time.perf_counter() - dml_model = source.load_cosmos_component(encoder, component="encoder", device="cpu").to(dml) + dml_model = source.load_cosmos_component(encoder, component="encoder", device="cpu").to(dtype=model_dtype, device=dml) report["dml_load_and_transfer_s"] = time.perf_counter() - started if {parameter.device.type for parameter in cpu_model.parameters()} != {"cpu"}: raise RuntimeError("CPU reference encoder placement differs") diff --git a/benchmarks/edge_harness/experiments/probe_internvla_hybrid_actions.py b/benchmarks/edge_harness/experiments/probe_internvla_hybrid_actions.py new file mode 100644 index 000000000..bddba3d05 --- /dev/null +++ b/benchmarks/edge_harness/experiments/probe_internvla_hybrid_actions.py @@ -0,0 +1,225 @@ +#!/usr/bin/env python3 +"""Compare complete InternVLA actions on CPU with a Radeon Cosmos handoff. + +The policy and action sampler remain on CPU. Only its Cosmos encoder is +replaced by Omni's existing external torch-DirectML graph worker. The test +uses synthetic observations and does not establish robot-task quality. +""" + +from __future__ import annotations + +import argparse +import hashlib +import json +import math +import os +import time +import traceback +from pathlib import Path + + +def sha256(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as source: + for block in iter(lambda: source.read(8 << 20), b""): + digest.update(block) + return digest.hexdigest() + + +def rank(values: list[float], fraction: float) -> float: + return sorted(values)[math.ceil(len(values) * fraction) - 1] + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--model-dir", type=Path, required=True) + parser.add_argument("--cosmos-dir", type=Path, required=True) + parser.add_argument("--processor-dir", type=Path, required=True) + parser.add_argument("--graph", type=Path, required=True) + parser.add_argument("--export-report", type=Path, required=True) + parser.add_argument("--output", type=Path, required=True) + parser.add_argument("--warmups", type=int, default=1) + parser.add_argument("--repeats", type=int, default=20) + args = parser.parse_args() + if args.warmups < 0 or args.repeats < 1: + parser.error("warmups must be nonnegative and repeats must be positive") + + os.environ["INTERNVLA_A1_COSMOS_DIR"] = str(args.cosmos_dir.resolve(strict=True)) + os.environ["INTERNVLA_A1_PROCESSOR_DIR"] = str(args.processor_dir.resolve(strict=True)) + os.environ["HF_HUB_OFFLINE"] = "1" + + import numpy as np + import psutil + import torch + + from vllm_omni.diffusion.data import OmniDiffusionConfig + from vllm_omni.diffusion.registry import initialize_model + from vllm_omni.diffusion.request import OmniDiffusionRequest + from vllm_omni.diffusion.worker.request_batch import DiffusionRequestBatch + from vllm_omni.edge.local.external.client import ExternalWorker + from vllm_omni.edge.local.external.launch import ROUTE_TORCH_DML, resolve + from vllm_omni.inputs.data import OmniDiffusionSamplingParams + + graph = args.graph.resolve(strict=True) + export_report = json.loads(args.export_report.read_text(encoding="utf-8")) + if export_report["artifact_sha256"] != sha256(graph): + raise RuntimeError("exported graph hash differs from the pinned manifest") + if export_report["input_shape"] != [6, 3, 256, 256] or export_report["input_dtype"] != "torch.float32": + raise RuntimeError("wrong Cosmos export shape or precision") + model_dir = args.model_dir.resolve(strict=True) + checkpoint = model_dir / "model.safetensors" + if not checkpoint.is_file(): + raise FileNotFoundError(checkpoint) + report = { + "scope": "InternVLA real Place_Markpen checkpoint, synthetic zero camera/state observations and zero diffusion noise; CPU BF16 policy with FP32 Radeon Cosmos encoder; no robot-task quality claim", + "model_checkpoint_sha256": sha256(checkpoint), + "graph_sha256": export_report["artifact_sha256"], + "graph_export": export_report, + "policy_torch": torch.__version__, + "warmups": args.warmups, + "repeats": args.repeats, + "status": "running", + } + worker = None + try: + config = OmniDiffusionConfig( + model=str(model_dir), + model_class_name="InternVLAA1Pipeline", + dtype=torch.bfloat16, + custom_pipeline_args={ + "device": "cpu", "dtype": "bfloat16", "compile_model": False, + "enable_regional_compile": False, "enable_warmup": False, + "strict_load": True, "processor_model_name": str(args.processor_dir.resolve()), + }, + ) + started = time.perf_counter() + pipeline = initialize_model(config) + report["policy_load_s"] = time.perf_counter() - started + if pipeline.runtime_mode() != "real_checkpoint_loaded": + raise RuntimeError(f"unexpected policy mode: {pipeline.runtime_mode()}") + if {p.device.type for p in pipeline.policy.parameters()} != {"cpu"}: + raise RuntimeError("policy did not load wholly on CPU") + report["policy_parameters_device"] = "cpu" + inputs = pipeline._build_fake_batch_inputs() + noise = torch.zeros((1, pipeline.config.chunk_size, pipeline.config.max_action_dim), dtype=torch.float32) + + route = resolve(ROUTE_TORCH_DML) + if not route.available: + raise RuntimeError(f"DirectML route unavailable: {route.reason}") + worker = ExternalWorker(route) + started = time.perf_counter() + hello = worker.start() + load_report = worker.load(graph, example_inputs={"pixels": np.zeros((6, 3, 256, 256), dtype=np.float32)}) + report["worker_start_and_graph_load_s"] = time.perf_counter() - started + report["worker_hello"] = {key: hello.get(key) for key in ("torch", "torch_directml", "available_providers", "executable")} + report["worker_load"] = load_report.to_dict() + if (load_report.device_name != "AMD Radeon(TM) 890M Graphics" or + load_report.fraction_on_target != 1.0 or + load_report.outputs[0]["shape"] != [6, 16, 32, 32]): + raise RuntimeError("Radeon placement or output shape not verified") + + class ExternalCosmosEncoder(torch.nn.Module): + def __init__(self): + super().__init__() + self.calls = 0 + self.timings = [] + + def forward(self, pixels: torch.Tensor) -> torch.Tensor: + if pixels.device.type != "cpu" or tuple(pixels.shape) != (6, 3, 256, 256): + raise RuntimeError(f"unexpected encoder input: {pixels.device}, {tuple(pixels.shape)}") + # DirectML BF16 aborts this runtime; the FP32 graph is an + # explicit artifact change, then latents return as policy BF16. + array = pixels.detach().float().contiguous().numpy() + output, timing = worker.run({"pixels": array}) + self.calls += 1 + self.timings.append(timing.to_dict()) + latent = output["out_0"] + if latent.shape != (6, 16, 32, 32) or not np.isfinite(latent).all(): + raise RuntimeError("bad DirectML Cosmos latent") + return torch.from_numpy(latent).to(pixels.dtype) + + external_encoder = ExternalCosmosEncoder() + cosmos = pipeline.policy.model.cosmos + cpu_encoder = cosmos._enc_model + + def actions(encoder: torch.nn.Module) -> np.ndarray: + cosmos._enc_model = encoder + result = pipeline.forward(DiffusionRequestBatch(requests=[ + OmniDiffusionRequest( + prompt="", + sampling_params=OmniDiffusionSamplingParams(extra_args={ + "batch_inputs": inputs, "noise": noise, "decode_image": False, + }), + request_id="internvla-hybrid-synthetic-observation", + ) + ])) + if result.error: + raise RuntimeError(result.error) + tensor = result.output["payload"]["actions"] + if tensor.device.type != "cpu" or tuple(tensor.shape) != (1, 50, 32): + raise RuntimeError(f"bad policy action shape/device: {tensor.shape} {tensor.device}") + if not torch.isfinite(tensor).all(): + raise RuntimeError("policy actions nonfinite") + return tensor.detach().float().cpu().contiguous().numpy() + + cpu_wall = [] + hybrid_wall = [] + errors = [] + reference = actual = None + for index in range(args.warmups + args.repeats): + started = time.perf_counter() + reference = actions(cpu_encoder) + cpu_s = time.perf_counter() - started + started = time.perf_counter() + actual = actions(external_encoder) + hybrid_s = time.perf_counter() - started + if index >= args.warmups: + cpu_wall.append(cpu_s) + hybrid_wall.append(hybrid_s) + errors.append({ + "max_abs": float(np.max(np.abs(reference - actual))), + "relative_l2": float(np.linalg.norm(reference - actual) / np.linalg.norm(reference)), + "cosine": float(np.dot(reference.ravel(), actual.ravel()) / ( + np.linalg.norm(reference) * np.linalg.norm(actual) + )), + }) + assert reference is not None and actual is not None + cosmos._enc_model = cpu_encoder + report.update({ + "status": "passed", + "action_shape": list(actual.shape), + "cpu_action_sha256_last": hashlib.sha256(reference.tobytes()).hexdigest(), + "hybrid_action_sha256_last": hashlib.sha256(actual.tobytes()).hexdigest(), + "cpu_wall_s": cpu_wall, + "hybrid_wall_s": hybrid_wall, + "per_request_action_error": errors, + "max_action_abs_error": max(e["max_abs"] for e in errors), + "max_action_relative_l2_error": max(e["relative_l2"] for e in errors), + "min_action_cosine": min(e["cosine"] for e in errors), + "cpu_p50_wall_s": rank(cpu_wall, .5), + "cpu_p95_wall_s": rank(cpu_wall, .95), + "hybrid_p50_wall_s": rank(hybrid_wall, .5), + "hybrid_p95_wall_s": rank(hybrid_wall, .95), + "external_encoder_calls": external_encoder.calls, + "external_encoder_timings": external_encoder.timings, + "worker_stats": worker.stats(), + "parent_rss_bytes_after": psutil.Process().memory_info().rss, + "wsl_available_bytes_after": psutil.virtual_memory().available, + }) + except BaseException as exc: + report["status"] = "failed" + report["error"] = f"{type(exc).__name__}: {exc}" + report["traceback"] = traceback.format_exc() + raise + finally: + if worker is not None: + worker.close() + args.output.parent.mkdir(parents=True, exist_ok=True) + args.output.write_text(json.dumps(report, indent=2) + "\n", encoding="utf-8") + print(json.dumps({key: value for key, value in report.items() if key not in ( + "cpu_wall_s", "hybrid_wall_s", "per_request_action_error", "external_encoder_timings" + )}, indent=2)) + + +if __name__ == "__main__": + main() diff --git a/benchmarks/edge_harness/results/e2e_expansion_20260923/README.md b/benchmarks/edge_harness/results/e2e_expansion_20260923/README.md index 210c4b8db..1bdbb8463 100644 --- a/benchmarks/edge_harness/results/e2e_expansion_20260923/README.md +++ b/benchmarks/edge_harness/results/e2e_expansion_20260923/README.md @@ -5,6 +5,7 @@ This extends the [60-cell device × model matrix](../e2e_profiling_20260922/evid | Device / model | Verified depth | Observed output and time | Remaining gate | |---|---|---|---| | Native Windows HX370 Radeon 890M / InternVLA-A1 Cosmos CI8x8 encoder | Component C; unchanged Omni encoder source in separate DirectML/PyTorch 2.4 environment, not an Omni full-policy stage | One warmup + 20 serial patterned 256×256 image encodes, including upload/readback: Radeon p50/p95 26.56/27.49 ms versus CPU 156.49/158.71 ms; relative L2 error 4.73e-07. Encoder weights and output device checked. | Complete policy/action and real-observation parity; policy/controller runtime compatibility, bounded handoff, shared-RAM admission and end-to-end benefit. [Raw evidence](evidence/internvla_cosmos_radeon890m/README.md). | +| WSL HX370 CPU policy + Radeon 890M DirectML Cosmos / InternVLA-A1 Place_Markpen | Complete synthetic action-policy path through Omni diffusion and its external graph worker; FP32 encoder to BF16 policy, not robot-task qualification | One warmup pair + 20 alternating measured CPU/hybrid complete requests returned finite `[1,50,32]` actions. Hybrid wall p50/p95 2.952/3.322 s versus CPU 3.178/3.266 s; 16/20 paired faster but the hybrid tail regressed. Action relative L2 difference 0.9007%, cosine 0.999959. The selected Radeon adapter and graph hash were checked. | Real observations/reference actions, units/timestamps, integrated admission/cancellation, loading peak and sustained tail/power; [raw evidence](evidence/internvla_cosmos_radeon890m/README.md). | | WSL HX370 CPU / Qwen3-TTS 0.6B CustomVoice BF16 | Scoped complete-request Omni resident CPU whole-session stage (P for two named texts; not playable streaming) | One warmup + 20 serial requests returned identical 3.44 s WAVs; nearest-rank complete-request wall p50/p95 8.27/8.47 s (RTF 2.40/2.46), excluding 19.82 s startup. One pinned Whisper tiny.en transcription matched the reference (WER 0); public `AsyncOmni` audio, 10 GiB admission, 4 GiB refusal and cancellation drain passed. The WSL PCM differs from the native Windows output for the same checkpoint/settings. | Cross-OS numerical/quality investigation, playable streaming, post-cancel restart, loading peak, concurrency and sustained power; [raw evidence](evidence/qwen_tts_omni_wsl_cpu/README.md). | | WSL HX370 CPU / MiniCPM-o 4.5 Q4_K_M/F16 GGUF | Scoped complete-request Omni C++ whole-session graph stage (P for one synthetic combined spoken-question+image input; CPU-only model execution) | All 20 measured requests after one warmup answered the red-square question correctly with complete nonzero 24 kHz speech. Nearest-rank complete-request wall p50/p95 22.67/24.83 s; audio duration 1.60–2.92 s, maximum sampled worker RSS 13.70 GB. One WAV independently transcribed exactly (Whisper tiny.en WER 0). 24 GiB admission, 8 GiB refusal and cancellation with zero remaining ledger passed. | Real multimodal suites, playable streaming, speech alignment, post-cancel restart, loading peak, concurrency and sustained power; [raw evidence](evidence/minicpmo_omni_wsl_cpu/README.md). | | Native Windows HX370 CPU / MiniCPM-o 4.5 Q4_K_M/F16 GGUF | Scoped complete-request Omni C++ whole-session graph stage (P for one synthetic combined audio+image input) | Correct red-square answer, 2.24 s 24 kHz WAV; one cold request 24.34 s, sampled RSS 13.11 GB. 24 GiB admission, 8 GiB refusal and in-flight cancellation with zero remaining reservation passed. | Real multimodal suites, playable streaming, repeated latency, loading peak, post-cancel restart and sustained power; [raw evidence](evidence/minicpmo_omni_cpp/README.md). | diff --git a/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/README.md b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/README.md index 1b17732be..748c11be4 100644 --- a/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/README.md +++ b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/README.md @@ -1,6 +1,6 @@ -# InternVLA Cosmos image-encoder component on Radeon 890M +# InternVLA Cosmos encoder and synthetic hybrid policy on Radeon 890M -This is a **component (C) pass**, not an InternVLA action-policy (P) pass. The unchanged Omni `model_cosmos.py` and `cosmos_ci_torch.py` loaded the pinned Cosmos-Tokenizer-CI8x8 encoder and executed one patterned `[1,3,256,256]` float32 image in `[-1,1]` on CPU and DirectML Radeon 890M. The pattern is synthetic; no camera, language, proprioception, diffusion action loop, unit/timestamp or robot-task quality is covered. +The first experiment below is a **component (C) pass**. The unchanged Omni `model_cosmos.py` and `cosmos_ci_torch.py` loaded the pinned Cosmos-Tokenizer-CI8x8 encoder and executed one patterned `[1,3,256,256]` float32 image in `[-1,1]` on CPU and DirectML Radeon 890M. The pattern is synthetic; this component result alone covers no camera, language, proprioception, diffusion action loop, unit/timestamp or robot-task quality. A later section records a separate complete synthetic policy path. The host was a Ryzen AI 9 HX 370 on native Windows 11 build 26200, AMD Radeon 890M driver 32.0.22018.6001 (2026-08-12), PyTorch 2.4.1+cpu and torch-directml 0.2.5.dev240914. The separate DirectML environment is not the installed Omni/vLLM 0.29 policy environment. Explicit DirectML device index 1 resolved to `AMD Radeon(TM) 890M Graphics`; all encoder parameters and the pre-readback output were checked on `privateuseone`. The encoder checkpoint SHA256 is `520a3b878e72ee872faccb1211b5d622d194c0fdd177f2f6df097586b8fa98e5`. Source SHA256 values are in [profile20.json](profile20.json). The 88 persistent encoder state tensors all had checkpoint keys. Two nonpersistent patcher buffers were also present in the checkpoint and ignored by the existing model loader; the wavelet buffer differs by at most `7.55e-05` because the checkpoint uses BF16 while the source constructs FP32. The same source-generated buffer was used for CPU and DirectML. @@ -19,3 +19,93 @@ $env:PYTHONUTF8 = '1' --output "$root\vllm-omni-edge\benchmarks\edge_harness\results\e2e_expansion_20260923\evidence\internvla_cosmos_radeon890m\profile20.json" ` --warmups 1 --repeats 20 --dml-index 1 ``` + +## Fixed six-frame component and complete synthetic policy + +The policy's three-camera × two-history fixture sends **six** frames through +Cosmos in one call. A separate [six-frame component profile](profile_batch6_20.json) +used one warmup plus 20 serial patterned calls: Radeon p50/p95 +133.82/144.88 ms including upload/readback, CPU FP32 835.17/851.48 ms, +relative L2 error `5.14e-07`. This is a more relevant shape than the first +single-image component test, but still not a whole-policy measurement. + +DirectML in the tested PyTorch 2.4 worker **aborts on BF16**; the +[fatal log](bf16_batch6_probe.log) is retained. The existing InternVLA policy +uses BF16 Cosmos on CPU. Rather than silently cast it, the hybrid experiment +uses an explicitly FP32 fixed-shape [`.pt2` export](export_batch6.json) of the +same checkpoint, then converts the returned latent to the policy's BF16. +`torch.export(..., strict=False)` produced a CPU output identical to the +unchanged source on the export sample. The 129,872,312-byte graph is stored +outside Git at the report's artifact path; its SHA256 is +`9111b3841893acaaa11cf45715d246da3ac9cdd03c7b33fb3c7c20fe38d74704`. +The experiment refuses a hash, shape or dtype mismatch. Recreate it with +[`export_internvla_cosmos.py`](../../../../experiments/export_internvla_cosmos.py). + +The [hybrid policy probe](../../../../experiments/probe_internvla_hybrid_actions.py) +loaded the real Place_Markpen checkpoint strictly in the WSL CPU Omni +diffusion pipeline, kept the Qwen3-VL/flow action policy on CPU and used +Omni's existing external `torch-dml` worker for only the Cosmos encoder. +The worker reported the selected adapter as `AMD Radeon(TM) 890M Graphics`; +its output remained on DirectML before readback. Its graph placement report +counts one **output tensor**, not every internal operation; no per-operator +attribution was captured. The controller used PyTorch 2.13.0+cpu, vLLM +0.28.0 and current Omni 0.29 source (a version mismatch warning remains); +the worker used PyTorch 2.4.1+cu121 over WSL GPU-PV. The underlying host was +the same Windows 11 build 26200 HX370/Radeon with driver 32.0.22018.6001. +Both policies received identical synthetic zero camera/state observations, +empty task and zero diffusion noise; output was a finite `[1,50,32]` action +tensor. This is a **synthetic complete policy path**, not a real robot-task +E2E result. The checkpoint's `train_config.json` says `action_mode=delta`, +but physical units, joint order, observation timestamps, action horizon and +reference action quality were not validated. + +The [paired 20-request result](hybrid_profile20.json) alternated CPU-only and +CPU+Radeon complete policy calls after one warmup pair, with one loaded policy +and persistent worker. Nearest-rank complete-request wall p50/p95 was +**3.178/3.266 s** on CPU and **2.952/3.322 s** on the hybrid. The paired +median improvement was 0.207 s (16/20 hybrid calls faster), but the hybrid +p95 regressed because several DirectML calls took about 0.5 s instead of +about 0.15 s. The largest action max-absolute difference was `0.00715`, +relative L2 `0.9007%`, cosine `0.999959`; the difference was repeatable on +this one fixture. No task tolerance is established, and the FP32/BF16 change +needs real-observation reference actions before deployment. Policy load was +32.96 s, worker start+graph load 3.34 s; these costs are excluded from the +request percentiles. Parent RSS after profiling was 9.30 GB and worker peak +RSS 0.91 GB; these are not shared-iGPU allocation or loading-peak bounds. +Power and thermal state were not recorded. + +The [first hybrid smoke](hybrid_smoke.json) and the later +[selected-adapter check](hybrid_selected_adapter.json) are retained. The +candidate still lacks an Omni graph-stage deployment plan with combined +shared-RAM admission, cancellation/restart validation, observation/action +metadata and real input quality. A single cold request loses the worker +startup cost, and the latency tail currently prevents a general speedup +claim. Keep CPU as the qualified baseline until those gates pass. + +Recreate the graph with the recorded Windows PyTorch 2.4 environment. Use the +freshly generated report alongside its graph, since serialization may produce +a different byte hash on another run: + +```powershell +$root = '\\wsl.localhost\Ubuntu\home\zhout\project\edge_infer' +$env:PYTHONUTF8 = '1' +& 'C:\Users\zhout\w2\qwen_dml_venv\Scripts\python.exe' ` + "$root\vllm-omni-edge\benchmarks\edge_harness\experiments\export_internvla_cosmos.py" ` + --encoder "$root\models\Cosmos-Tokenizer-CI8x8\encoder.safetensors" ` + --output "$root\models\InternVLA-cosmos-encoder-batch6.pt2" ` + --report "$root\models\InternVLA-cosmos-encoder-batch6.export.json" --batch-size 6 +``` + +Reproduce the complete synthetic policy probe from this repository root on +WSL, using the matching local export report: + +```bash +PYTHONPATH="$PWD" OMP_NUM_THREADS=8 MKL_NUM_THREADS=8 TOKENIZERS_PARALLELISM=false \ + ../.venvs/omni-cpu/bin/python benchmarks/edge_harness/experiments/probe_internvla_hybrid_actions.py \ + --model-dir ../models/InternVLA-A1-3B-FT-Place_Markpen \ + --cosmos-dir ../models/Cosmos-Tokenizer-CI8x8 \ + --processor-dir ../models/Qwen3-VL-2B-Instruct-processor \ + --graph ../models/InternVLA-cosmos-encoder-batch6.pt2 \ + --export-report ../models/InternVLA-cosmos-encoder-batch6.export.json \ + --output /tmp/internvla-hybrid-profile.json --warmups 1 --repeats 20 +``` diff --git a/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/bf16_batch6_probe.log b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/bf16_batch6_probe.log new file mode 100644 index 000000000..3b051b7d2 --- /dev/null +++ b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/bf16_batch6_probe.log @@ -0,0 +1 @@ +[F924 00:53:57.000000000 dml_util.cc:118] Invalid or unsupported data type BFloat16. diff --git a/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/export_batch6.json b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/export_batch6.json new file mode 100644 index 000000000..2a619b34d --- /dev/null +++ b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/export_batch6.json @@ -0,0 +1,28 @@ +{ + "status": "passed", + "scope": "fixed-shape Cosmos CI8x8 encoder graph; no InternVLA action-policy claim", + "encoder_sha256": "520a3b878e72ee872faccb1211b5d622d194c0fdd177f2f6df097586b8fa98e5", + "source_sha256": { + "model_cosmos.py": "81f523767d356f16856fa35521bc637ac5df9fc8383ca11fc9a58875eb4c97c7", + "cosmos_ci_torch.py": "a88015b3854b8da730b89c6a35eb3b23721608797208847d9b4cb9a8b8d60f5e" + }, + "torch": "2.4.1+cpu", + "input_shape": [ + 6, + 3, + 256, + 256 + ], + "input_dtype": "torch.float32", + "output_shape": [ + 6, + 16, + 32, + 32 + ], + "max_abs_export_error": 0.0, + "export_s": 3.224664800101891, + "artifact_sha256": "9111b3841893acaaa11cf45715d246da3ac9cdd03c7b33fb3c7c20fe38d74704", + "artifact_bytes": 129872312, + "artifact_path": "\\\\wsl.localhost\\Ubuntu\\home\\zhout\\project\\edge_infer\\models\\InternVLA-cosmos-encoder-batch6.pt2" +} diff --git a/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/export_batch6.log b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/export_batch6.log new file mode 100644 index 000000000..2a619b34d --- /dev/null +++ b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/export_batch6.log @@ -0,0 +1,28 @@ +{ + "status": "passed", + "scope": "fixed-shape Cosmos CI8x8 encoder graph; no InternVLA action-policy claim", + "encoder_sha256": "520a3b878e72ee872faccb1211b5d622d194c0fdd177f2f6df097586b8fa98e5", + "source_sha256": { + "model_cosmos.py": "81f523767d356f16856fa35521bc637ac5df9fc8383ca11fc9a58875eb4c97c7", + "cosmos_ci_torch.py": "a88015b3854b8da730b89c6a35eb3b23721608797208847d9b4cb9a8b8d60f5e" + }, + "torch": "2.4.1+cpu", + "input_shape": [ + 6, + 3, + 256, + 256 + ], + "input_dtype": "torch.float32", + "output_shape": [ + 6, + 16, + 32, + 32 + ], + "max_abs_export_error": 0.0, + "export_s": 3.224664800101891, + "artifact_sha256": "9111b3841893acaaa11cf45715d246da3ac9cdd03c7b33fb3c7c20fe38d74704", + "artifact_bytes": 129872312, + "artifact_path": "\\\\wsl.localhost\\Ubuntu\\home\\zhout\\project\\edge_infer\\models\\InternVLA-cosmos-encoder-batch6.pt2" +} diff --git a/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_profile20.json b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_profile20.json new file mode 100644 index 000000000..21c5b2021 --- /dev/null +++ b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_profile20.json @@ -0,0 +1,416 @@ +{ + "scope": "InternVLA real Place_Markpen checkpoint, synthetic zero camera/state observations and zero diffusion noise; CPU BF16 policy with FP32 Radeon Cosmos encoder; no robot-task quality claim", + "model_checkpoint_sha256": "586799539888c69c35f84d083e559cc5f0ba887801d000e70e65f58d3f85c313", + "graph_sha256": "9111b3841893acaaa11cf45715d246da3ac9cdd03c7b33fb3c7c20fe38d74704", + "graph_export": { + "status": "passed", + "scope": "fixed-shape Cosmos CI8x8 encoder graph; no InternVLA action-policy claim", + "encoder_sha256": "520a3b878e72ee872faccb1211b5d622d194c0fdd177f2f6df097586b8fa98e5", + "source_sha256": { + "model_cosmos.py": "81f523767d356f16856fa35521bc637ac5df9fc8383ca11fc9a58875eb4c97c7", + "cosmos_ci_torch.py": "a88015b3854b8da730b89c6a35eb3b23721608797208847d9b4cb9a8b8d60f5e" + }, + "torch": "2.4.1+cpu", + "input_shape": [ + 6, + 3, + 256, + 256 + ], + "input_dtype": "torch.float32", + "output_shape": [ + 6, + 16, + 32, + 32 + ], + "max_abs_export_error": 0.0, + "export_s": 3.224664800101891, + "artifact_sha256": "9111b3841893acaaa11cf45715d246da3ac9cdd03c7b33fb3c7c20fe38d74704", + "artifact_bytes": 129872312, + "artifact_path": "\\\\wsl.localhost\\Ubuntu\\home\\zhout\\project\\edge_infer\\models\\InternVLA-cosmos-encoder-batch6.pt2" + }, + "policy_torch": "2.13.0+cpu", + "warmups": 1, + "repeats": 20, + "status": "passed", + "policy_load_s": 32.959274790016934, + "policy_parameters_device": "cpu", + "worker_start_and_graph_load_s": 3.3366938079707325, + "worker_hello": { + "torch": "2.4.1+cu121", + "torch_directml": "unknown", + "available_providers": [ + "NVIDIA GeForce RTX 5090 Laptop GPU\u0000", + "AMD Radeon(TM) 890M Graphics\u0000" + ], + "executable": "/home/zhout/project/edge_infer/.venvs/dml/bin/python" + }, + "worker_load": { + "ep": "dml", + "graph_path": "/home/zhout/project/edge_infer/models/InternVLA-cosmos-encoder-batch6.pt2", + "session_providers": [ + "torch-directml" + ], + "available_providers": [ + "torch-directml" + ], + "node_counts": { + "dml": 1, + "cpu": 0 + }, + "total_nodes": 1, + "target_nodes": 1, + "fraction_on_target": 1.0, + "session_create_s": 0.8180774669745006, + "warmup_s": 0.677739959966857, + "rss_bytes": 696750080, + "inputs": [ + { + "name": "pixels", + "shape": [ + 6, + 3, + 256, + 256 + ] + } + ], + "outputs": [ + { + "name": "out_0", + "shape": [ + 6, + 16, + 32, + 32 + ] + } + ], + "profile_path": "", + "ep_directory": "", + "requested_provider_missing": "", + "fallback_note": "", + "onnxruntime": "", + "note": "" + }, + "action_shape": [ + 1, + 50, + 32 + ], + "cpu_action_sha256_last": "db60d6590e242694948f7dcdf873b2fff44819d31b0b178fdad5ec9608d46140", + "hybrid_action_sha256_last": "256b244d3b6a8745391690ff88182a5f0f6f9325d279de1e9c5287a00c463798", + "cpu_wall_s": [ + 3.266188815992791, + 3.2130069519625977, + 3.200305638019927, + 3.182389290013816, + 3.2533019420225173, + 3.163670579029713, + 3.1292421899852343, + 3.1379489160026424, + 3.258549672027584, + 3.2664072579937056, + 3.162602616008371, + 3.1880405800184235, + 3.1626134979887865, + 3.1519040080020204, + 3.178045471024234, + 3.110473181004636, + 3.1697323330445215, + 3.1663852329947986, + 3.2292595140170306, + 3.2074096809956245 + ], + "hybrid_wall_s": [ + 3.1687436809879728, + 2.9065867449971847, + 2.9316007799934596, + 3.405398574017454, + 2.9016875599627383, + 2.891013133979868, + 2.9670994469779544, + 3.3216434589703567, + 2.911582596017979, + 3.267322317988146, + 2.9339384569902904, + 2.8921132480027154, + 3.0768511260394007, + 3.2951800349983387, + 2.9927860139869153, + 3.008475508017, + 2.9399544459884055, + 3.071420267049689, + 2.8709001630195417, + 2.952331782958936 + ], + "per_request_action_error": [ + { + "max_abs": 0.007147848606109619, + "relative_l2": 0.009007224813103676, + "cosine": 0.9999594688415527 + }, + { + "max_abs": 0.007147848606109619, + "relative_l2": 0.009007224813103676, + "cosine": 0.9999594688415527 + }, + { + "max_abs": 0.007147848606109619, + "relative_l2": 0.009007224813103676, + "cosine": 0.9999594688415527 + }, + { + "max_abs": 0.007147848606109619, + "relative_l2": 0.009007224813103676, + "cosine": 0.9999594688415527 + }, + { + "max_abs": 0.007147848606109619, + "relative_l2": 0.009007224813103676, + "cosine": 0.9999594688415527 + }, + { + "max_abs": 0.007147848606109619, + "relative_l2": 0.009007224813103676, + "cosine": 0.9999594688415527 + }, + { + "max_abs": 0.007147848606109619, + "relative_l2": 0.009007224813103676, + "cosine": 0.9999594688415527 + }, + { + "max_abs": 0.007147848606109619, + "relative_l2": 0.009007224813103676, + "cosine": 0.9999594688415527 + }, + { + "max_abs": 0.007147848606109619, + "relative_l2": 0.009007224813103676, + "cosine": 0.9999594688415527 + }, + { + "max_abs": 0.007147848606109619, + "relative_l2": 0.009007224813103676, + "cosine": 0.9999594688415527 + }, + { + "max_abs": 0.007147848606109619, + "relative_l2": 0.009007224813103676, + "cosine": 0.9999594688415527 + }, + { + "max_abs": 0.007147848606109619, + "relative_l2": 0.009007224813103676, + "cosine": 0.9999594688415527 + }, + { + "max_abs": 0.007147848606109619, + "relative_l2": 0.009007224813103676, + "cosine": 0.9999594688415527 + }, + { + "max_abs": 0.007147848606109619, + "relative_l2": 0.009007224813103676, + "cosine": 0.9999594688415527 + }, + { + "max_abs": 0.007147848606109619, + "relative_l2": 0.009007224813103676, + "cosine": 0.9999594688415527 + }, + { + "max_abs": 0.007147848606109619, + "relative_l2": 0.009007224813103676, + "cosine": 0.9999594688415527 + }, + { + "max_abs": 0.007147848606109619, + "relative_l2": 0.009007224813103676, + "cosine": 0.9999594688415527 + }, + { + "max_abs": 0.007147848606109619, + "relative_l2": 0.009007224813103676, + "cosine": 0.9999594688415527 + }, + { + "max_abs": 0.007147848606109619, + "relative_l2": 0.009007224813103676, + "cosine": 0.9999594688415527 + }, + { + "max_abs": 0.007147848606109619, + "relative_l2": 0.009007224813103676, + "cosine": 0.9999594688415527 + } + ], + "max_action_abs_error": 0.007147848606109619, + "max_action_relative_l2_error": 0.009007224813103676, + "min_action_cosine": 0.9999594688415527, + "cpu_p50_wall_s": 3.178045471024234, + "cpu_p95_wall_s": 3.266188815992791, + "hybrid_p50_wall_s": 2.952331782958936, + "hybrid_p95_wall_s": 3.3216434589703567, + "external_encoder_calls": 21, + "external_encoder_timings": [ + { + "worker_s": 0.8607061729999259, + "round_trip_s": 0.8648391110473312, + "transport_s": 0.004132938047405332 + }, + { + "worker_s": 0.3715811110450886, + "round_trip_s": 0.3743669349933043, + "transport_s": 0.0027858239482156932 + }, + { + "worker_s": 0.14860690099885687, + "round_trip_s": 0.15083393501117826, + "transport_s": 0.0022270340123213828 + }, + { + "worker_s": 0.14834689296549186, + "round_trip_s": 0.15213954000500962, + "transport_s": 0.0037926470395177603 + }, + { + "worker_s": 0.5417412479873747, + "round_trip_s": 0.5445115080219693, + "transport_s": 0.002770260034594685 + }, + { + "worker_s": 0.14636369701474905, + "round_trip_s": 0.1487328299554065, + "transport_s": 0.002369132940657437 + }, + { + "worker_s": 0.1489313739584759, + "round_trip_s": 0.1511367280036211, + "transport_s": 0.0022053540451452136 + }, + { + "worker_s": 0.14715390495257452, + "round_trip_s": 0.15077846799977124, + "transport_s": 0.003624563047196716 + }, + { + "worker_s": 0.4843184489873238, + "round_trip_s": 0.48674986098194495, + "transport_s": 0.0024314119946211576 + }, + { + "worker_s": 0.14651734399376437, + "round_trip_s": 0.1493279380374588, + "transport_s": 0.0028105940436944366 + }, + { + "worker_s": 0.500042352010496, + "round_trip_s": 0.5025758480187505, + "transport_s": 0.0025334960082545877 + }, + { + "worker_s": 0.14640763704665005, + "round_trip_s": 0.1490332469693385, + "transport_s": 0.0026256099226884544 + }, + { + "worker_s": 0.14674461202230304, + "round_trip_s": 0.1490190249751322, + "transport_s": 0.0022744129528291523 + }, + { + "worker_s": 0.1487067990237847, + "round_trip_s": 0.15151096595218405, + "transport_s": 0.0028041669283993542 + }, + { + "worker_s": 0.511554681987036, + "round_trip_s": 0.5144772549974732, + "transport_s": 0.0029225730104371905 + }, + { + "worker_s": 0.23890922096325085, + "round_trip_s": 0.24169003596762195, + "transport_s": 0.0027808150043711066 + }, + { + "worker_s": 0.2586796889663674, + "round_trip_s": 0.2610690040164627, + "transport_s": 0.0023893150500953197 + }, + { + "worker_s": 0.14408373599871993, + "round_trip_s": 0.14687694498570636, + "transport_s": 0.0027932089869864285 + }, + { + "worker_s": 0.2575082419789396, + "round_trip_s": 0.2602673360379413, + "transport_s": 0.0027590940590016544 + }, + { + "worker_s": 0.15473052201559767, + "round_trip_s": 0.1571155230049044, + "transport_s": 0.002385000989306718 + }, + { + "worker_s": 0.147569980006665, + "round_trip_s": 0.14973747095791623, + "transport_s": 0.0021674909512512386 + } + ], + "worker_stats": { + "runs": 21, + "total_run_s": 5.799204566923436, + "rss_bytes": 695242752, + "peak_rss_bytes": 910659584, + "report": { + "ep": "dml", + "device_name": "AMD Radeon(TM) 890M Graphics\u0000", + "torch": "2.4.1+cu121", + "session_create_s": 0.8180774669745006, + "session_providers": [ + "torch-directml" + ], + "available_providers": [ + "torch-directml" + ], + "inputs": [ + { + "name": "pixels", + "shape": [ + 6, + 3, + 256, + 256 + ] + } + ], + "warmup_s": 0.677739959966857, + "node_counts": { + "dml": 1, + "cpu": 0 + }, + "total_nodes": 1, + "target_nodes": 1, + "fraction_on_target": 1.0, + "outputs": [ + { + "name": "out_0", + "shape": [ + 6, + 16, + 32, + 32 + ] + } + ], + "rss_bytes": 696750080 + } + }, + "parent_rss_bytes_after": 9302196224, + "wsl_available_bytes_after": 22021693440 +} diff --git a/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_profile20.log b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_profile20.log new file mode 100644 index 000000000..ed32e1eb5 --- /dev/null +++ b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_profile20.log @@ -0,0 +1,178 @@ +/home/zhout/project/edge_infer/vllm-omni-edge/vllm_omni/version.py:55: RuntimeWarning: vLLM and vLLM-Omni appear to have mismatched major/minor versions: + --> vLLM-Omni version 0.29.0rc2.dev71+g00510ce38.d20260922 + --> vLLM version 0.28.0 +This will likely cause compatibility issues. + warn_if_misaligned_vllm_version() +W0924 01:01:44.263000 3704894 torch/utils/_pytree.py:630] is an Enum subclass and is now natively supported by torch.compile as an opaque value type. Calling register_constant() on Enum subclasses is deprecated and will be an error in a future release. +W0924 01:01:44.286000 3704894 torch/utils/_pytree.py:630] is an Enum subclass and is now natively supported by torch.compile as an opaque value type. Calling register_constant() on Enum subclasses is deprecated and will be an error in a future release. +INFO 09-24 01:01:45 [importing.py:53] Triton is installed but 0 active driver(s) found (expected 1). Disabling Triton to prevent runtime errors. +WARNING 09-24 01:01:45 [importing.py:65] Triton is installed, but doesn't include CPU backend. Disabling Triton. +INFO 09-24 01:01:45 [importing.py:88] Triton not installed or not compatible; certain GPU-related functions will not be available. +INFO 09-24 01:01:46 [patch.py:259] NVFP4 W4A4 weight_scale NaN-clamp: installed. +INFO 09-24 01:01:46 [patch.py:510] inductor factorable-divisibility patch: installed. +INFO 09-24 01:01:46 [patch.py:646] CPU AOT compile-cache load shim installed: compiled models are reused across engine starts instead of being recompiled. +INFO 09-24 01:01:46 [patch.py:756] CPU weight-load memory release installed (set VLLM_OMNI_CPU_RELEASE_MEMORY=0 to disable). +INFO 09-24 01:01:50 [pipeline_internvla_a1.py:164] Loading InternVLA-A1 weights from /home/zhout/project/edge_infer/models/InternVLA-A1-3B-FT-Place_Markpen +{ + "scope": "InternVLA real Place_Markpen checkpoint, synthetic zero camera/state observations and zero diffusion noise; CPU BF16 policy with FP32 Radeon Cosmos encoder; no robot-task quality claim", + "model_checkpoint_sha256": "586799539888c69c35f84d083e559cc5f0ba887801d000e70e65f58d3f85c313", + "graph_sha256": "9111b3841893acaaa11cf45715d246da3ac9cdd03c7b33fb3c7c20fe38d74704", + "graph_export": { + "status": "passed", + "scope": "fixed-shape Cosmos CI8x8 encoder graph; no InternVLA action-policy claim", + "encoder_sha256": "520a3b878e72ee872faccb1211b5d622d194c0fdd177f2f6df097586b8fa98e5", + "source_sha256": { + "model_cosmos.py": "81f523767d356f16856fa35521bc637ac5df9fc8383ca11fc9a58875eb4c97c7", + "cosmos_ci_torch.py": "a88015b3854b8da730b89c6a35eb3b23721608797208847d9b4cb9a8b8d60f5e" + }, + "torch": "2.4.1+cpu", + "input_shape": [ + 6, + 3, + 256, + 256 + ], + "input_dtype": "torch.float32", + "output_shape": [ + 6, + 16, + 32, + 32 + ], + "max_abs_export_error": 0.0, + "export_s": 3.224664800101891, + "artifact_sha256": "9111b3841893acaaa11cf45715d246da3ac9cdd03c7b33fb3c7c20fe38d74704", + "artifact_bytes": 129872312, + "artifact_path": "\\\\wsl.localhost\\Ubuntu\\home\\zhout\\project\\edge_infer\\models\\InternVLA-cosmos-encoder-batch6.pt2" + }, + "policy_torch": "2.13.0+cpu", + "warmups": 1, + "repeats": 20, + "status": "passed", + "policy_load_s": 32.959274790016934, + "policy_parameters_device": "cpu", + "worker_start_and_graph_load_s": 3.3366938079707325, + "worker_hello": { + "torch": "2.4.1+cu121", + "torch_directml": "unknown", + "available_providers": [ + "NVIDIA GeForce RTX 5090 Laptop GPU\u0000", + "AMD Radeon(TM) 890M Graphics\u0000" + ], + "executable": "/home/zhout/project/edge_infer/.venvs/dml/bin/python" + }, + "worker_load": { + "ep": "dml", + "graph_path": "/home/zhout/project/edge_infer/models/InternVLA-cosmos-encoder-batch6.pt2", + "session_providers": [ + "torch-directml" + ], + "available_providers": [ + "torch-directml" + ], + "node_counts": { + "dml": 1, + "cpu": 0 + }, + "total_nodes": 1, + "target_nodes": 1, + "fraction_on_target": 1.0, + "session_create_s": 0.8180774669745006, + "warmup_s": 0.677739959966857, + "rss_bytes": 696750080, + "inputs": [ + { + "name": "pixels", + "shape": [ + 6, + 3, + 256, + 256 + ] + } + ], + "outputs": [ + { + "name": "out_0", + "shape": [ + 6, + 16, + 32, + 32 + ] + } + ], + "profile_path": "", + "ep_directory": "", + "requested_provider_missing": "", + "fallback_note": "", + "onnxruntime": "", + "note": "" + }, + "action_shape": [ + 1, + 50, + 32 + ], + "cpu_action_sha256_last": "db60d6590e242694948f7dcdf873b2fff44819d31b0b178fdad5ec9608d46140", + "hybrid_action_sha256_last": "256b244d3b6a8745391690ff88182a5f0f6f9325d279de1e9c5287a00c463798", + "max_action_abs_error": 0.007147848606109619, + "max_action_relative_l2_error": 0.009007224813103676, + "min_action_cosine": 0.9999594688415527, + "cpu_p50_wall_s": 3.178045471024234, + "cpu_p95_wall_s": 3.266188815992791, + "hybrid_p50_wall_s": 2.952331782958936, + "hybrid_p95_wall_s": 3.3216434589703567, + "external_encoder_calls": 21, + "worker_stats": { + "runs": 21, + "total_run_s": 5.799204566923436, + "rss_bytes": 695242752, + "peak_rss_bytes": 910659584, + "report": { + "ep": "dml", + "device_name": "AMD Radeon(TM) 890M Graphics\u0000", + "torch": "2.4.1+cu121", + "session_create_s": 0.8180774669745006, + "session_providers": [ + "torch-directml" + ], + "available_providers": [ + "torch-directml" + ], + "inputs": [ + { + "name": "pixels", + "shape": [ + 6, + 3, + 256, + 256 + ] + } + ], + "warmup_s": 0.677739959966857, + "node_counts": { + "dml": 1, + "cpu": 0 + }, + "total_nodes": 1, + "target_nodes": 1, + "fraction_on_target": 1.0, + "outputs": [ + { + "name": "out_0", + "shape": [ + 6, + 16, + 32, + 32 + ] + } + ], + "rss_bytes": 696750080 + } + }, + "parent_rss_bytes_after": 9302196224, + "wsl_available_bytes_after": 22021693440 +} diff --git a/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_selected_adapter.json b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_selected_adapter.json new file mode 100644 index 000000000..20a188e25 --- /dev/null +++ b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_selected_adapter.json @@ -0,0 +1,186 @@ +{ + "scope": "InternVLA real Place_Markpen checkpoint, synthetic zero camera/state observations and zero diffusion noise; CPU BF16 policy with FP32 Radeon Cosmos encoder; no robot-task quality claim", + "model_checkpoint_sha256": "586799539888c69c35f84d083e559cc5f0ba887801d000e70e65f58d3f85c313", + "graph_sha256": "9111b3841893acaaa11cf45715d246da3ac9cdd03c7b33fb3c7c20fe38d74704", + "graph_export": { + "status": "passed", + "scope": "fixed-shape Cosmos CI8x8 encoder graph; no InternVLA action-policy claim", + "encoder_sha256": "520a3b878e72ee872faccb1211b5d622d194c0fdd177f2f6df097586b8fa98e5", + "source_sha256": { + "model_cosmos.py": "81f523767d356f16856fa35521bc637ac5df9fc8383ca11fc9a58875eb4c97c7", + "cosmos_ci_torch.py": "a88015b3854b8da730b89c6a35eb3b23721608797208847d9b4cb9a8b8d60f5e" + }, + "torch": "2.4.1+cpu", + "input_shape": [ + 6, + 3, + 256, + 256 + ], + "input_dtype": "torch.float32", + "output_shape": [ + 6, + 16, + 32, + 32 + ], + "max_abs_export_error": 0.0, + "export_s": 3.224664800101891, + "artifact_sha256": "9111b3841893acaaa11cf45715d246da3ac9cdd03c7b33fb3c7c20fe38d74704", + "artifact_bytes": 129872312, + "artifact_path": "\\\\wsl.localhost\\Ubuntu\\home\\zhout\\project\\edge_infer\\models\\InternVLA-cosmos-encoder-batch6.pt2" + }, + "policy_torch": "2.13.0+cpu", + "warmups": 0, + "repeats": 1, + "status": "passed", + "policy_load_s": 29.15763967798557, + "policy_parameters_device": "cpu", + "worker_start_and_graph_load_s": 3.116139805992134, + "worker_hello": { + "torch": "2.4.1+cu121", + "torch_directml": "unknown", + "available_providers": [ + "NVIDIA GeForce RTX 5090 Laptop GPU\u0000", + "AMD Radeon(TM) 890M Graphics\u0000" + ], + "executable": "/home/zhout/project/edge_infer/.venvs/dml/bin/python" + }, + "worker_load": { + "ep": "dml", + "graph_path": "/home/zhout/project/edge_infer/models/InternVLA-cosmos-encoder-batch6.pt2", + "device_name": "AMD Radeon(TM) 890M Graphics", + "placement_granularity": "output_device", + "session_providers": [ + "torch-directml" + ], + "available_providers": [ + "torch-directml" + ], + "node_counts": { + "dml": 1, + "cpu": 0 + }, + "total_nodes": 1, + "target_nodes": 1, + "fraction_on_target": 1.0, + "session_create_s": 0.8267001520143822, + "warmup_s": 0.5573145250091329, + "rss_bytes": 696872960, + "inputs": [ + { + "name": "pixels", + "shape": [ + 6, + 3, + 256, + 256 + ] + } + ], + "outputs": [ + { + "name": "out_0", + "shape": [ + 6, + 16, + 32, + 32 + ] + } + ], + "profile_path": "", + "ep_directory": "", + "requested_provider_missing": "", + "fallback_note": "", + "onnxruntime": "", + "note": "" + }, + "action_shape": [ + 1, + 50, + 32 + ], + "cpu_action_sha256_last": "db60d6590e242694948f7dcdf873b2fff44819d31b0b178fdad5ec9608d46140", + "hybrid_action_sha256_last": "256b244d3b6a8745391690ff88182a5f0f6f9325d279de1e9c5287a00c463798", + "cpu_wall_s": [ + 3.2618731430266052 + ], + "hybrid_wall_s": [ + 3.699077647004742 + ], + "per_request_action_error": [ + { + "max_abs": 0.007147848606109619, + "relative_l2": 0.009007224813103676, + "cosine": 0.9999594688415527 + } + ], + "max_action_abs_error": 0.007147848606109619, + "max_action_relative_l2_error": 0.009007224813103676, + "min_action_cosine": 0.9999594688415527, + "cpu_p50_wall_s": 3.2618731430266052, + "cpu_p95_wall_s": 3.2618731430266052, + "hybrid_p50_wall_s": 3.699077647004742, + "hybrid_p95_wall_s": 3.699077647004742, + "external_encoder_calls": 1, + "external_encoder_timings": [ + { + "worker_s": 0.9252440289710648, + "round_trip_s": 0.9288088360335678, + "transport_s": 0.0035648070625029504 + } + ], + "worker_stats": { + "runs": 1, + "total_run_s": 0.9252440289710648, + "rss_bytes": 692346880, + "peak_rss_bytes": 911052800, + "report": { + "ep": "dml", + "device_name": "AMD Radeon(TM) 890M Graphics\u0000", + "placement_granularity": "output_device", + "torch": "2.4.1+cu121", + "session_create_s": 0.8267001520143822, + "session_providers": [ + "torch-directml" + ], + "available_providers": [ + "torch-directml" + ], + "inputs": [ + { + "name": "pixels", + "shape": [ + 6, + 3, + 256, + 256 + ] + } + ], + "warmup_s": 0.5573145250091329, + "node_counts": { + "dml": 1, + "cpu": 0 + }, + "total_nodes": 1, + "target_nodes": 1, + "fraction_on_target": 1.0, + "outputs": [ + { + "name": "out_0", + "shape": [ + 6, + 16, + 32, + 32 + ] + } + ], + "rss_bytes": 696872960 + } + }, + "parent_rss_bytes_after": 9297932288, + "wsl_available_bytes_after": 21906087936 +} diff --git a/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_selected_adapter.log b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_selected_adapter.log new file mode 100644 index 000000000..274b66ed7 --- /dev/null +++ b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_selected_adapter.log @@ -0,0 +1,181 @@ +/home/zhout/project/edge_infer/vllm-omni-edge/vllm_omni/version.py:55: RuntimeWarning: vLLM and vLLM-Omni appear to have mismatched major/minor versions: + --> vLLM-Omni version 0.29.0rc2.dev71+g00510ce38.d20260922 + --> vLLM version 0.28.0 +This will likely cause compatibility issues. + warn_if_misaligned_vllm_version() +W0924 01:10:49.657000 3705598 torch/utils/_pytree.py:630] is an Enum subclass and is now natively supported by torch.compile as an opaque value type. Calling register_constant() on Enum subclasses is deprecated and will be an error in a future release. +W0924 01:10:49.680000 3705598 torch/utils/_pytree.py:630] is an Enum subclass and is now natively supported by torch.compile as an opaque value type. Calling register_constant() on Enum subclasses is deprecated and will be an error in a future release. +INFO 09-24 01:10:50 [importing.py:53] Triton is installed but 0 active driver(s) found (expected 1). Disabling Triton to prevent runtime errors. +WARNING 09-24 01:10:50 [importing.py:65] Triton is installed, but doesn't include CPU backend. Disabling Triton. +INFO 09-24 01:10:50 [importing.py:88] Triton not installed or not compatible; certain GPU-related functions will not be available. +INFO 09-24 01:10:51 [patch.py:259] NVFP4 W4A4 weight_scale NaN-clamp: installed. +INFO 09-24 01:10:51 [patch.py:510] inductor factorable-divisibility patch: installed. +INFO 09-24 01:10:51 [patch.py:646] CPU AOT compile-cache load shim installed: compiled models are reused across engine starts instead of being recompiled. +INFO 09-24 01:10:51 [patch.py:756] CPU weight-load memory release installed (set VLLM_OMNI_CPU_RELEASE_MEMORY=0 to disable). +INFO 09-24 01:10:55 [pipeline_internvla_a1.py:164] Loading InternVLA-A1 weights from /home/zhout/project/edge_infer/models/InternVLA-A1-3B-FT-Place_Markpen +{ + "scope": "InternVLA real Place_Markpen checkpoint, synthetic zero camera/state observations and zero diffusion noise; CPU BF16 policy with FP32 Radeon Cosmos encoder; no robot-task quality claim", + "model_checkpoint_sha256": "586799539888c69c35f84d083e559cc5f0ba887801d000e70e65f58d3f85c313", + "graph_sha256": "9111b3841893acaaa11cf45715d246da3ac9cdd03c7b33fb3c7c20fe38d74704", + "graph_export": { + "status": "passed", + "scope": "fixed-shape Cosmos CI8x8 encoder graph; no InternVLA action-policy claim", + "encoder_sha256": "520a3b878e72ee872faccb1211b5d622d194c0fdd177f2f6df097586b8fa98e5", + "source_sha256": { + "model_cosmos.py": "81f523767d356f16856fa35521bc637ac5df9fc8383ca11fc9a58875eb4c97c7", + "cosmos_ci_torch.py": "a88015b3854b8da730b89c6a35eb3b23721608797208847d9b4cb9a8b8d60f5e" + }, + "torch": "2.4.1+cpu", + "input_shape": [ + 6, + 3, + 256, + 256 + ], + "input_dtype": "torch.float32", + "output_shape": [ + 6, + 16, + 32, + 32 + ], + "max_abs_export_error": 0.0, + "export_s": 3.224664800101891, + "artifact_sha256": "9111b3841893acaaa11cf45715d246da3ac9cdd03c7b33fb3c7c20fe38d74704", + "artifact_bytes": 129872312, + "artifact_path": "\\\\wsl.localhost\\Ubuntu\\home\\zhout\\project\\edge_infer\\models\\InternVLA-cosmos-encoder-batch6.pt2" + }, + "policy_torch": "2.13.0+cpu", + "warmups": 0, + "repeats": 1, + "status": "passed", + "policy_load_s": 29.15763967798557, + "policy_parameters_device": "cpu", + "worker_start_and_graph_load_s": 3.116139805992134, + "worker_hello": { + "torch": "2.4.1+cu121", + "torch_directml": "unknown", + "available_providers": [ + "NVIDIA GeForce RTX 5090 Laptop GPU\u0000", + "AMD Radeon(TM) 890M Graphics\u0000" + ], + "executable": "/home/zhout/project/edge_infer/.venvs/dml/bin/python" + }, + "worker_load": { + "ep": "dml", + "graph_path": "/home/zhout/project/edge_infer/models/InternVLA-cosmos-encoder-batch6.pt2", + "device_name": "AMD Radeon(TM) 890M Graphics", + "placement_granularity": "output_device", + "session_providers": [ + "torch-directml" + ], + "available_providers": [ + "torch-directml" + ], + "node_counts": { + "dml": 1, + "cpu": 0 + }, + "total_nodes": 1, + "target_nodes": 1, + "fraction_on_target": 1.0, + "session_create_s": 0.8267001520143822, + "warmup_s": 0.5573145250091329, + "rss_bytes": 696872960, + "inputs": [ + { + "name": "pixels", + "shape": [ + 6, + 3, + 256, + 256 + ] + } + ], + "outputs": [ + { + "name": "out_0", + "shape": [ + 6, + 16, + 32, + 32 + ] + } + ], + "profile_path": "", + "ep_directory": "", + "requested_provider_missing": "", + "fallback_note": "", + "onnxruntime": "", + "note": "" + }, + "action_shape": [ + 1, + 50, + 32 + ], + "cpu_action_sha256_last": "db60d6590e242694948f7dcdf873b2fff44819d31b0b178fdad5ec9608d46140", + "hybrid_action_sha256_last": "256b244d3b6a8745391690ff88182a5f0f6f9325d279de1e9c5287a00c463798", + "max_action_abs_error": 0.007147848606109619, + "max_action_relative_l2_error": 0.009007224813103676, + "min_action_cosine": 0.9999594688415527, + "cpu_p50_wall_s": 3.2618731430266052, + "cpu_p95_wall_s": 3.2618731430266052, + "hybrid_p50_wall_s": 3.699077647004742, + "hybrid_p95_wall_s": 3.699077647004742, + "external_encoder_calls": 1, + "worker_stats": { + "runs": 1, + "total_run_s": 0.9252440289710648, + "rss_bytes": 692346880, + "peak_rss_bytes": 911052800, + "report": { + "ep": "dml", + "device_name": "AMD Radeon(TM) 890M Graphics\u0000", + "placement_granularity": "output_device", + "torch": "2.4.1+cu121", + "session_create_s": 0.8267001520143822, + "session_providers": [ + "torch-directml" + ], + "available_providers": [ + "torch-directml" + ], + "inputs": [ + { + "name": "pixels", + "shape": [ + 6, + 3, + 256, + 256 + ] + } + ], + "warmup_s": 0.5573145250091329, + "node_counts": { + "dml": 1, + "cpu": 0 + }, + "total_nodes": 1, + "target_nodes": 1, + "fraction_on_target": 1.0, + "outputs": [ + { + "name": "out_0", + "shape": [ + 6, + 16, + 32, + 32 + ] + } + ], + "rss_bytes": 696872960 + } + }, + "parent_rss_bytes_after": 9297932288, + "wsl_available_bytes_after": 21906087936 +} diff --git a/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_smoke.json b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_smoke.json new file mode 100644 index 000000000..045e7df69 --- /dev/null +++ b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_smoke.json @@ -0,0 +1,183 @@ +{ + "scope": "InternVLA real Place_Markpen checkpoint, synthetic zero camera/state observations and zero diffusion noise; CPU BF16 policy with FP32 Radeon Cosmos encoder; no robot-task quality claim", + "model_checkpoint_sha256": "586799539888c69c35f84d083e559cc5f0ba887801d000e70e65f58d3f85c313", + "graph_sha256": "9111b3841893acaaa11cf45715d246da3ac9cdd03c7b33fb3c7c20fe38d74704", + "graph_export": { + "status": "passed", + "scope": "fixed-shape Cosmos CI8x8 encoder graph; no InternVLA action-policy claim", + "encoder_sha256": "520a3b878e72ee872faccb1211b5d622d194c0fdd177f2f6df097586b8fa98e5", + "source_sha256": { + "model_cosmos.py": "81f523767d356f16856fa35521bc637ac5df9fc8383ca11fc9a58875eb4c97c7", + "cosmos_ci_torch.py": "a88015b3854b8da730b89c6a35eb3b23721608797208847d9b4cb9a8b8d60f5e" + }, + "torch": "2.4.1+cpu", + "input_shape": [ + 6, + 3, + 256, + 256 + ], + "input_dtype": "torch.float32", + "output_shape": [ + 6, + 16, + 32, + 32 + ], + "max_abs_export_error": 0.0, + "export_s": 3.224664800101891, + "artifact_sha256": "9111b3841893acaaa11cf45715d246da3ac9cdd03c7b33fb3c7c20fe38d74704", + "artifact_bytes": 129872312, + "artifact_path": "\\\\wsl.localhost\\Ubuntu\\home\\zhout\\project\\edge_infer\\models\\InternVLA-cosmos-encoder-batch6.pt2" + }, + "policy_torch": "2.13.0+cpu", + "warmups": 0, + "repeats": 1, + "status": "passed", + "policy_load_s": 29.812130431004334, + "policy_parameters_device": "cpu", + "worker_start_and_graph_load_s": 3.608572050987277, + "worker_hello": { + "torch": "2.4.1+cu121", + "torch_directml": "unknown", + "available_providers": [ + "NVIDIA GeForce RTX 5090 Laptop GPU\u0000", + "AMD Radeon(TM) 890M Graphics\u0000" + ], + "executable": "/home/zhout/project/edge_infer/.venvs/dml/bin/python" + }, + "worker_load": { + "ep": "dml", + "graph_path": "/home/zhout/project/edge_infer/models/InternVLA-cosmos-encoder-batch6.pt2", + "session_providers": [ + "torch-directml" + ], + "available_providers": [ + "torch-directml" + ], + "node_counts": { + "dml": 1, + "cpu": 0 + }, + "total_nodes": 1, + "target_nodes": 1, + "fraction_on_target": 1.0, + "session_create_s": 0.8515134960180148, + "warmup_s": 0.8757424399955198, + "rss_bytes": 696877056, + "inputs": [ + { + "name": "pixels", + "shape": [ + 6, + 3, + 256, + 256 + ] + } + ], + "outputs": [ + { + "name": "out_0", + "shape": [ + 6, + 16, + 32, + 32 + ] + } + ], + "profile_path": "", + "ep_directory": "", + "requested_provider_missing": "", + "fallback_note": "", + "onnxruntime": "", + "note": "" + }, + "action_shape": [ + 1, + 50, + 32 + ], + "cpu_action_sha256_last": "db60d6590e242694948f7dcdf873b2fff44819d31b0b178fdad5ec9608d46140", + "hybrid_action_sha256_last": "256b244d3b6a8745391690ff88182a5f0f6f9325d279de1e9c5287a00c463798", + "cpu_wall_s": [ + 3.4815611069789156 + ], + "hybrid_wall_s": [ + 4.190806481987238 + ], + "per_request_action_error": [ + { + "max_abs": 0.007147848606109619, + "relative_l2": 0.009007224813103676, + "cosine": 0.9999594688415527 + } + ], + "max_action_abs_error": 0.007147848606109619, + "max_action_relative_l2_error": 0.009007224813103676, + "min_action_cosine": 0.9999594688415527, + "cpu_p50_wall_s": 3.4815611069789156, + "cpu_p95_wall_s": 3.4815611069789156, + "hybrid_p50_wall_s": 4.190806481987238, + "hybrid_p95_wall_s": 4.190806481987238, + "external_encoder_calls": 1, + "external_encoder_timings": [ + { + "worker_s": 1.3663232960388996, + "round_trip_s": 1.370061487017665, + "transport_s": 0.0037381909787654877 + } + ], + "worker_stats": { + "runs": 1, + "total_run_s": 1.3663232960388996, + "rss_bytes": 697073664, + "peak_rss_bytes": 910974976, + "report": { + "ep": "dml", + "device_name": "AMD Radeon(TM) 890M Graphics\u0000", + "torch": "2.4.1+cu121", + "session_create_s": 0.8515134960180148, + "session_providers": [ + "torch-directml" + ], + "available_providers": [ + "torch-directml" + ], + "inputs": [ + { + "name": "pixels", + "shape": [ + 6, + 3, + 256, + 256 + ] + } + ], + "warmup_s": 0.8757424399955198, + "node_counts": { + "dml": 1, + "cpu": 0 + }, + "total_nodes": 1, + "target_nodes": 1, + "fraction_on_target": 1.0, + "outputs": [ + { + "name": "out_0", + "shape": [ + 6, + 16, + 32, + 32 + ] + } + ], + "rss_bytes": 696877056 + } + }, + "parent_rss_bytes_after": 9304088576, + "wsl_available_bytes_after": 21880107008 +} diff --git a/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_smoke.log b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_smoke.log new file mode 100644 index 000000000..acb68f2a5 --- /dev/null +++ b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/hybrid_smoke.log @@ -0,0 +1,178 @@ +/home/zhout/project/edge_infer/vllm-omni-edge/vllm_omni/version.py:55: RuntimeWarning: vLLM and vLLM-Omni appear to have mismatched major/minor versions: + --> vLLM-Omni version 0.29.0rc2.dev71+g00510ce38.d20260922 + --> vLLM version 0.28.0 +This will likely cause compatibility issues. + warn_if_misaligned_vllm_version() +W0924 01:00:26.790000 3704813 torch/utils/_pytree.py:630] is an Enum subclass and is now natively supported by torch.compile as an opaque value type. Calling register_constant() on Enum subclasses is deprecated and will be an error in a future release. +W0924 01:00:26.813000 3704813 torch/utils/_pytree.py:630] is an Enum subclass and is now natively supported by torch.compile as an opaque value type. Calling register_constant() on Enum subclasses is deprecated and will be an error in a future release. +INFO 09-24 01:00:28 [importing.py:53] Triton is installed but 0 active driver(s) found (expected 1). Disabling Triton to prevent runtime errors. +WARNING 09-24 01:00:28 [importing.py:65] Triton is installed, but doesn't include CPU backend. Disabling Triton. +INFO 09-24 01:00:28 [importing.py:88] Triton not installed or not compatible; certain GPU-related functions will not be available. +INFO 09-24 01:00:28 [patch.py:259] NVFP4 W4A4 weight_scale NaN-clamp: installed. +INFO 09-24 01:00:28 [patch.py:510] inductor factorable-divisibility patch: installed. +INFO 09-24 01:00:28 [patch.py:646] CPU AOT compile-cache load shim installed: compiled models are reused across engine starts instead of being recompiled. +INFO 09-24 01:00:29 [patch.py:756] CPU weight-load memory release installed (set VLLM_OMNI_CPU_RELEASE_MEMORY=0 to disable). +INFO 09-24 01:00:35 [pipeline_internvla_a1.py:164] Loading InternVLA-A1 weights from /home/zhout/project/edge_infer/models/InternVLA-A1-3B-FT-Place_Markpen +{ + "scope": "InternVLA real Place_Markpen checkpoint, synthetic zero camera/state observations and zero diffusion noise; CPU BF16 policy with FP32 Radeon Cosmos encoder; no robot-task quality claim", + "model_checkpoint_sha256": "586799539888c69c35f84d083e559cc5f0ba887801d000e70e65f58d3f85c313", + "graph_sha256": "9111b3841893acaaa11cf45715d246da3ac9cdd03c7b33fb3c7c20fe38d74704", + "graph_export": { + "status": "passed", + "scope": "fixed-shape Cosmos CI8x8 encoder graph; no InternVLA action-policy claim", + "encoder_sha256": "520a3b878e72ee872faccb1211b5d622d194c0fdd177f2f6df097586b8fa98e5", + "source_sha256": { + "model_cosmos.py": "81f523767d356f16856fa35521bc637ac5df9fc8383ca11fc9a58875eb4c97c7", + "cosmos_ci_torch.py": "a88015b3854b8da730b89c6a35eb3b23721608797208847d9b4cb9a8b8d60f5e" + }, + "torch": "2.4.1+cpu", + "input_shape": [ + 6, + 3, + 256, + 256 + ], + "input_dtype": "torch.float32", + "output_shape": [ + 6, + 16, + 32, + 32 + ], + "max_abs_export_error": 0.0, + "export_s": 3.224664800101891, + "artifact_sha256": "9111b3841893acaaa11cf45715d246da3ac9cdd03c7b33fb3c7c20fe38d74704", + "artifact_bytes": 129872312, + "artifact_path": "\\\\wsl.localhost\\Ubuntu\\home\\zhout\\project\\edge_infer\\models\\InternVLA-cosmos-encoder-batch6.pt2" + }, + "policy_torch": "2.13.0+cpu", + "warmups": 0, + "repeats": 1, + "status": "passed", + "policy_load_s": 29.812130431004334, + "policy_parameters_device": "cpu", + "worker_start_and_graph_load_s": 3.608572050987277, + "worker_hello": { + "torch": "2.4.1+cu121", + "torch_directml": "unknown", + "available_providers": [ + "NVIDIA GeForce RTX 5090 Laptop GPU\u0000", + "AMD Radeon(TM) 890M Graphics\u0000" + ], + "executable": "/home/zhout/project/edge_infer/.venvs/dml/bin/python" + }, + "worker_load": { + "ep": "dml", + "graph_path": "/home/zhout/project/edge_infer/models/InternVLA-cosmos-encoder-batch6.pt2", + "session_providers": [ + "torch-directml" + ], + "available_providers": [ + "torch-directml" + ], + "node_counts": { + "dml": 1, + "cpu": 0 + }, + "total_nodes": 1, + "target_nodes": 1, + "fraction_on_target": 1.0, + "session_create_s": 0.8515134960180148, + "warmup_s": 0.8757424399955198, + "rss_bytes": 696877056, + "inputs": [ + { + "name": "pixels", + "shape": [ + 6, + 3, + 256, + 256 + ] + } + ], + "outputs": [ + { + "name": "out_0", + "shape": [ + 6, + 16, + 32, + 32 + ] + } + ], + "profile_path": "", + "ep_directory": "", + "requested_provider_missing": "", + "fallback_note": "", + "onnxruntime": "", + "note": "" + }, + "action_shape": [ + 1, + 50, + 32 + ], + "cpu_action_sha256_last": "db60d6590e242694948f7dcdf873b2fff44819d31b0b178fdad5ec9608d46140", + "hybrid_action_sha256_last": "256b244d3b6a8745391690ff88182a5f0f6f9325d279de1e9c5287a00c463798", + "max_action_abs_error": 0.007147848606109619, + "max_action_relative_l2_error": 0.009007224813103676, + "min_action_cosine": 0.9999594688415527, + "cpu_p50_wall_s": 3.4815611069789156, + "cpu_p95_wall_s": 3.4815611069789156, + "hybrid_p50_wall_s": 4.190806481987238, + "hybrid_p95_wall_s": 4.190806481987238, + "external_encoder_calls": 1, + "worker_stats": { + "runs": 1, + "total_run_s": 1.3663232960388996, + "rss_bytes": 697073664, + "peak_rss_bytes": 910974976, + "report": { + "ep": "dml", + "device_name": "AMD Radeon(TM) 890M Graphics\u0000", + "torch": "2.4.1+cu121", + "session_create_s": 0.8515134960180148, + "session_providers": [ + "torch-directml" + ], + "available_providers": [ + "torch-directml" + ], + "inputs": [ + { + "name": "pixels", + "shape": [ + 6, + 3, + 256, + 256 + ] + } + ], + "warmup_s": 0.8757424399955198, + "node_counts": { + "dml": 1, + "cpu": 0 + }, + "total_nodes": 1, + "target_nodes": 1, + "fraction_on_target": 1.0, + "outputs": [ + { + "name": "out_0", + "shape": [ + 6, + 16, + 32, + 32 + ] + } + ], + "rss_bytes": 696877056 + } + }, + "parent_rss_bytes_after": 9304088576, + "wsl_available_bytes_after": 21880107008 +} diff --git a/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/profile_batch6_20.json b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/profile_batch6_20.json new file mode 100644 index 000000000..fdd3ef248 --- /dev/null +++ b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/profile_batch6_20.json @@ -0,0 +1,114 @@ +{ + "scope": "InternVLA real Cosmos CI8x8 image encoder component; synthetic patterned 256x256 input; no full policy or robot-task claim", + "source_files_sha256": { + "model_cosmos.py": "81f523767d356f16856fa35521bc637ac5df9fc8383ca11fc9a58875eb4c97c7", + "cosmos_ci_torch.py": "a88015b3854b8da730b89c6a35eb3b23721608797208847d9b4cb9a8b8d60f5e" + }, + "encoder_sha256": "520a3b878e72ee872faccb1211b5d622d194c0fdd177f2f6df097586b8fa98e5", + "device_name": "AMD Radeon(TM) 890M Graphics", + "torch": "2.4.1+cpu", + "torch_directml": "0.2.5.dev240914", + "input_shape": [ + 6, + 3, + 256, + 256 + ], + "input_dtype": "float32", + "warmups": 1, + "repeats": 20, + "cpu_load_s": 0.5824802999850363, + "checkpoint_tensor_count": 90, + "encoder_state_tensor_count": 88, + "checkpoint_missing_keys": [], + "checkpoint_unexpected_keys": [ + "encoder.patcher._arange", + "encoder.patcher.wavelets" + ], + "nonpersistent_buffer_comparison": { + "encoder.patcher._arange": { + "checkpoint_shape": [ + 2 + ], + "model_shape": [ + 2 + ], + "checkpoint_dtype": "torch.int64", + "model_dtype": "torch.int64", + "max_abs_error": 0.0 + }, + "encoder.patcher.wavelets": { + "checkpoint_shape": [ + 2 + ], + "model_shape": [ + 2 + ], + "checkpoint_dtype": "torch.bfloat16", + "model_dtype": "torch.float32", + "max_abs_error": 7.551908493041992e-05 + } + }, + "dml_load_and_transfer_s": 0.65743709995877, + "status": "passed", + "output_shape": [ + 6, + 16, + 32, + 32 + ], + "cpu_output_sha256_float32": "e9e6cf789cbefb1c2f288cf17066f257a89de5548d528e66d2e984ddfddfbe79", + "dml_output_sha256_float32": "f371d1faaf6dfe00759a15d4b238844b6c75aba7757d10683a6b72a7c7c95df0", + "max_abs_error": 1.049041748046875e-05, + "relative_l2_error": 5.140985308571544e-07, + "cosine_similarity": 0.9999999403953552, + "cpu_nearest_rank_p50_wall_s": 0.8351699999766424, + "cpu_nearest_rank_p95_wall_s": 0.8514761000405997, + "dml_nearest_rank_p50_wall_s": 0.13381510006729513, + "dml_nearest_rank_p95_wall_s": 0.14488479995634407, + "cpu_times_s": [ + 0.8759546000510454, + 0.8428523000329733, + 0.8379843001021072, + 0.837651600013487, + 0.8445929000154138, + 0.8227816999424249, + 0.835246599977836, + 0.8439408000558615, + 0.8240886999992654, + 0.8341848999261856, + 0.825562399928458, + 0.8514761000405997, + 0.8318861000007018, + 0.8337026999797672, + 0.8306489000096917, + 0.8351699999766424, + 0.8360441999975592, + 0.8495628000237048, + 0.8333365999860689, + 0.79932450002525 + ], + "dml_times_s": [ + 0.3357291999273002, + 0.12866579997353256, + 0.1395762999309227, + 0.13055210001766682, + 0.12943259999155998, + 0.13381510006729513, + 0.13458940002601594, + 0.13404289993923157, + 0.1437174000311643, + 0.12850900006014854, + 0.12948820006567985, + 0.12899790005758405, + 0.1348303999984637, + 0.12745120003819466, + 0.13730459997896105, + 0.14488479995634407, + 0.1366466999752447, + 0.12663509999401867, + 0.13856200000736862, + 0.1294181999983266 + ], + "process_rss_bytes_after": 2996514816 +} diff --git a/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/profile_batch6_20_driver.log b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/profile_batch6_20_driver.log new file mode 100644 index 000000000..a5d184082 --- /dev/null +++ b/benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/profile_batch6_20_driver.log @@ -0,0 +1,70 @@ +{ + "scope": "InternVLA real Cosmos CI8x8 image encoder component; synthetic patterned 256x256 input; no full policy or robot-task claim", + "source_files_sha256": { + "model_cosmos.py": "81f523767d356f16856fa35521bc637ac5df9fc8383ca11fc9a58875eb4c97c7", + "cosmos_ci_torch.py": "a88015b3854b8da730b89c6a35eb3b23721608797208847d9b4cb9a8b8d60f5e" + }, + "encoder_sha256": "520a3b878e72ee872faccb1211b5d622d194c0fdd177f2f6df097586b8fa98e5", + "device_name": "AMD Radeon(TM) 890M Graphics", + "torch": "2.4.1+cpu", + "torch_directml": "0.2.5.dev240914", + "input_shape": [ + 6, + 3, + 256, + 256 + ], + "input_dtype": "float32", + "warmups": 1, + "repeats": 20, + "cpu_load_s": 0.5824802999850363, + "checkpoint_tensor_count": 90, + "encoder_state_tensor_count": 88, + "checkpoint_missing_keys": [], + "checkpoint_unexpected_keys": [ + "encoder.patcher._arange", + "encoder.patcher.wavelets" + ], + "nonpersistent_buffer_comparison": { + "encoder.patcher._arange": { + "checkpoint_shape": [ + 2 + ], + "model_shape": [ + 2 + ], + "checkpoint_dtype": "torch.int64", + "model_dtype": "torch.int64", + "max_abs_error": 0.0 + }, + "encoder.patcher.wavelets": { + "checkpoint_shape": [ + 2 + ], + "model_shape": [ + 2 + ], + "checkpoint_dtype": "torch.bfloat16", + "model_dtype": "torch.float32", + "max_abs_error": 7.551908493041992e-05 + } + }, + "dml_load_and_transfer_s": 0.65743709995877, + "status": "passed", + "output_shape": [ + 6, + 16, + 32, + 32 + ], + "cpu_output_sha256_float32": "e9e6cf789cbefb1c2f288cf17066f257a89de5548d528e66d2e984ddfddfbe79", + "dml_output_sha256_float32": "f371d1faaf6dfe00759a15d4b238844b6c75aba7757d10683a6b72a7c7c95df0", + "max_abs_error": 1.049041748046875e-05, + "relative_l2_error": 5.140985308571544e-07, + "cosine_similarity": 0.9999999403953552, + "cpu_nearest_rank_p50_wall_s": 0.8351699999766424, + "cpu_nearest_rank_p95_wall_s": 0.8514761000405997, + "dml_nearest_rank_p50_wall_s": 0.13381510006729513, + "dml_nearest_rank_p95_wall_s": 0.14488479995634407, + "process_rss_bytes_after": 2996514816 +} diff --git a/benchmarks/edge_harness/results/e2e_profiling_20260922/evidence/summary/README.md b/benchmarks/edge_harness/results/e2e_profiling_20260922/evidence/summary/README.md index 1a2697bcd..e3cb51bd4 100644 --- a/benchmarks/edge_harness/results/e2e_profiling_20260922/evidence/summary/README.md +++ b/benchmarks/edge_harness/results/e2e_profiling_20260922/evidence/summary/README.md @@ -2,7 +2,7 @@ All 60 pairings have a disposition. The timing tables below remain the 2026-09-22 measurements. The configuration matrix and affected per-cell reasons incorporate the [2026-09-23 scoped recovery runs](../../../e2e_recovery_20260923/README.md) and [WSL CPU/native Windows expansion](../../../e2e_expansion_20260923/README.md). The expansion adds separate 20-request serial MiniCPM-o text-to-speech profiles on WSL CPU and native Windows GPU, a Spark output-head component profile on the HX370 AMD NPU, complete Spark text-request profiles through standalone llama.cpp and a bounded Omni whole-session stage on native Windows CPU and Radeon 890M, native Windows CPU Qwen3-TTS text-to-WAV profiles through both standalone PyTorch and a bounded Omni whole-session stage, and a hybrid CPU+Radeon 890M Qwen3-TTS profile likewise repeated through a bounded Omni whole-session stage. A pinned GGUF MiniCPM-o route adds combined image+audio to text+speech runs on WSL CPU, native Windows CPU and native Windows Radeon 890M+CPU. All three now pass a bounded complete request through an Omni graph stage; the WSL CPU path additionally passed one warmup plus 20 serial measured requests. These are scoped synthetic cases, not full release qualification. -The Radeon 890M InternVLA cell now has a separate 20-call [Cosmos image-encoder component profile](../../../e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/README.md). It remains **NOT E2E** because no complete action-policy workload ran on that placement. +The Radeon 890M InternVLA cell now has a [Cosmos image-encoder component profile and a separate CPU+Radeon complete synthetic action-policy profile](../../../e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/README.md). It remains short of robot-task E2E qualification because real observations, reference actions, units/timestamps, complete admission and lifecycle are unverified. ## Configuration × model @@ -20,7 +20,7 @@ NOT E2E means no complete device/model workload was verified. “Scoped E2E” i | PC HX370: CPU / native Windows | scoped E2E: Omni Spark text | scoped E2E: Omni CPU text → complete WAV | NOT E2E | scoped E2E: Omni GGUF image+audio → text+speech | synthetic policy pass | | PC HX370 + RTX 5090 Laptop / WSL | profile completed | profile completed | scoped E2E: text + image | scoped E2E: text/image/audio → speech | synthetic policy pass | | PC HX370 + RTX 5090 Laptop / Windows | profile completed | profile completed | NOT E2E | scoped E2E: text/image/audio → speech | synthetic policy pass | -| PC HX370 + Radeon 890M / Windows worker | scoped E2E: Omni Spark text | scoped E2E: Omni Radeon talker/codec + CPU predictor | NOT E2E | scoped E2E: Omni Radeon+CPU image+audio → text+speech | NOT E2E (Cosmos encoder component passed) | +| PC HX370 + Radeon 890M / Windows worker | scoped E2E: Omni Spark text | scoped E2E: Omni Radeon talker/codec + CPU predictor | NOT E2E | scoped E2E: Omni Radeon+CPU image+audio → text+speech | synthetic policy pass: CPU policy + Radeon Cosmos | | PC HX370 + AMD NPU / Windows worker | NOT E2E (output-head component passed) | NOT E2E | NOT E2E | NOT E2E | NOT E2E | | PC CPU+iGPU+NPU +/- discrete GPU, joint model execution | NOT E2E | NOT E2E | NOT E2E | NOT E2E | NOT E2E | | PC Snapdragon X Elite CRD / AI Hub | NOT E2E | NOT E2E | NOT E2E | NOT E2E | NOT E2E | @@ -57,7 +57,7 @@ NOT E2E means no complete device/model workload was verified. “Scoped E2E” i | PC HX370 + Radeon 890M / Windows worker | Qwen3-TTS 0.6B CustomVoice | SCOPED_E2E_OMNI_COMPLETE_REQUEST_HYBRID | The pinned Q8_0 CustomVoice talker, F16 codec and punctuation GGUFs completed two named text-to-WAV requests through an Omni whole-session CrispASR stage on native Windows. The runtime log identifies Radeon 890M Vulkan0 for talker/codec and the 432 MB code predictor pinned to CPU FP32; this is not all-Radeon or NPU execution. Both PCM hashes exactly match the earlier standalone outputs. Whisper tiny.en transcribed the first Omni WAV and both standalone WAVs exactly (WER 0 as an intelligibility proxy). One warmup plus 20 serial complete Omni requests for 2.56 s of audio had identical PCM and nearest-rank wall p50/p95 3.298/3.336 s (RTF 1.29/1.30). A public AsyncOmni audio request passed; cancellation drained the worker without stale output or remaining reservation. The earlier standalone profile was 3.310/3.345 s. The default Vulkan configuration previously fell back to CPU, all-Vulkan ran away to a 360-frame cap, and DirectML failed waveform quality. No playable stream, post-cancel restart, loading peak, broad speech quality or sustained power/thermal run is claimed. | Validate playable streaming, restart/recovery, broader voice quality, shared-RAM/GPU peak, concurrency and sustained real-time behavior before wider qualification; [Omni raw evidence](../../../e2e_expansion_20260923/evidence/qwen_tts_omni_hybrid/README.md), [standalone evidence](../../../e2e_expansion_20260923/evidence/qwen_tts_radeon890m_joint/README.md), [failed DirectML route](../../../e2e_expansion_20260923/evidence/qwen_tts_radeon890m_directml/README.md). | | PC HX370 + Radeon 890M / Windows worker | Qwen3.8-27B | NOT_E2E_PROFILEABLE | FP32 448x448 vision tower: DirectML 85/113 nodes; normalized max error 9.095e-06 versus torch CPU. Historical component path, not full 27B or current graph-stage image-to-text integration. | Recover the hashed tower bundle and qualify its current Omni graph handoff with the language stage. | | PC HX370 + Radeon 890M / Windows worker | MiniCPM-o 4.5 | SCOPED_E2E_OMNI_COMPLETE_REQUEST_HYBRID | The same pinned GGUF set ran one combined synthetic spoken-question+JPEG → text+speech request through a bounded Omni whole-session graph stage. Logs verify `GGML_VK_VISIBLE_DEVICES=1`, Radeon 890M Vulkan0 language (37/37 layers) and vision, with CPU TTS/Token2Wav/vocoder. It answered “The square in the image is red.” and produced 2.60 s of 24 kHz speech in 18.27 s complete-request wall time (one cold sample, zero warmups); sampled worker RSS peaked at 15.57 GB. The stage verified artifact and binary hashes, reserved 24 GiB shared RAM, emitted a terminal audio event, and in-flight cancellation left no stale output or reservation. The prior standalone prompted run took 18.63 s and its output transcribed with WER 0. This is CPU+iGPU joint execution, not all-Radeon or NPU execution; neither run qualifies general quality or sustained performance. | Validate real multimodal quality, playable streaming, post-cancel restart, loading peak, repeated/concurrent latency and sustained thermal behavior. [Omni raw evidence](../../../e2e_expansion_20260923/evidence/minicpmo_omni_cpp/README.md), [standalone prompted evidence](../../../e2e_expansion_20260923/evidence/minicpmo_cpp_radeon890m_prompted/README.md). | -| PC HX370 + Radeon 890M / Windows worker | InternVLA-A1 | COMPONENT_PASS; NOT_E2E_PROFILEABLE | The pinned Cosmos CI8x8 image encoder ran on Radeon 890M through DirectML with weights and pre-readback output checked on that device. One warmup plus 20 serial patterned `[1,3,256,256]` component requests, including upload/readback, gave nearest-rank wall p50/p95 26.56/27.49 ms versus 156.49/158.71 ms for the same source on CPU; relative L2 output error was 4.73e-07. This is the real vision-tokenizer component only. The separate DirectML/PyTorch 2.4 environment cannot host the installed Omni/vLLM 0.29 policy directly; no complete Radeon or Radeon+CPU action-policy path, real-observation quality, state/admission or handoff benefit is verified. | Build and validate a bounded component-to-policy handoff in the current Omni controller only if whole-request gain exceeds transfer, startup and shared-RAM costs; check action parity on real observations, units/timestamps and cancellation. [Raw component evidence](../../../e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/README.md). | +| PC HX370 + Radeon 890M / Windows worker | InternVLA-A1 | SYNTHETIC_POLICY_PASS_HYBRID; NOT_TASK_E2E | The real Place_Markpen checkpoint strict-loaded in WSL CPU Omni diffusion. Its Cosmos encoder ran as a pinned FP32 fixed-six-frame export in Omni's external DirectML worker; the selected device was verified as Radeon 890M, and the remainder of the BF16 policy/action loop stayed on CPU. One warmup plus 20 alternating identical synthetic zero-observation/noise requests produced finite `[1,50,32]` actions. Complete-request wall p50/p95 was 2.952/3.322 s hybrid versus 3.178/3.266 s CPU; 16/20 paired calls were faster, but the hybrid tail regressed. Action relative L2 difference was 0.9007% and cosine 0.999959, without a task tolerance. DirectML BF16 aborted, so FP32 encoder is an explicit precision change. Worker startup+graph load took 3.34 s, excluded from warm timing. This proves a scoped synthetic CPU+iGPU policy path, not real-observation quality, action units/time, complete shared-RAM admission, cancellation or sustained benefit. | Validate real observation/reference-action quality and metadata, integrate an admitted bounded graph-stage plan with cancellation/restart, and resolve latency-tail and startup amortization before deployment. [Raw hybrid and component evidence](../../../e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/README.md). | | PC HX370 + AMD NPU / Windows worker | Spark-X2.5 | COMPONENT_PASS; NOT_E2E_PROFILEABLE | The real 1.7B output head (RMS norm and full 131,072-logit projection) ran through Omni `external.graph.v1` with VitisAI: one fused NPU partition and seven CPU nodes per request. The A16W8 graph matched top-1 on four captured activations (full-logit SNR 55.43–56.81 dB). One warmup plus 20 serial repeated-input component requests gave p50/p95 10.21/12.44 ms, versus 17.97/20.29 ms for the original FP32 output head on the same Omni CPU stage. NPU startup was 18.21 s versus 4.48 s for FP32 CPU, and NPU worker peak RSS was 3.52 GiB versus 2.06 GiB. No full prefill/decode/KV/sampling, real handoff, power, or sustained run was verified. | Measure an actual vLLM-to-output-head handoff and whole-generation cost, state/cancellation, memory admission and quality before considering a split plan; [component evidence](../../../e2e_expansion_20260923/evidence/spark_amd_npu_output_head/README.md). | | PC HX370 + AMD NPU / Windows worker | Qwen3-TTS 0.6B CustomVoice | NOT_E2E_PROFILEABLE | No placement- and quality-verified whole-model graph bundle/stateful adapter for this model on this AMD route. Small backend graphs do not establish model support. | Supply and validate the missing matching artifact/backend, then run the complete specified workload. | | PC HX370 + AMD NPU / Windows worker | Qwen3.8-27B | NOT_E2E_PROFILEABLE | The tested A16W8 whole-vision-tower export failed NPU placement. This conclusion is specific to that export, not all future Qwen/NPU combinations. | Validate a supported export or smaller useful component, including same-checkpoint numerical quality. | diff --git a/docs/design/omni_edge_e2e_roadmap.md b/docs/design/omni_edge_e2e_roadmap.md index 0e82d6974..14bb93646 100644 --- a/docs/design/omni_edge_e2e_roadmap.md +++ b/docs/design/omni_edge_e2e_roadmap.md @@ -33,9 +33,15 @@ and output were checked on DirectML, with one warmup and 20 measured patterned 256×256 encodes at 26.56/27.49 ms p50/p95 including transfer and readback, versus 156.49/158.71 ms for the same CPU source. Relative L2 error was 4.73e-07. The separate older DirectML runtime cannot host the current Omni -policy directly. M4 remains open for complete actions, real observations, -time/units, state/admission and a measured full-request handoff benefit; no -joint CPU+iGPU InternVLA E2E status is inferred from this component timing. +policy directly. A follow-up fixed-six-frame FP32 export ran in the existing +Omni external DirectML worker while the real-weight BF16 action policy stayed +on WSL CPU. Twenty paired synthetic complete-policy requests after one warmup +gave hybrid p50/p95 2.952/3.322 s versus CPU 3.178/3.266 s, with 16/20 paired +calls faster but a worse hybrid tail. Action relative L2 difference was 0.9007% +without a task tolerance. This advances M4 to a synthetic CPU+iGPU policy +path, while real observations/reference actions, units/time, shared-RAM +admission, cancellation and sustained benefit remain open. It does not turn +the joint CPU+iGPU+NPU matrix cell into a pass. The WSL RTX MiniCPM-o image-to-text+speech path now passes for one 448×448 synthetic red-square image under an explicit 0.61 thinker GPU budget. The diff --git a/tests/edge/local/external/test_stage.py b/tests/edge/local/external/test_stage.py index c08425648..49a1cc517 100644 --- a/tests/edge/local/external/test_stage.py +++ b/tests/edge/local/external/test_stage.py @@ -152,6 +152,20 @@ def test_verify_placement_accepts_a_real_split(a16w8_graph, npu_device): assert verify_placement(plan, report) is None +def test_load_report_preserves_selected_adapter_name(): + from vllm_omni.edge.local.external.client import LoadReport + + report = LoadReport.from_body( + {"device_name": "AMD Radeon(TM) 890M Graphics\x00", "fraction_on_target": 1.0, + "placement_granularity": "output_device", "target_nodes": 1, "total_nodes": 1}, + ep="dml", graph_path="cosmos.pt2", + ) + assert report.device_name == "AMD Radeon(TM) 890M Graphics" + assert report.placement_granularity == "output_device" + assert "1/1 outputs" in report.summary() + assert report.to_dict()["device_name"] == report.device_name + + def test_refusing_a_plan_cannot_be_opened(a16w8_graph, npu_device): plan = plan_external_stage(_artifact(a16w8_graph, fmt=FORMAT_ONNX_FP16), [npu_device]) with pytest.raises(PlacementRefused): diff --git a/vllm_omni/edge/local/external/client.py b/vllm_omni/edge/local/external/client.py index 1c4afc6e6..ab33ce51c 100644 --- a/vllm_omni/edge/local/external/client.py +++ b/vllm_omni/edge/local/external/client.py @@ -64,6 +64,8 @@ class LoadReport: ep: str graph_path: str + device_name: str = "" + placement_granularity: str = "graph_nodes" session_providers: tuple[str, ...] = () available_providers: tuple[str, ...] = () node_counts: dict[str, int] = field(default_factory=dict) @@ -89,6 +91,8 @@ class LoadReport: return cls( ep=ep, graph_path=graph_path, + device_name=str(body.get("device_name") or "").rstrip("\x00"), + placement_granularity=str(body.get("placement_granularity") or "graph_nodes"), session_providers=tuple(body.get("session_providers") or ()), available_providers=tuple(body.get("available_providers") or ()), node_counts=dict(body.get("node_counts") or {}), @@ -116,9 +120,11 @@ class LoadReport: placement = f"placement unverified ({self.note or 'no profiled run'})" else: split = ", ".join(f"{k}={v}" for k, v in sorted(self.node_counts.items())) - placement = f"{self.target_nodes}/{self.total_nodes} nodes on {self.ep} ({split})" + counted = "outputs" if self.placement_granularity == "output_device" else "nodes" + placement = f"{self.target_nodes}/{self.total_nodes} {counted} on {self.ep} ({split})" + device_suffix = f" ({self.device_name})" if self.device_name else "" return ( - f"{Path(self.graph_path).name} on {self.ep}: {placement}; " + f"{Path(self.graph_path).name} on {self.ep}{device_suffix}: {placement}; " f"session {self.session_create_s:.3f}s, warmup {self.warmup_s:.3f}s, " f"worker rss {self.rss_bytes / 2**20:.0f} MiB" ) diff --git a/vllm_omni/edge/local/external/worker_dml.py b/vllm_omni/edge/local/external/worker_dml.py index ceb9e05ab..ee1d8bdae 100644 --- a/vllm_omni/edge/local/external/worker_dml.py +++ b/vllm_omni/edge/local/external/worker_dml.py @@ -150,6 +150,7 @@ def _load(state: _Session, body: dict[str, Any], tensors: dict[str, np.ndarray]) info: dict[str, Any] = { "ep": "dml", "device_name": device_name, + "placement_granularity": "output_device", "torch": torch.__version__, "session_create_s": create_s, "session_providers": ["torch-directml"],