Profile InternVLA Cosmos encoder on Radeon 890M and update matrix

This commit is contained in:
tzhouam committed 2026-09-24 00:51:17 +08:00
1 parent e6ea35ca12
commit b796c787ec
11 files changed
+587 -2

No files matched your search

@@ -0,0 +1,193 @@
#!/usr/bin/env python3
"""Probe InternVLA's real Cosmos image encoder on CPU and one DirectML GPU.
This loads the unchanged Omni model source as an isolated experiment because
the installed DirectML PyTorch environment is separate from the vLLM runtime.
It tests one model component, not the full action policy or robot-task quality.
"""
from __future__ import annotations
import argparse
import hashlib
import importlib.util
import json
import math
import sys
import time
import traceback
import types
from pathlib import Path
def _rank(values: list[float], fraction: float) -> float:
return sorted(values)[math.ceil(len(values) * fraction) - 1]
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 _load_omni_cosmos_module(source_dir: Path):
# Keep the model implementation unchanged without importing the unrelated
# vLLM engine in a separate, older Torch/DirectML experiment environment.
package_name = "internvla_cosmos_probe"
package = types.ModuleType(package_name)
package.__path__ = [str(source_dir)]
sys.modules[package_name] = package
name = f"{package_name}.model_cosmos"
spec = importlib.util.spec_from_file_location(name, source_dir / "model_cosmos.py")
if spec is None or spec.loader is None:
raise RuntimeError("could not load unchanged InternVLA Cosmos source")
module = importlib.util.module_from_spec(spec)
sys.modules[name] = module
spec.loader.exec_module(module)
return module
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("--dml-index", type=int, default=1)
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")
import numpy as np
import psutil
import torch
import torch_directml
from safetensors import safe_open
source_dir = Path(__file__).resolve().parents[3] / "vllm_omni" / "diffusion" / "models" / "internvla_a1"
source = _load_omni_cosmos_module(source_dir)
device_name = torch_directml.device_name(args.dml_index).rstrip("\x00")
if device_name != "AMD Radeon(TM) 890M Graphics":
raise RuntimeError(f"refusing unverified DirectML device: {device_name!r}")
dml = torch_directml.device(args.dml_index)
encoder = args.encoder.resolve(strict=True)
report = {
"scope": "InternVLA real Cosmos CI8x8 image encoder component; synthetic patterned 256x256 input; no full policy or robot-task claim",
"source_files_sha256": {
name: _sha256(source_dir / name)
for name in ("model_cosmos.py", "cosmos_ci_torch.py")
},
"encoder_sha256": _sha256(encoder),
"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",
"warmups": args.warmups,
"repeats": args.repeats,
}
try:
torch.manual_seed(42)
image = torch.zeros((1, 3, 256, 256), dtype=torch.float32)
image[:, 0, 48:208, 48:208] = 1
image[:, 1, 48:208, 48:208] = -1
image[:, 2, :, :] = torch.linspace(-1, 1, 256)[None, None, :]
started = time.perf_counter()
cpu_model = source.load_cosmos_component(encoder, component="encoder", device="cpu")
report["cpu_load_s"] = time.perf_counter() - started
with safe_open(str(encoder), framework="pt", device="cpu") as checkpoint:
checkpoint_keys = set(checkpoint.keys())
checkpoint_buffers = {
key: checkpoint.get_tensor(key)
for key in checkpoint_keys
if key in {"encoder.patcher._arange", "encoder.patcher.wavelets"}
}
model_keys = set(cpu_model.state_dict())
report["checkpoint_tensor_count"] = len(checkpoint_keys)
report["encoder_state_tensor_count"] = len(model_keys)
report["checkpoint_missing_keys"] = sorted(model_keys - checkpoint_keys)
report["checkpoint_unexpected_keys"] = sorted(checkpoint_keys - model_keys)
model_buffers = dict(cpu_model.named_buffers())
report["nonpersistent_buffer_comparison"] = {
key: {
"checkpoint_shape": list(value.shape),
"model_shape": list(model_buffers[key].shape),
"checkpoint_dtype": str(value.dtype),
"model_dtype": str(model_buffers[key].dtype),
"max_abs_error": float((value.float() - model_buffers[key].float()).abs().max()),
}
for key, value in checkpoint_buffers.items()
}
if (report["checkpoint_missing_keys"] or
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)
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")
if {parameter.device.type for parameter in dml_model.parameters()} != {"privateuseone"}:
raise RuntimeError("DirectML encoder weights were not on the declared GPU")
def execute(model, input_tensor, expected_device_type):
with torch.no_grad():
output = model(input_tensor)
if not isinstance(output, torch.Tensor):
output = output[0]
if output.device.type != expected_device_type:
raise RuntimeError(f"encoder output on {output.device}, expected {expected_device_type}")
return output.cpu().float().contiguous()
cpu_times: list[float] = []
dml_times: list[float] = []
cpu_output = dml_output = None
for index in range(args.warmups + args.repeats):
started = time.perf_counter()
cpu_output = execute(cpu_model, image, "cpu")
cpu_wall = time.perf_counter() - started
started = time.perf_counter()
dml_output = execute(dml_model, image.to(dml), "privateuseone")
dml_wall = time.perf_counter() - started
if index >= args.warmups:
cpu_times.append(cpu_wall)
dml_times.append(dml_wall)
assert cpu_output is not None and dml_output is not None
if cpu_output.shape != dml_output.shape or not torch.isfinite(dml_output).all():
raise RuntimeError("DirectML encoder returned wrong shape or non-finite output")
reference = cpu_output.numpy()
actual = dml_output.numpy()
difference = reference - actual
report.update({
"status": "passed",
"output_shape": list(reference.shape),
"cpu_output_sha256_float32": hashlib.sha256(reference.tobytes()).hexdigest(),
"dml_output_sha256_float32": hashlib.sha256(actual.tobytes()).hexdigest(),
"max_abs_error": float(np.max(np.abs(difference))),
"relative_l2_error": float(np.linalg.norm(difference) / np.linalg.norm(reference)),
"cosine_similarity": float(np.dot(reference.ravel(), actual.ravel()) / (
np.linalg.norm(reference) * np.linalg.norm(actual)
)),
"cpu_nearest_rank_p50_wall_s": _rank(cpu_times, 0.5),
"cpu_nearest_rank_p95_wall_s": _rank(cpu_times, 0.95),
"dml_nearest_rank_p50_wall_s": _rank(dml_times, 0.5),
"dml_nearest_rank_p95_wall_s": _rank(dml_times, 0.95),
"cpu_times_s": cpu_times,
"dml_times_s": dml_times,
"process_rss_bytes_after": psutil.Process().memory_info().rss,
})
except BaseException as exc:
report["status"] = "failed"
report["error"] = f"{type(exc).__name__}: {exc}"
report["traceback"] = traceback.format_exc()
raise
finally:
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 not key.endswith("times_s")}, indent=2))
if __name__ == "__main__":
main()
@@ -4,6 +4,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 / 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). |
@@ -0,0 +1,21 @@
# InternVLA Cosmos image-encoder component 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 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.
One warmup followed by 20 serial measured calls produced `[1,16,32,32]` outputs. The complete per-call timing includes host-to-DirectML upload, encoder forward, DirectML-to-host readback/synchronization and float32 conversion. Nearest-rank wall p50/p95 were **26.56/27.49 ms** on Radeon and **156.49/158.71 ms** on CPU. The DirectML result versus this CPU source had max absolute error `1.168e-05`, relative L2 error `4.732e-07`, and cosine similarity `0.99999994`. Load plus weight transfer took 0.71 s after CPU construction. These are one-shape, warmed component observations, without external device-utilization trace, process isolation, peak shared-RAM, concurrent load, power or sustained thermal measurement. They cannot be added to prior whole-policy times to claim a hybrid speedup; the full handoff, co-residency, policy output and action quality must be measured together.
The [first failed report](first_report.json) and [log](first_driver.log) preserve a DirectML `torch.inference_mode()` version-counter failure in the first experiment. Using `torch.no_grad()` in the probe resolved that runtime incompatibility without changing model operations. The final [profile report](profile20.json) records checkpoint-key coverage, the two nonpersistent buffers and the successful run. The [single-call pass](second_report.json) preceded the 20-request measurement.
Reproduce in PowerShell from this checkout, with `PYTHONUTF8=1` and the recorded DirectML environment:
```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\probe_internvla_cosmos_directml.py" `
--encoder "$root\models\Cosmos-Tokenizer-CI8x8\encoder.safetensors" `
--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
```
@@ -0,0 +1,65 @@
{
Traceback (most recent call last):
"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": [
1,
3,
256,
256
],
"input_dtype": "float32",
"warmups": 0,
"repeats": 1,
"cpu_load_s": 0.5681545999832451,
"dml_load_and_transfer_s": 1.1489207999547943,
"status": "failed",
"error": "RuntimeError: Cannot set version_counter for inference tensor",
File "\\wsl.localhost\Ubuntu\home\zhout\project\edge_infer\vllm-omni-edge\benchmarks\edge_harness\experiments\probe_internvla_cosmos_directml.py", line 165, in <module>
"traceback": "Traceback (most recent call last):\n File \"\\\\wsl.localhost\\Ubuntu\\home\\zhout\\project\\edge_infer\\vllm-omni-edge\\benchmarks\\edge_harness\\experiments\\probe_internvla_cosmos_directml.py\", line 124, in main\n dml_output = execute(dml_model, image.to(dml))\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\\\\wsl.localhost\\Ubuntu\\home\\zhout\\project\\edge_infer\\vllm-omni-edge\\benchmarks\\edge_harness\\experiments\\probe_internvla_cosmos_directml.py\", line 111, in execute\n output = model(input_tensor)\n ^^^^^^^^^^^^^^^^^^^\n File \"C:\\Users\\zhout\\w2\\qwen_dml_venv\\Lib\\site-packages\\torch\\nn\\modules\\module.py\", line 1553, in _wrapped_call_impl\n return self._call_impl(*args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"C:\\Users\\zhout\\w2\\qwen_dml_venv\\Lib\\site-packages\\torch\\nn\\modules\\module.py\", line 1562, in _call_impl\n return forward_call(*args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"C:\\Users\\zhout\\w2\\qwen_dml_venv\\Lib\\site-packages\\torch\\nn\\modules\\container.py\", line 219, in forward\n input = module(input)\n ^^^^^^^^^^^^^\n File \"C:\\Users\\zhout\\w2\\qwen_dml_venv\\Lib\\site-packages\\torch\\nn\\modules\\module.py\", line 1553, in _wrapped_call_impl\n return self._call_impl(*args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"C:\\Users\\zhout\\w2\\qwen_dml_venv\\Lib\\site-packages\\torch\\nn\\modules\\module.py\", line 1562, in _call_impl\n return forward_call(*args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\\\\wsl.localhost\\Ubuntu\\home\\zhout\\project\\edge_infer\\vllm-omni-edge\\vllm_omni\\diffusion\\models\\internvla_a1\\cosmos_ci_torch.py\", line 270, in forward\n hs = [self.conv_in(x)]\n ^^^^^^^^^^^^^^^\n File \"C:\\Users\\zhout\\w2\\qwen_dml_venv\\Lib\\site-packages\\torch\\nn\\modules\\module.py\", line 1553, in _wrapped_call_impl\n return self._call_impl(*args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"C:\\Users\\zhout\\w2\\qwen_dml_venv\\Lib\\site-packages\\torch\\nn\\modules\\module.py\", line 1562, in _call_impl\n return forward_call(*args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"C:\\Users\\zhout\\w2\\qwen_dml_venv\\Lib\\site-packages\\torch\\nn\\modules\\conv.py\", line 458, in forward\n return self._conv_forward(input, self.weight, self.bias)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"C:\\Users\\zhout\\w2\\qwen_dml_venv\\Lib\\site-packages\\torch\\nn\\modules\\conv.py\", line 454, in _conv_forward\n return F.conv2d(input, weight, bias, self.stride,\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nRuntimeError: Cannot set version_counter for inference tensor\n"
}
main()
File "\\wsl.localhost\Ubuntu\home\zhout\project\edge_infer\vllm-omni-edge\benchmarks\edge_harness\experiments\probe_internvla_cosmos_directml.py", line 124, in main
dml_output = execute(dml_model, image.to(dml))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "\\wsl.localhost\Ubuntu\home\zhout\project\edge_infer\vllm-omni-edge\benchmarks\edge_harness\experiments\probe_internvla_cosmos_directml.py", line 111, in execute
output = model(input_tensor)
^^^^^^^^^^^^^^^^^^^
File "C:\Users\zhout\w2\qwen_dml_venv\Lib\site-packages\torch\nn\modules\module.py", line 1553, in _wrapped_call_impl
return self._call_impl(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\zhout\w2\qwen_dml_venv\Lib\site-packages\torch\nn\modules\module.py", line 1562, in _call_impl
return forward_call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\zhout\w2\qwen_dml_venv\Lib\site-packages\torch\nn\modules\container.py", line 219, in forward
input = module(input)
^^^^^^^^^^^^^
File "C:\Users\zhout\w2\qwen_dml_venv\Lib\site-packages\torch\nn\modules\module.py", line 1553, in _wrapped_call_impl
return self._call_impl(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\zhout\w2\qwen_dml_venv\Lib\site-packages\torch\nn\modules\module.py", line 1562, in _call_impl
return forward_call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "\\wsl.localhost\Ubuntu\home\zhout\project\edge_infer\vllm-omni-edge\vllm_omni\diffusion\models\internvla_a1\cosmos_ci_torch.py", line 270, in forward
hs = [self.conv_in(x)]
^^^^^^^^^^^^^^^
File "C:\Users\zhout\w2\qwen_dml_venv\Lib\site-packages\torch\nn\modules\module.py", line 1553, in _wrapped_call_impl
return self._call_impl(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\zhout\w2\qwen_dml_venv\Lib\site-packages\torch\nn\modules\module.py", line 1562, in _call_impl
return forward_call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\zhout\w2\qwen_dml_venv\Lib\site-packages\torch\nn\modules\conv.py", line 458, in forward
return self._conv_forward(input, self.weight, self.bias)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\zhout\w2\qwen_dml_venv\Lib\site-packages\torch\nn\modules\conv.py", line 454, in _conv_forward
return F.conv2d(input, weight, bias, self.stride,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: Cannot set version_counter for inference tensor
@@ -0,0 +1,25 @@
{
"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": [
1,
3,
256,
256
],
"input_dtype": "float32",
"warmups": 0,
"repeats": 1,
"cpu_load_s": 0.5681545999832451,
"dml_load_and_transfer_s": 1.1489207999547943,
"status": "failed",
"error": "RuntimeError: Cannot set version_counter for inference tensor",
"traceback": "Traceback (most recent call last):\n File \"\\\\wsl.localhost\\Ubuntu\\home\\zhout\\project\\edge_infer\\vllm-omni-edge\\benchmarks\\edge_harness\\experiments\\probe_internvla_cosmos_directml.py\", line 124, in main\n dml_output = execute(dml_model, image.to(dml))\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\\\\wsl.localhost\\Ubuntu\\home\\zhout\\project\\edge_infer\\vllm-omni-edge\\benchmarks\\edge_harness\\experiments\\probe_internvla_cosmos_directml.py\", line 111, in execute\n output = model(input_tensor)\n ^^^^^^^^^^^^^^^^^^^\n File \"C:\\Users\\zhout\\w2\\qwen_dml_venv\\Lib\\site-packages\\torch\\nn\\modules\\module.py\", line 1553, in _wrapped_call_impl\n return self._call_impl(*args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"C:\\Users\\zhout\\w2\\qwen_dml_venv\\Lib\\site-packages\\torch\\nn\\modules\\module.py\", line 1562, in _call_impl\n return forward_call(*args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"C:\\Users\\zhout\\w2\\qwen_dml_venv\\Lib\\site-packages\\torch\\nn\\modules\\container.py\", line 219, in forward\n input = module(input)\n ^^^^^^^^^^^^^\n File \"C:\\Users\\zhout\\w2\\qwen_dml_venv\\Lib\\site-packages\\torch\\nn\\modules\\module.py\", line 1553, in _wrapped_call_impl\n return self._call_impl(*args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"C:\\Users\\zhout\\w2\\qwen_dml_venv\\Lib\\site-packages\\torch\\nn\\modules\\module.py\", line 1562, in _call_impl\n return forward_call(*args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"\\\\wsl.localhost\\Ubuntu\\home\\zhout\\project\\edge_infer\\vllm-omni-edge\\vllm_omni\\diffusion\\models\\internvla_a1\\cosmos_ci_torch.py\", line 270, in forward\n hs = [self.conv_in(x)]\n ^^^^^^^^^^^^^^^\n File \"C:\\Users\\zhout\\w2\\qwen_dml_venv\\Lib\\site-packages\\torch\\nn\\modules\\module.py\", line 1553, in _wrapped_call_impl\n return self._call_impl(*args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"C:\\Users\\zhout\\w2\\qwen_dml_venv\\Lib\\site-packages\\torch\\nn\\modules\\module.py\", line 1562, in _call_impl\n return forward_call(*args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"C:\\Users\\zhout\\w2\\qwen_dml_venv\\Lib\\site-packages\\torch\\nn\\modules\\conv.py\", line 458, in forward\n return self._conv_forward(input, self.weight, self.bias)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"C:\\Users\\zhout\\w2\\qwen_dml_venv\\Lib\\site-packages\\torch\\nn\\modules\\conv.py\", line 454, in _conv_forward\n return F.conv2d(input, weight, bias, self.stride,\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nRuntimeError: Cannot set version_counter for inference tensor\n"
}
@@ -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": [
1,
3,
256,
256
],
"input_dtype": "float32",
"warmups": 1,
"repeats": 20,
"cpu_load_s": 0.5784786000149325,
"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.6941631999798119,
"status": "passed",
"output_shape": [
1,
16,
32,
32
],
"cpu_output_sha256_float32": "75b0c7cc33cc2a9845242030080cf901e4b05bdd5bdd8a65a0a3da253361dc28",
"dml_output_sha256_float32": "f80d2c94d6ccac5c4975b22f5731018be2ae94dbd603abfa37a4a783ec4e6196",
"max_abs_error": 1.1682510375976562e-05,
"relative_l2_error": 4.732218030767399e-07,
"cosine_similarity": 0.9999999403953552,
"cpu_nearest_rank_p50_wall_s": 0.15648690005764365,
"cpu_nearest_rank_p95_wall_s": 0.158714700024575,
"dml_nearest_rank_p50_wall_s": 0.02656210004352033,
"dml_nearest_rank_p95_wall_s": 0.027489100000821054,
"cpu_times_s": [
0.15362280001863837,
0.15843149996362627,
0.15427219995763153,
0.15648690005764365,
0.15469810005743057,
0.15557049994822592,
0.15391450002789497,
0.1574046000605449,
0.15519369998946786,
0.15620780002791435,
0.15926450002007186,
0.15724650002084672,
0.1561526000732556,
0.15597209997940809,
0.158714700024575,
0.15829010005109012,
0.1574720999924466,
0.15677859995048493,
0.15707050007767975,
0.15649339999072254
],
"dml_times_s": [
0.027489100000821054,
0.026306899962946773,
0.02755960007198155,
0.02656210004352033,
0.026282600010745227,
0.024926300044171512,
0.0269368999870494,
0.02647149993572384,
0.026945200050249696,
0.026124599971808493,
0.02645699994172901,
0.026391200022771955,
0.026137599954381585,
0.026738699991256,
0.02733730000909418,
0.027434600051492453,
0.026773600024171174,
0.02701279998291284,
0.026166999945417047,
0.026771700009703636
],
"process_rss_bytes_after": 1406013440
}
@@ -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": [
1,
3,
256,
256
],
"input_dtype": "float32",
"warmups": 1,
"repeats": 20,
"cpu_load_s": 0.5784786000149325,
"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.6941631999798119,
"status": "passed",
"output_shape": [
1,
16,
32,
32
],
"cpu_output_sha256_float32": "75b0c7cc33cc2a9845242030080cf901e4b05bdd5bdd8a65a0a3da253361dc28",
"dml_output_sha256_float32": "f80d2c94d6ccac5c4975b22f5731018be2ae94dbd603abfa37a4a783ec4e6196",
"max_abs_error": 1.1682510375976562e-05,
"relative_l2_error": 4.732218030767399e-07,
"cosine_similarity": 0.9999999403953552,
"cpu_nearest_rank_p50_wall_s": 0.15648690005764365,
"cpu_nearest_rank_p95_wall_s": 0.158714700024575,
"dml_nearest_rank_p50_wall_s": 0.02656210004352033,
"dml_nearest_rank_p95_wall_s": 0.027489100000821054,
"process_rss_bytes_after": 1406013440
}
@@ -0,0 +1,39 @@
{
"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": [
1,
3,
256,
256
],
"input_dtype": "float32",
"warmups": 0,
"repeats": 1,
"cpu_load_s": 0.558287899941206,
"dml_load_and_transfer_s": 1.2977324000094086,
"status": "passed",
"output_shape": [
1,
16,
32,
32
],
"cpu_output_sha256_float32": "75b0c7cc33cc2a9845242030080cf901e4b05bdd5bdd8a65a0a3da253361dc28",
"dml_output_sha256_float32": "f80d2c94d6ccac5c4975b22f5731018be2ae94dbd603abfa37a4a783ec4e6196",
"max_abs_error": 1.1682510375976562e-05,
"relative_l2_error": 4.732218030767399e-07,
"cosine_similarity": 0.9999999403953552,
"cpu_nearest_rank_p50_wall_s": 0.17620460002217442,
"cpu_nearest_rank_p95_wall_s": 0.17620460002217442,
"dml_nearest_rank_p50_wall_s": 0.8288762000156567,
"dml_nearest_rank_p95_wall_s": 0.8288762000156567,
"process_rss_bytes_after": 1006407680
}
@@ -0,0 +1,45 @@
{
"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": [
1,
3,
256,
256
],
"input_dtype": "float32",
"warmups": 0,
"repeats": 1,
"cpu_load_s": 0.558287899941206,
"dml_load_and_transfer_s": 1.2977324000094086,
"status": "passed",
"output_shape": [
1,
16,
32,
32
],
"cpu_output_sha256_float32": "75b0c7cc33cc2a9845242030080cf901e4b05bdd5bdd8a65a0a3da253361dc28",
"dml_output_sha256_float32": "f80d2c94d6ccac5c4975b22f5731018be2ae94dbd603abfa37a4a783ec4e6196",
"max_abs_error": 1.1682510375976562e-05,
"relative_l2_error": 4.732218030767399e-07,
"cosine_similarity": 0.9999999403953552,
"cpu_nearest_rank_p50_wall_s": 0.17620460002217442,
"cpu_nearest_rank_p95_wall_s": 0.17620460002217442,
"dml_nearest_rank_p50_wall_s": 0.8288762000156567,
"dml_nearest_rank_p95_wall_s": 0.8288762000156567,
"cpu_times_s": [
0.17620460002217442
],
"dml_times_s": [
0.8288762000156567
],
"process_rss_bytes_after": 1006407680
}
@@ -1,6 +1,8 @@
# E2E check and profiling
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.
## Configuration × model
@@ -18,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 |
| 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 + 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 |
@@ -55,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 | 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 + 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 + 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. |
+10
View File
@@ -27,6 +27,16 @@ use reached 11.17 GB. Native Windows InternVLA direct-policy runs separately
passed on CPU and RTX 5090 Laptop with synthetic inputs; AMD and mobile cells
do not inherit these passes.
A [native Windows Radeon 890M InternVLA Cosmos encoder probe](../../benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/internvla_cosmos_radeon890m/README.md)
now establishes only component depth C: the real CI8x8 image encoder weights
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.
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
previous 0.58 budget failed the 2,048-token KV admission gate; the successful