Profile Spark BF16 on fork branch and audit S25 short vocoder
This commit is contained in:
1 parent
8978302a1b
commit
68e0fd7cad
51 files changed
+38444
-6
No files matched your search
@@ -0,0 +1,143 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Audit a two-frame Code2Wav S25 candidate against its local CPU export."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import math
|
||||
from collections import Counter
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
def sha256(path: Path) -> str:
|
||||
with path.open("rb") as stream:
|
||||
return hashlib.file_digest(stream, "sha256").hexdigest()
|
||||
|
||||
|
||||
def waveform(path: Path, name: str) -> np.ndarray:
|
||||
with np.load(path, allow_pickle=False) as data:
|
||||
if data.files != [name]:
|
||||
raise ValueError(f"{path}: expected one output named {name}")
|
||||
value = np.asarray(data[name])
|
||||
if value.shape != (1, 3840) or value.dtype != np.float32 or not np.isfinite(value).all():
|
||||
raise ValueError(f"{path}: expected finite float32[1,3840], got {value.shape}/{value.dtype}")
|
||||
return value
|
||||
|
||||
|
||||
def compare(reference: np.ndarray, observed: np.ndarray) -> dict:
|
||||
a = reference.astype(np.float64).ravel()
|
||||
b = observed.astype(np.float64).ravel()
|
||||
delta = float(np.linalg.norm(a - b))
|
||||
norm = float(np.linalg.norm(a))
|
||||
return {
|
||||
"relative_l2": delta / norm,
|
||||
"snr_db": 20 * math.log10(norm / delta) if delta else None,
|
||||
"max_abs": float(np.max(np.abs(a - b))),
|
||||
"reference_rms": float(np.sqrt(np.mean(a * a))),
|
||||
"output_rms": float(np.sqrt(np.mean(b * b))),
|
||||
"output_saturated_fraction_abs_ge_0_999": float(np.mean(np.abs(b) >= 0.999)),
|
||||
}
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
for name in ("export-report", "upload-report", "dataset-report", "fixture",
|
||||
"cpu-output", "eager-output", "compile-report", "inference-report",
|
||||
"device-output", "output-report"):
|
||||
parser.add_argument(f"--{name}", type=Path, required=True)
|
||||
parser.add_argument("--profile-report", type=Path)
|
||||
parser.add_argument("--expected-compile-options", default="--target_runtime qnn_dlc --qnn_options default_graph_htp_precision=FLOAT16")
|
||||
parser.add_argument("--expected-run-options", default="--compute_unit npu")
|
||||
args = parser.parse_args()
|
||||
export = json.loads(args.export_report.read_text())
|
||||
upload = json.loads(args.upload_report.read_text())
|
||||
dataset = json.loads(args.dataset_report.read_text())
|
||||
compile_job = json.loads(args.compile_report.read_text())
|
||||
inference = json.loads(args.inference_report.read_text())
|
||||
profile = json.loads(args.profile_report.read_text()) if args.profile_report else None
|
||||
if export["context_frames"] != 72 or export["chunk_frames"] != 2:
|
||||
raise ValueError("export differs from the tested two-frame window")
|
||||
if (upload["source_sha256"] != export["onnx_sha256"]
|
||||
or compile_job["source_model_id"] != upload["source_model_id"]
|
||||
or compile_job["status"] != "SUCCESS"
|
||||
or compile_job["options"] != args.expected_compile_options):
|
||||
raise ValueError("compile does not use the verified short-window artifact")
|
||||
if (dataset["fixture_sha256"] != export["short_fixture_sha256"]
|
||||
or dataset["input_shape"] != [1, 512, 74]
|
||||
or dataset["sample_count"] != 1
|
||||
or sha256(args.fixture) != dataset["fixture_sha256"]):
|
||||
raise ValueError("hosted input is not the retained short-window fixture")
|
||||
if (inference["status"] != "SUCCESS"
|
||||
or inference["model_id"] != compile_job["target_model_id"]
|
||||
or inference["input_dataset_id"] != dataset["dataset_id"]
|
||||
or inference["options"] != args.expected_run_options
|
||||
or inference["device"] != compile_job["device"]
|
||||
or inference["device"]["name"] != "Samsung Galaxy S25"):
|
||||
raise ValueError("inference differs from the exact S25 target/fixture/route")
|
||||
if (sha256(args.cpu_output) != export["ort_output_sha256"]
|
||||
or sha256(args.eager_output) != export["eager_output_sha256"]):
|
||||
raise ValueError("local CPU outputs differ from export parity evidence")
|
||||
cpu = waveform(args.cpu_output, "wav")
|
||||
eager = waveform(args.eager_output, "wav")
|
||||
hosted = waveform(args.device_output, "output_0__0")
|
||||
report = {
|
||||
"scope": "one two-frame Qwen3-TTS vocoder component on hosted S25; no complete stream",
|
||||
"status": "component_inference_numeric_measured",
|
||||
"device": inference["device"],
|
||||
"source_model_id": compile_job["source_model_id"],
|
||||
"target_model_id": compile_job["target_model_id"],
|
||||
"input_dataset_id": dataset["dataset_id"],
|
||||
"jobs": {"compile": compile_job["job_id"], "inference": inference["job_id"]},
|
||||
"route": {"compile_options": compile_job["options"], "run_options": inference["options"]},
|
||||
"files": {name: {"bytes": path.stat().st_size, "sha256": sha256(path)}
|
||||
for name, path in {"fixture": args.fixture, "ort_cpu": args.cpu_output,
|
||||
"eager_cpu": args.eager_output,
|
||||
"device_output": args.device_output}.items()},
|
||||
"ort_cpu_vs_device": compare(cpu, hosted),
|
||||
"eager_cpu_vs_device": compare(eager, hosted),
|
||||
"limits": [
|
||||
"One fixed two-frame waveform has no listening-quality tolerance.",
|
||||
"The 72-frame input history, talker, predictor and stage handoff did not run on the device.",
|
||||
"No persistent state, admission, cancellation or complete TTS stream was tested.",
|
||||
],
|
||||
}
|
||||
if profile is not None:
|
||||
if (profile["status"] != "SUCCESS"
|
||||
or profile["model_id"] != inference["model_id"]
|
||||
or profile["device"] != inference["device"]
|
||||
or profile["options"] != inference["options"]
|
||||
or profile["shapes"] != {"quantized": [[1, 512, 74], "float32"]}):
|
||||
raise ValueError("placement profile did not use the audited device/artifact")
|
||||
execution = profile["profile"]
|
||||
samples = execution["execution_summary"]["all_inference_times"]
|
||||
if not samples or any(not isinstance(t, int) or t <= 0 for t in samples):
|
||||
raise ValueError("placement profile has no valid timing samples")
|
||||
units = Counter(row.get("compute_unit") for row in execution["execution_detail"])
|
||||
if not units:
|
||||
raise ValueError("placement profile has no node placement detail")
|
||||
ordered = sorted(samples)
|
||||
report["jobs"]["profile"] = profile["job_id"]
|
||||
report["profile"] = {
|
||||
"sample_count": len(samples),
|
||||
"min_us": ordered[0],
|
||||
"nearest_rank_p50_us": ordered[math.ceil(0.5 * len(samples)) - 1],
|
||||
"nearest_rank_p95_us": ordered[math.ceil(0.95 * len(samples)) - 1],
|
||||
"reported_peak_memory_bytes": execution["execution_summary"]["estimated_inference_peak_memory"],
|
||||
"compute_unit_row_counts": dict(units),
|
||||
"profile_input": "Workbench generated input with audited tensor shape; the waveform inference used the retained fixture",
|
||||
}
|
||||
report["status"] = "component_inference_numeric_and_placement_measured"
|
||||
else:
|
||||
report["limits"].append("Requested accelerator execution is not verified node placement without a profile.")
|
||||
args.output_report.write_text(json.dumps(report, indent=2) + "\n")
|
||||
print(json.dumps({"status": report["status"],
|
||||
"comparison": report["ort_cpu_vs_device"],
|
||||
"profile": report.get("profile")}, indent=2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,191 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Export and numerically gate a shorter Qwen3-TTS Code2Wav window.
|
||||
|
||||
The retained 25-frame graph takes 72 context frames plus 25 new frames. This
|
||||
experiment keeps the same decoder and 72-frame history while reducing the new
|
||||
chunk to two frames, before any device compilation or performance claim.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import math
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
import onnx
|
||||
import onnxruntime as ort
|
||||
import torch
|
||||
from torch import nn
|
||||
|
||||
from vllm_omni.edge.decoder_export import load_code2wav_decoder
|
||||
|
||||
|
||||
class QuantizedWindowDecoder(nn.Module):
|
||||
"""The existing decoder after RVQ lookup, with an explicit context window."""
|
||||
|
||||
def __init__(self, decoder: nn.Module, chunk_frames: int) -> None:
|
||||
super().__init__()
|
||||
self.decoder = decoder
|
||||
self.chunk_frames = chunk_frames
|
||||
self.hop = int(decoder.total_upsample)
|
||||
|
||||
def forward(self, quantized: torch.Tensor) -> torch.Tensor:
|
||||
decoder = self.decoder
|
||||
hidden = decoder.pre_conv(quantized).transpose(1, 2)
|
||||
hidden = decoder.pre_transformer(inputs_embeds=hidden).last_hidden_state
|
||||
hidden = hidden.permute(0, 2, 1)
|
||||
for blocks in decoder.upsample:
|
||||
for block in blocks:
|
||||
hidden = block(hidden)
|
||||
for block in decoder.decoder:
|
||||
hidden = block(hidden)
|
||||
return hidden.clamp(-1, 1).reshape(1, -1)[:, -self.chunk_frames * self.hop :]
|
||||
|
||||
|
||||
def sha256(path: Path) -> str:
|
||||
with path.open("rb") as stream:
|
||||
return hashlib.file_digest(stream, "sha256").hexdigest()
|
||||
|
||||
|
||||
def compare(reference: np.ndarray, output: np.ndarray) -> dict:
|
||||
a = reference.astype(np.float64).ravel()
|
||||
b = output.astype(np.float64).ravel()
|
||||
error = float(np.linalg.norm(a - b))
|
||||
norm = float(np.linalg.norm(a))
|
||||
return {
|
||||
"relative_l2": error / norm,
|
||||
"snr_db": 20 * math.log10(norm / error) if error else None,
|
||||
"max_abs": float(np.max(np.abs(a - b))),
|
||||
"reference_rms": float(np.sqrt(np.mean(a * a))),
|
||||
"output_rms": float(np.sqrt(np.mean(b * b))),
|
||||
}
|
||||
|
||||
|
||||
def strip_export_guards(path: Path) -> None:
|
||||
graph = onnx.load(str(path))
|
||||
nodes = graph.graph.node
|
||||
producers = {out: node for node in nodes for out in node.output}
|
||||
rename: dict[str, str] = {}
|
||||
for node in list(nodes):
|
||||
if node.op_type != "Where" or node.input[0] not in producers:
|
||||
continue
|
||||
guard = producers[node.input[0]]
|
||||
if guard.op_type != "IsNaN":
|
||||
continue
|
||||
source = guard.input[0]
|
||||
if source not in node.input[1:]:
|
||||
continue
|
||||
rename[node.output[0]] = source
|
||||
nodes.remove(node)
|
||||
nodes.remove(guard)
|
||||
for node in nodes:
|
||||
for index, value in enumerate(node.input):
|
||||
if value in rename:
|
||||
node.input[index] = rename[value]
|
||||
if node.op_type == "Reshape":
|
||||
for attribute in node.attribute:
|
||||
if attribute.name == "allowzero":
|
||||
attribute.i = 0
|
||||
for value in graph.graph.output:
|
||||
if value.name in rename:
|
||||
value.name = rename[value.name]
|
||||
onnx.save(graph, str(path))
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
for name in ("model", "fixture", "long-reference", "onnx-output", "fixture-output",
|
||||
"eager-output", "ort-output", "report"):
|
||||
parser.add_argument(f"--{name}", type=Path, required=True)
|
||||
parser.add_argument("--chunk-frames", type=int, default=2)
|
||||
parser.add_argument("--context-frames", type=int, default=72)
|
||||
args = parser.parse_args()
|
||||
if args.chunk_frames <= 0 or args.context_frames != 72 or args.chunk_frames > 25:
|
||||
raise ValueError("this fixture supports 72 history frames and 1-25 new frames")
|
||||
with np.load(args.fixture, allow_pickle=False) as source:
|
||||
if source.files != ["quantized"]:
|
||||
raise ValueError("unexpected retained fixture")
|
||||
full_input = np.asarray(source["quantized"])
|
||||
if full_input.shape != (1, 512, 97) or full_input.dtype != np.float32:
|
||||
raise ValueError("retained vocoder fixture differs from expected shape/dtype")
|
||||
short_input = np.ascontiguousarray(full_input[:, :, : args.context_frames + args.chunk_frames])
|
||||
if not np.isfinite(short_input).all():
|
||||
raise ValueError("fixture contains nonfinite values")
|
||||
|
||||
decoder = load_code2wav_decoder(str(args.model))
|
||||
model = QuantizedWindowDecoder(decoder, args.chunk_frames).eval()
|
||||
with torch.inference_mode():
|
||||
eager = model(torch.from_numpy(short_input)).detach().numpy()
|
||||
expected_shape = (1, args.chunk_frames * model.hop)
|
||||
if eager.shape != expected_shape or not np.isfinite(eager).all():
|
||||
raise ValueError("eager short-window output violates contract")
|
||||
args.onnx_output.parent.mkdir(parents=True, exist_ok=True)
|
||||
started = time.perf_counter()
|
||||
program = torch.onnx.export(
|
||||
model, (torch.from_numpy(short_input),),
|
||||
input_names=["quantized"], output_names=["wav"],
|
||||
opset_version=17, dynamo=True, optimize=True,
|
||||
)
|
||||
program.save(str(args.onnx_output))
|
||||
strip_export_guards(args.onnx_output)
|
||||
export_s = time.perf_counter() - started
|
||||
exported_model = onnx.load(str(args.onnx_output), load_external_data=False)
|
||||
options = ort.SessionOptions()
|
||||
options.intra_op_num_threads = 4
|
||||
session = ort.InferenceSession(str(args.onnx_output), sess_options=options,
|
||||
providers=["CPUExecutionProvider"])
|
||||
observed = np.asarray(session.run(["wav"], {"quantized": short_input})[0])
|
||||
if observed.shape != expected_shape or not np.isfinite(observed).all():
|
||||
raise ValueError("ORT short-window output violates contract")
|
||||
with np.load(args.long_reference, allow_pickle=False) as reference:
|
||||
if reference.files != ["wav"] or reference["wav"].shape != (1, 48000):
|
||||
raise ValueError("long-window reference differs from retained CPU output")
|
||||
long_prefix = np.asarray(reference["wav"][:, : expected_shape[1]])
|
||||
for path, key, value in (
|
||||
(args.fixture_output, "quantized", short_input),
|
||||
(args.eager_output, "wav", eager),
|
||||
(args.ort_output, "wav", observed),
|
||||
):
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
np.savez_compressed(path, **{key: value})
|
||||
report = {
|
||||
"scope": "one synthetic first short vocoder window; no device execution or complete TTS stream",
|
||||
"model_snapshot": str(args.model.resolve()),
|
||||
"model_snapshot_revision": args.model.resolve().name,
|
||||
"model_weight_sha256": sha256(args.model / "speech_tokenizer" / "model.safetensors"),
|
||||
"torch_version": torch.__version__,
|
||||
"onnx_version": onnx.__version__,
|
||||
"onnxruntime_version": ort.__version__,
|
||||
"actual_opsets": {entry.domain or "ai.onnx": entry.version
|
||||
for entry in exported_model.opset_import},
|
||||
"source_fixture_sha256": sha256(args.fixture),
|
||||
"long_cpu_reference_sha256": sha256(args.long_reference),
|
||||
"context_frames": args.context_frames,
|
||||
"chunk_frames": args.chunk_frames,
|
||||
"input_shape": list(short_input.shape),
|
||||
"output_shape": list(expected_shape),
|
||||
"export_s_not_inference": export_s,
|
||||
"onnx_sha256": sha256(args.onnx_output),
|
||||
"short_fixture_sha256": sha256(args.fixture_output),
|
||||
"eager_output_sha256": sha256(args.eager_output),
|
||||
"ort_output_sha256": sha256(args.ort_output),
|
||||
"ort_vs_eager": compare(eager, observed),
|
||||
"short_eager_vs_25_frame_prefix": compare(long_prefix, eager),
|
||||
"limits": [
|
||||
"The short-window graph still requires its prior 72 quantized frames from a model adapter.",
|
||||
"Prefix agreement is tested on one retained synthetic fixture, not a speech-quality set.",
|
||||
"CPU export parity does not establish target compilation, placement or memory admission.",
|
||||
],
|
||||
}
|
||||
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({"ort_vs_eager": report["ort_vs_eager"],
|
||||
"short_vs_long": report["short_eager_vs_25_frame_prefix"]}, indent=2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Profile the pinned two-frame Code2Wav ONNX artifact on local ORT CPU."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import math
|
||||
import platform
|
||||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
import onnxruntime as ort
|
||||
import psutil
|
||||
|
||||
|
||||
def sha256(path: Path) -> str:
|
||||
with path.open("rb") as stream:
|
||||
return hashlib.file_digest(stream, "sha256").hexdigest()
|
||||
|
||||
|
||||
def rank(values: list[float], fraction: float) -> float:
|
||||
ordered = sorted(values)
|
||||
return ordered[math.ceil(fraction * len(ordered)) - 1]
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
for name in ("export-report", "model", "fixture", "reference-output", "report"):
|
||||
parser.add_argument(f"--{name}", type=Path, required=True)
|
||||
parser.add_argument("--threads", type=int, default=4)
|
||||
parser.add_argument("--warmups", type=int, default=1)
|
||||
parser.add_argument("--repeats", type=int, default=20)
|
||||
args = parser.parse_args()
|
||||
if args.threads < 1 or args.warmups < 1 or args.repeats < 20:
|
||||
raise ValueError("expected positive threads and at least one warmup / 20 samples")
|
||||
export = json.loads(args.export_report.read_text())
|
||||
if (sha256(args.model) != export["onnx_sha256"]
|
||||
or sha256(args.fixture) != export["short_fixture_sha256"]
|
||||
or sha256(args.reference_output) != export["ort_output_sha256"]):
|
||||
raise ValueError("model, fixture or reference differs from the audited export")
|
||||
with np.load(args.fixture, allow_pickle=False) as data:
|
||||
if data.files != ["quantized"]:
|
||||
raise ValueError("unexpected fixture schema")
|
||||
x = np.asarray(data["quantized"])
|
||||
with np.load(args.reference_output, allow_pickle=False) as data:
|
||||
if data.files != ["wav"]:
|
||||
raise ValueError("unexpected reference schema")
|
||||
reference = np.asarray(data["wav"])
|
||||
if x.shape != (1, 512, 74) or x.dtype != np.float32 or reference.shape != (1, 3840):
|
||||
raise ValueError("short-window tensor contract differs")
|
||||
options = ort.SessionOptions()
|
||||
options.intra_op_num_threads = args.threads
|
||||
started = time.perf_counter()
|
||||
session = ort.InferenceSession(str(args.model), sess_options=options,
|
||||
providers=["CPUExecutionProvider"])
|
||||
load_s = time.perf_counter() - started
|
||||
if session.get_providers() != ["CPUExecutionProvider"]:
|
||||
raise RuntimeError("the profile did not use ORT CPU")
|
||||
process = psutil.Process()
|
||||
loaded_rss = process.memory_info().rss
|
||||
samples: list[float] = []
|
||||
for index in range(args.warmups + args.repeats):
|
||||
started = time.perf_counter()
|
||||
output = np.asarray(session.run(["wav"], {"quantized": x})[0])
|
||||
elapsed = time.perf_counter() - started
|
||||
if output.shape != reference.shape or not np.isfinite(output).all():
|
||||
raise ValueError("profile output violates waveform contract")
|
||||
relative_l2 = float(np.linalg.norm((output - reference).astype(np.float64))
|
||||
/ np.linalg.norm(reference.astype(np.float64)))
|
||||
if relative_l2 > 1e-6:
|
||||
raise ValueError(f"profile output drifted from its own CPU reference: {relative_l2}")
|
||||
if index >= args.warmups:
|
||||
samples.append(elapsed)
|
||||
report = {
|
||||
"scope": "one fixed two-frame Code2Wav component on HX370 WSL ORT CPU; no complete TTS stream",
|
||||
"status": "component_cpu_profiled",
|
||||
"platform": platform.platform(),
|
||||
"cpu": next((line.split(":", 1)[1].strip()
|
||||
for line in Path("/proc/cpuinfo").read_text().splitlines()
|
||||
if line.startswith("model name")), platform.processor()),
|
||||
"python_version": sys.version.split()[0],
|
||||
"checkpoint_revision": export["model_snapshot_revision"],
|
||||
"power_condition": "not recorded",
|
||||
"ort_version": ort.__version__,
|
||||
"provider": session.get_providers(),
|
||||
"threads": args.threads,
|
||||
"model_sha256": export["onnx_sha256"],
|
||||
"fixture_sha256": export["short_fixture_sha256"],
|
||||
"load_s": load_s,
|
||||
"rss_after_load_bytes": loaded_rss,
|
||||
"warmups": args.warmups,
|
||||
"sample_count": len(samples),
|
||||
"samples_s": samples,
|
||||
"nearest_rank_p50_s": rank(samples, 0.5),
|
||||
"nearest_rank_p95_s": rank(samples, 0.95),
|
||||
"audio_duration_s": 3840 / 24000,
|
||||
"median_component_rtf": rank(samples, 0.5) / (3840 / 24000),
|
||||
"limits": [
|
||||
"The input is one retained synthetic window, and no talker or predictor ran.",
|
||||
"This host CPU timing cannot be transplanted to the S25 or another SoC.",
|
||||
],
|
||||
}
|
||||
args.report.parent.mkdir(parents=True, exist_ok=True)
|
||||
args.report.write_text(json.dumps(report, indent=2) + "\n")
|
||||
print(json.dumps({k: report[k] for k in
|
||||
("sample_count", "nearest_rank_p50_s", "nearest_rank_p95_s",
|
||||
"median_component_rtf")}, indent=2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Profile serial complete Spark BF16 text requests through the Omni CPU stage."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import asyncio
|
||||
import hashlib
|
||||
import json
|
||||
import math
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
from vllm_omni.edge.local.engine import LocalTextEngine
|
||||
from vllm_omni.edge.local.manifest import runtime_versions
|
||||
from vllm_omni.edge.local.plan import plan_text_session
|
||||
from vllm_omni.edge.local.prompts import acceptance_prompts
|
||||
|
||||
|
||||
def rank(values: list[float], fraction: float) -> float:
|
||||
ordered = sorted(values)
|
||||
return ordered[math.ceil(fraction * len(ordered)) - 1]
|
||||
|
||||
|
||||
async def profile(args: argparse.Namespace) -> dict:
|
||||
plan = plan_text_session(
|
||||
str(args.model), max_model_len=4096, max_num_seqs=1,
|
||||
max_num_batched_tokens=2048, enforce_eager=True,
|
||||
)
|
||||
if not plan.admitted or plan.selected is None or plan.selected.device_id != "cpu":
|
||||
raise RuntimeError("the pinned Spark BF16 run was not admitted on CPU")
|
||||
name, prompt = acceptance_prompts()[0]
|
||||
runs = []
|
||||
async with LocalTextEngine(plan) as engine:
|
||||
for index in range(args.warmups + args.repeats):
|
||||
session = engine.open_session()
|
||||
started = time.perf_counter()
|
||||
request_id, stream = await engine.submit(
|
||||
session, prompt, max_tokens=args.max_tokens,
|
||||
temperature=0.0, ignore_eos=True,
|
||||
)
|
||||
async for _ in stream:
|
||||
pass
|
||||
wall_s = time.perf_counter() - started
|
||||
record = engine.records[request_id]
|
||||
if record.error or record.cancelled or not record.finished or record.output_tokens != args.max_tokens:
|
||||
raise RuntimeError(f"request {index} did not complete the specified text workload")
|
||||
digest = hashlib.sha256(json.dumps(record.output_token_ids).encode()).hexdigest()
|
||||
runs.append({
|
||||
"kind": "warmup" if index < args.warmups else "measured",
|
||||
"prompt_name": name,
|
||||
"prompt_tokens": record.prompt_tokens,
|
||||
"output_tokens": record.output_tokens,
|
||||
"token_ids_sha256": digest,
|
||||
"wall_s": wall_s,
|
||||
"ttft_s": record.ttft_s,
|
||||
"decode_tok_per_s": record.decode_tok_per_s,
|
||||
"stream": stream.stats(),
|
||||
})
|
||||
engine.close_session(session.session_id)
|
||||
placement = engine.report_placement()
|
||||
usage = engine.report_usage()
|
||||
load_s = engine.load_seconds
|
||||
measured = runs[args.warmups:]
|
||||
if len({row["token_ids_sha256"] for row in runs}) != 1:
|
||||
raise RuntimeError("serial greedy requests produced different token sequences")
|
||||
report = {
|
||||
"scope": "Spark-X2.5-1.7B dense BF16 complete text requests through Omni on WSL HX370 CPU",
|
||||
"status": "scoped_e2e_profiled",
|
||||
"model": str(args.model.resolve()),
|
||||
"runtime": runtime_versions().to_dict(),
|
||||
"plan": plan.to_dict(),
|
||||
"placement": placement,
|
||||
"usage": usage,
|
||||
"load_s_not_request_timing": load_s,
|
||||
"warmup_count": args.warmups,
|
||||
"measured_count": args.repeats,
|
||||
"max_new_tokens": args.max_tokens,
|
||||
"runs": runs,
|
||||
"nearest_rank_p50_wall_s": rank([r["wall_s"] for r in measured], 0.5),
|
||||
"nearest_rank_p95_wall_s": rank([r["wall_s"] for r in measured], 0.95),
|
||||
"nearest_rank_p50_ttft_s": rank([r["ttft_s"] for r in measured], 0.5),
|
||||
"nearest_rank_p95_ttft_s": rank([r["ttft_s"] for r in measured], 0.95),
|
||||
"limits": [
|
||||
"One short prompt and one concurrency level; the acceptance and parity suites are separate evidence.",
|
||||
"The host power condition was not controlled or recorded as a sustained thermal test.",
|
||||
],
|
||||
}
|
||||
return report
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--model", type=Path, required=True)
|
||||
parser.add_argument("--report", type=Path, required=True)
|
||||
parser.add_argument("--warmups", type=int, default=1)
|
||||
parser.add_argument("--repeats", type=int, default=20)
|
||||
parser.add_argument("--max-tokens", type=int, default=64)
|
||||
args = parser.parse_args()
|
||||
if args.warmups < 1 or args.repeats < 20 or args.max_tokens < 1:
|
||||
parser.error("expected at least one warmup, 20 measured requests and positive token count")
|
||||
report = asyncio.run(profile(args))
|
||||
args.report.parent.mkdir(parents=True, exist_ok=True)
|
||||
args.report.write_text(json.dumps(report, indent=2) + "\n")
|
||||
print(json.dumps({key: report[key] for key in (
|
||||
"status", "measured_count", "nearest_rank_p50_wall_s", "nearest_rank_p95_wall_s",
|
||||
"nearest_rank_p50_ttft_s", "nearest_rank_p95_ttft_s",
|
||||
)}, indent=2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,5 +1,23 @@
|
||||
# 2026-09-24 Qualcomm component expansion
|
||||
|
||||
A separate [complete Spark 1.7B BF16 WSL CPU run](evidence/spark_bf16_wsl_cpu/README.md)
|
||||
now uses both verified upstream weight shards in the fork-branch Omni local text
|
||||
route. Twelve 128-token requests passed cancellation and exact greedy-token
|
||||
parity against standalone vLLM. One warmup plus 20 serial 64-token complete
|
||||
requests measured nearest-rank p50/p95 wall time **5.411/5.751 s** and
|
||||
TTFT **0.129/0.146 s** on HX370 WSL CPU. This qualifies the stated text
|
||||
workload only. A separate neighboring-checkout profile is retained in the
|
||||
evidence directory with its own provenance. A new [S25 two-frame Code2Wav candidate](evidence/qwen_tts_vocoder_qualcomm/s25/qnn_short_chunk/README.md)
|
||||
matched eager and ONNX CPU on one fixture, but its FP16 QNN DLC failed
|
||||
NPU-requested inference at the Workbench device-memory limit, just as the
|
||||
25-frame artifact did. Neither result is a complete mobile TTS stream.
|
||||
A [separate TFLite GPU-requested two-frame inference](evidence/qwen_tts_vocoder_qualcomm/s25/tflite_short_chunk/README.md)
|
||||
returned a finite unsaturated waveform at 2.325% relative L2 / 32.67 dB SNR
|
||||
against local ONNX CPU on the same fixture. Its 100-sample component p50/p95
|
||||
was **0.559/1.052 s** for 0.16 s audio, with 403 CPU and 335 GPU placement
|
||||
rows and a median component RTF of 3.49. Listening quality and playable
|
||||
complete-stream behavior remain open.
|
||||
|
||||
The [Qwen3-TTS vocoder study](evidence/qwen_tts_vocoder_qualcomm/README.md) reuses a retained fixed-shape Code2Wav export and historical Workbench input to test numerical behavior on SA8775P and other Qualcomm settings. The fresh SA8775P GPU-requested inference produces a saturated waveform, while the same binary's CPU-requested output on the exact SA device matches ONNX CPU within 4.13e-6 relative L2. Its 100-sample CPU-requested component profile had p50/p95 5.384/5.534 s with all 738 execution-detail rows on CPU. A FP32-preserving GPU-option control still saturated 84.89% of samples, so that option did not repair the tested path. RB3 GPU-requested execution produces an unsaturated but 15.73%-divergent waveform; its fresh 100-sample mixed CPU/GPU component p50/p95 was 3.099/3.133 s, not a usable TTS timing claim. On the exact RB3 device, the same binary requested on CPU matched original ONNX CPU within 4.13e-6 relative L2 on the retained fixture; its 47-sample component profile measured p50/p95 12.727/13.424 s with all 738 execution-detail rows on CPU. This is a major streaming-latency blocker. A single-fixture-calibrated RB3 INT8 QNN vocoder returned a finite but 66.93%-relative-L2 divergent waveform (3.49 dB SNR) versus ONNX CPU; its 100-sample component profile was p50/p95 1.971/1.992 s with all 728 execution-detail rows on NPU; these timings describe numerically unqualified audio. X Elite ONNX CPU output matches the local ONNX Runtime reference on the retained fixture; its 94-sample component p50/p95 was 6.384/6.644 s with all execution-detail rows on CPU. Corrected X Elite DirectML inference and profile both failed during provider initialization; separate FP16 QNN DLC inference returned an unsaturated waveform at 1.138% relative L2 / 38.88 dB SNR against original ONNX CPU; its placement profile timed out during QNN graph preparation without samples. A separate SA8775P FP16 QNN vocoder compile passed, but same-fixture NPU-requested inference failed after compilation without a waveform or placement samples. Fresh S24 and S25 CPU-requested TFLite vocoder inferences matched ONNX CPU within 4.04e-6 relative L2 on the retained fixture. S25 measured 100 component samples at p50/p95 4.418/4.641 s with all 738 execution-detail rows on CPU; S24 measured 100 at 4.826/4.958 s with all 738 rows on CPU. Separate explicit INT8 and W8A16 QDQ ONNX exports checked on local ORT CPU failed the same-fixture numerical gate at 246.97% and 331.83% waveform relative L2, respectively. S25 CPU talker inference preserved token 80 and its 100-sample component profile measured p50/p95 30.161/31.301 ms with all 1,800 rows on CPU. No complete on-device TTS stream or model-quality qualification is claimed.
|
||||
|
||||
A local HX370 x86-64 LiteRT CPU control of the identical SA/RB3 TFLite binary matched the original ONNX CPU waveform within 3.45e-6 relative L2. The SA saturation is therefore not universal to the converted artifact; the exact SA CPU control passed numerical and placement checks, while the faulty GPU delegate operation remains unidentified.
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ This is **one fixed-cache-bucket talker decode step**, not complete Qwen3-TTS ge
|
||||
|
||||
The deterministic synthetic input dataset `d7dw6pgy2` has SHA256 `0bf538e1b64dfc9737dc4f925d61c6e4ffa5075a5dcd7afb1e85ac3bd2d9afea`. A local ONNX Runtime 1.29 CPU reference output has SHA256 `ee0ead70e33c02c7d3d6bcb757c5cf0fcbb9eb6fc75c34abfbe8a4479657d5be`. The fixture exercises the stated tensor shapes, but does not represent a real text-to-speech request or establish token/audio quality.
|
||||
|
||||
Historical FP16 QNN context-binary [S24](s24/compile_report.json), [S25](s25/compile_report.json), [SA8775P](sa8775p/compile_report.json), and [Snapdragon X Elite](xelite/compile_report.json) compile jobs succeeded. Same-fixture NPU-requested inference succeeded on all four, but **all changed the CPU reference top-1 logit** on this synthetic step: CPU token 80 versus S24/SA/X Elite 1720 and S25 412. The [S24](s24/audit_report.json), [S25](s25/audit_report.json), [SA8775P](sa8775p/audit_report.json) and [X Elite](xelite/audit_report.json) audits report logits relative L2 **9.33%/8.99%/9.43%/8.57%**, respectively, with maximum K/V relative L2 **11.23%/11.71%/11.54%/11.50%**. These FP16 artifacts are numerically unqualified for this fixture; a successful graph execution is not speech-token parity. The [RB3 compile](rb3/compile_report.json) rejected floating-point input on this device. These are artifact-specific outcomes, not full-model support claims.
|
||||
Historical FP16 QNN context-binary [S24](s24/compile_report.json), [S25](s25/compile_report.json), [SA8775P](sa8775p/compile_report.json), and [Snapdragon X Elite](xelite/compile_report.json) compile jobs succeeded. Same-fixture NPU-requested inference succeeded on all four, but **all changed the CPU reference top-1 logit** on this synthetic step: CPU token 80 versus S24/SA/X Elite 1720 and S25 412. The [S24](s24/audit_report.json), [S25](s25/audit_report.json), [SA8775P](sa8775p/audit_report.json) and [X Elite](xelite/audit_report.json) audits report logits relative L2 **9.33%/8.99%/9.43%/8.57%**, respectively, with maximum K/V relative L2 **11.23%/11.71%/11.54%/11.50%**. These FP16 artifacts are numerically unqualified for this fixture; a successful graph execution is not speech-token parity. A separate [S25 FP16 QNN DLC compile](s25/qnn_fp16_dlc/compile_report.json) and [same-fixture inference](s25/qnn_fp16_dlc/inference_report.json) also executed, but the [audit](s25/qnn_fp16_dlc/audit_report.json) found 8.77% logits relative L2, 11.27% maximum new-cache relative L2 and token 1720 instead of CPU token 80. Changing from the historical context-binary conversion to this DLC artifact did not recover the numerical gate. The [RB3 compile](rb3/compile_report.json) rejected floating-point input on this device. These are artifact-specific outcomes, not full-model support claims.
|
||||
|
||||
Explicit [X Elite ONNX CPU](xelite/cpu_fallback/compile_report.json) and [SA8775P TFLite CPU](sa8775p/cpu_fallback/compile_report.json) fallback compiles succeeded from the same source. The same-fixture [X Elite CPU-requested inference](xelite/cpu_fallback/inference_report.json) succeeded. Its [audit](xelite/cpu_fallback/audit_report.json) found logits relative L2 2.07e-5, maximum new-K/V relative L2 2.18e-5, and preserved ONNX CPU top-1 speech token 80. The [CPU-requested placement profile](xelite/cpu_fallback/profile_report.json) returned 100 decode-step component samples at nearest-rank p50/p95 **191.414/309.428 ms**, with all **1,744 execution-detail rows on CPU**. The 142.921 ms estimated-time field is the sample minimum; reported inference peak memory was 1,928,019,968 bytes. The [SA8775P TFLite CPU-requested inference](sa8775p/cpu_fallback/inference_report.json) also succeeded. Its [audit](sa8775p/cpu_fallback/audit_report.json) found logits relative L2 3.33e-5, maximum new-K/V relative L2 3.41e-5, and preserved CPU top-1 speech token 80. The [CPU-requested placement profile](sa8775p/cpu_fallback/profile_report.json) returned 100 decode-step component samples at nearest-rank p50/p95 **52.635/76.925 ms**, with all **1,800 execution-detail rows on CPU**. The 45.688 ms estimated-time field is the sample minimum; reported inference peak memory was 1,913,794,560 bytes. Both explicit CPU routes are numerically close on one decode step, not complete talker loops or TTS deployments.
|
||||
|
||||
|
||||
+401
@@ -0,0 +1,401 @@
|
||||
{
|
||||
"scope": "one synthetic fixed-cache 28-layer Qwen3-TTS talker decode step; no complete TTS stream",
|
||||
"status": "component_executed_numeric_measured",
|
||||
"device": {
|
||||
"name": "Samsung Galaxy S25",
|
||||
"os": "15",
|
||||
"attributes": [
|
||||
"os:android",
|
||||
"framework:tflite",
|
||||
"framework:onnx",
|
||||
"abi:aarch64-android",
|
||||
"vendor:samsung",
|
||||
"format:phone",
|
||||
"chipset:qualcomm-snapdragon-8-elite-for-galaxy",
|
||||
"chipset:sm8750-ac",
|
||||
"hexagon:v79",
|
||||
"soc-model:69",
|
||||
"htp-supports-fp16:true",
|
||||
"htp-supports-weight-sharing:true",
|
||||
"framework:qnn"
|
||||
]
|
||||
},
|
||||
"compile_job_id": "jgolry1kg",
|
||||
"inference_job_id": "jg9zmv98p",
|
||||
"source_model_id": "mq3xre4rq",
|
||||
"target_model_id": "mnlzdl4oq",
|
||||
"input_dataset_id": "d7dw6pgy2",
|
||||
"requested_run_options": "--compute_unit npu",
|
||||
"files": {
|
||||
"source_onnx": {
|
||||
"bytes": 1776377476,
|
||||
"sha256": "41feb08517678e94d9301e992d0df610fc60e7c9faba5600703298c86554fd22"
|
||||
},
|
||||
"fixture": {
|
||||
"bytes": 54591500,
|
||||
"sha256": "0bf538e1b64dfc9737dc4f925d61c6e4ffa5075a5dcd7afb1e85ac3bd2d9afea"
|
||||
},
|
||||
"cpu_reference": {
|
||||
"bytes": 237615,
|
||||
"sha256": "ee0ead70e33c02c7d3d6bcb757c5cf0fcbb9eb6fc75c34abfbe8a4479657d5be"
|
||||
},
|
||||
"device_output": {
|
||||
"bytes": 168000,
|
||||
"sha256": "f836e59cd2572556a9b6c0092fa244a4f46a408442643e53c60e9a4093602c5e"
|
||||
}
|
||||
},
|
||||
"tensor_comparison": {
|
||||
"logits": {
|
||||
"relative_l2": 0.0876850526212223,
|
||||
"max_abs_error": 1.3075941801071167,
|
||||
"reference_rms": 3.7322664515389006,
|
||||
"output_rms": 3.754969774544142,
|
||||
"cpu_top1": 80,
|
||||
"device_top1": 1720,
|
||||
"top1_matches": false
|
||||
},
|
||||
"k_new_0": {
|
||||
"relative_l2": 0.0005230155784396237,
|
||||
"max_abs_error": 0.0037479400634765625,
|
||||
"reference_rms": 1.1349352034374294,
|
||||
"output_rms": 1.1348859231876618
|
||||
},
|
||||
"v_new_0": {
|
||||
"relative_l2": 0.000362212102381853,
|
||||
"max_abs_error": 0.00020900368690490723,
|
||||
"reference_rms": 0.1383137764927112,
|
||||
"output_rms": 0.1383144368591086
|
||||
},
|
||||
"k_new_1": {
|
||||
"relative_l2": 0.001540598700847705,
|
||||
"max_abs_error": 0.0086439847946167,
|
||||
"reference_rms": 1.4773734279001252,
|
||||
"output_rms": 1.4772890926361812
|
||||
},
|
||||
"v_new_1": {
|
||||
"relative_l2": 0.0015613755499334814,
|
||||
"max_abs_error": 0.0009385757148265839,
|
||||
"reference_rms": 0.162893856079411,
|
||||
"output_rms": 0.16291330617946456
|
||||
},
|
||||
"k_new_2": {
|
||||
"relative_l2": 0.002761054571015776,
|
||||
"max_abs_error": 0.020048856735229492,
|
||||
"reference_rms": 1.4749251890370425,
|
||||
"output_rms": 1.4749432597408292
|
||||
},
|
||||
"v_new_2": {
|
||||
"relative_l2": 0.003124315994655873,
|
||||
"max_abs_error": 0.003032371401786804,
|
||||
"reference_rms": 0.2996575863196337,
|
||||
"output_rms": 0.29957990625185127
|
||||
},
|
||||
"k_new_3": {
|
||||
"relative_l2": 0.004821709696188454,
|
||||
"max_abs_error": 0.03383982181549072,
|
||||
"reference_rms": 1.4529848472712377,
|
||||
"output_rms": 1.4528154889915204
|
||||
},
|
||||
"v_new_3": {
|
||||
"relative_l2": 0.004771549667840103,
|
||||
"max_abs_error": 0.00476527214050293,
|
||||
"reference_rms": 0.2917197159228712,
|
||||
"output_rms": 0.2914876080010164
|
||||
},
|
||||
"k_new_4": {
|
||||
"relative_l2": 0.005449794208301409,
|
||||
"max_abs_error": 0.04018670320510864,
|
||||
"reference_rms": 1.5413980317857385,
|
||||
"output_rms": 1.5416838528549397
|
||||
},
|
||||
"v_new_4": {
|
||||
"relative_l2": 0.0077393775088357925,
|
||||
"max_abs_error": 0.015972793102264404,
|
||||
"reference_rms": 0.41222657123793377,
|
||||
"output_rms": 0.41124714948666696
|
||||
},
|
||||
"k_new_5": {
|
||||
"relative_l2": 0.006980911986420664,
|
||||
"max_abs_error": 0.051262855529785156,
|
||||
"reference_rms": 1.6285454176549035,
|
||||
"output_rms": 1.6284136449722517
|
||||
},
|
||||
"v_new_5": {
|
||||
"relative_l2": 0.008944790284710817,
|
||||
"max_abs_error": 0.010748535394668579,
|
||||
"reference_rms": 0.32638470026742417,
|
||||
"output_rms": 0.3260101745890208
|
||||
},
|
||||
"k_new_6": {
|
||||
"relative_l2": 0.009914561650426496,
|
||||
"max_abs_error": 0.10113561153411865,
|
||||
"reference_rms": 1.8000231156167423,
|
||||
"output_rms": 1.8004348379922543
|
||||
},
|
||||
"v_new_6": {
|
||||
"relative_l2": 0.011895405889581826,
|
||||
"max_abs_error": 0.013239093124866486,
|
||||
"reference_rms": 0.2629708328253682,
|
||||
"output_rms": 0.26272664367887155
|
||||
},
|
||||
"k_new_7": {
|
||||
"relative_l2": 0.011574984331246546,
|
||||
"max_abs_error": 0.18203949928283691,
|
||||
"reference_rms": 1.6255722851184644,
|
||||
"output_rms": 1.6256887782660017
|
||||
},
|
||||
"v_new_7": {
|
||||
"relative_l2": 0.01222879669226326,
|
||||
"max_abs_error": 0.018638402223587036,
|
||||
"reference_rms": 0.348368074126628,
|
||||
"output_rms": 0.3482941115788742
|
||||
},
|
||||
"k_new_8": {
|
||||
"relative_l2": 0.013421898308530838,
|
||||
"max_abs_error": 0.09088659286499023,
|
||||
"reference_rms": 1.516512353065435,
|
||||
"output_rms": 1.5161715614768887
|
||||
},
|
||||
"v_new_8": {
|
||||
"relative_l2": 0.013888393822759375,
|
||||
"max_abs_error": 0.01586216688156128,
|
||||
"reference_rms": 0.28027916002007797,
|
||||
"output_rms": 0.2806169285825688
|
||||
},
|
||||
"k_new_9": {
|
||||
"relative_l2": 0.015263377070499391,
|
||||
"max_abs_error": 0.10664939880371094,
|
||||
"reference_rms": 1.5960043895576705,
|
||||
"output_rms": 1.5967548122383879
|
||||
},
|
||||
"v_new_9": {
|
||||
"relative_l2": 0.019649029067684943,
|
||||
"max_abs_error": 0.024999573826789856,
|
||||
"reference_rms": 0.37541008682864946,
|
||||
"output_rms": 0.3752565042185322
|
||||
},
|
||||
"k_new_10": {
|
||||
"relative_l2": 0.020560530259558635,
|
||||
"max_abs_error": 0.15616607666015625,
|
||||
"reference_rms": 1.6561161468173449,
|
||||
"output_rms": 1.6555065727672071
|
||||
},
|
||||
"v_new_10": {
|
||||
"relative_l2": 0.028246579911853437,
|
||||
"max_abs_error": 0.033145904541015625,
|
||||
"reference_rms": 0.26429778504066537,
|
||||
"output_rms": 0.2649298588657518
|
||||
},
|
||||
"k_new_11": {
|
||||
"relative_l2": 0.024226437534041585,
|
||||
"max_abs_error": 0.14327839016914368,
|
||||
"reference_rms": 1.5170462775366995,
|
||||
"output_rms": 1.5164443227984858
|
||||
},
|
||||
"v_new_11": {
|
||||
"relative_l2": 0.032821000942314556,
|
||||
"max_abs_error": 0.026863843202590942,
|
||||
"reference_rms": 0.22548908846990579,
|
||||
"output_rms": 0.22610859225044458
|
||||
},
|
||||
"k_new_12": {
|
||||
"relative_l2": 0.02424459703399902,
|
||||
"max_abs_error": 0.13305354118347168,
|
||||
"reference_rms": 1.5731131793440647,
|
||||
"output_rms": 1.5728852520114331
|
||||
},
|
||||
"v_new_12": {
|
||||
"relative_l2": 0.03151381616847344,
|
||||
"max_abs_error": 0.02252097614109516,
|
||||
"reference_rms": 0.20839677682266325,
|
||||
"output_rms": 0.20901723170338624
|
||||
},
|
||||
"k_new_13": {
|
||||
"relative_l2": 0.02684749384011855,
|
||||
"max_abs_error": 0.17472481727600098,
|
||||
"reference_rms": 1.4939452330557514,
|
||||
"output_rms": 1.4929511567426517
|
||||
},
|
||||
"v_new_13": {
|
||||
"relative_l2": 0.0348100900904329,
|
||||
"max_abs_error": 0.028251543641090393,
|
||||
"reference_rms": 0.24929462665621008,
|
||||
"output_rms": 0.2498725455988227
|
||||
},
|
||||
"k_new_14": {
|
||||
"relative_l2": 0.02791923833069605,
|
||||
"max_abs_error": 0.15481090545654297,
|
||||
"reference_rms": 1.4942429579997731,
|
||||
"output_rms": 1.494004847658895
|
||||
},
|
||||
"v_new_14": {
|
||||
"relative_l2": 0.041331563093406604,
|
||||
"max_abs_error": 0.04944309592247009,
|
||||
"reference_rms": 0.32824019866053383,
|
||||
"output_rms": 0.3295947163282871
|
||||
},
|
||||
"k_new_15": {
|
||||
"relative_l2": 0.032452521516218184,
|
||||
"max_abs_error": 0.19741547107696533,
|
||||
"reference_rms": 1.6561072116211841,
|
||||
"output_rms": 1.6551009838057842
|
||||
},
|
||||
"v_new_15": {
|
||||
"relative_l2": 0.0466727113355849,
|
||||
"max_abs_error": 0.03767561912536621,
|
||||
"reference_rms": 0.24976283574047556,
|
||||
"output_rms": 0.25253061223199835
|
||||
},
|
||||
"k_new_16": {
|
||||
"relative_l2": 0.04171664506917453,
|
||||
"max_abs_error": 0.2883577346801758,
|
||||
"reference_rms": 1.617983543941328,
|
||||
"output_rms": 1.6163302517820928
|
||||
},
|
||||
"v_new_16": {
|
||||
"relative_l2": 0.05475395691907811,
|
||||
"max_abs_error": 0.0824914276599884,
|
||||
"reference_rms": 0.3826095020438836,
|
||||
"output_rms": 0.38613193762350373
|
||||
},
|
||||
"k_new_17": {
|
||||
"relative_l2": 0.056294548186683446,
|
||||
"max_abs_error": 0.4603831171989441,
|
||||
"reference_rms": 1.6828817809060599,
|
||||
"output_rms": 1.6835371322893817
|
||||
},
|
||||
"v_new_17": {
|
||||
"relative_l2": 0.06025778430481221,
|
||||
"max_abs_error": 0.10319685935974121,
|
||||
"reference_rms": 0.4656876133547257,
|
||||
"output_rms": 0.4675643428477375
|
||||
},
|
||||
"k_new_18": {
|
||||
"relative_l2": 0.06067033637299982,
|
||||
"max_abs_error": 0.4243013858795166,
|
||||
"reference_rms": 1.5546463592216835,
|
||||
"output_rms": 1.5533939819606717
|
||||
},
|
||||
"v_new_18": {
|
||||
"relative_l2": 0.06991244010967108,
|
||||
"max_abs_error": 0.11277598142623901,
|
||||
"reference_rms": 0.5200020604619255,
|
||||
"output_rms": 0.5222859980551071
|
||||
},
|
||||
"k_new_19": {
|
||||
"relative_l2": 0.0641229525559854,
|
||||
"max_abs_error": 0.3378424644470215,
|
||||
"reference_rms": 1.5217070844504548,
|
||||
"output_rms": 1.5200443294471528
|
||||
},
|
||||
"v_new_19": {
|
||||
"relative_l2": 0.07749365505892926,
|
||||
"max_abs_error": 0.1699829399585724,
|
||||
"reference_rms": 0.5402920798790236,
|
||||
"output_rms": 0.5445328063931953
|
||||
},
|
||||
"k_new_20": {
|
||||
"relative_l2": 0.07900454500371618,
|
||||
"max_abs_error": 0.7018804550170898,
|
||||
"reference_rms": 1.6813854859968058,
|
||||
"output_rms": 1.681353760733933
|
||||
},
|
||||
"v_new_20": {
|
||||
"relative_l2": 0.0893259005949654,
|
||||
"max_abs_error": 0.16725420951843262,
|
||||
"reference_rms": 0.6088730895277438,
|
||||
"output_rms": 0.6087740268479712
|
||||
},
|
||||
"k_new_21": {
|
||||
"relative_l2": 0.07482362765411124,
|
||||
"max_abs_error": 0.6752438545227051,
|
||||
"reference_rms": 1.7370493419005983,
|
||||
"output_rms": 1.7330445579916067
|
||||
},
|
||||
"v_new_21": {
|
||||
"relative_l2": 0.09334181609757561,
|
||||
"max_abs_error": 0.2183903455734253,
|
||||
"reference_rms": 0.6072011016139925,
|
||||
"output_rms": 0.607087366794611
|
||||
},
|
||||
"k_new_22": {
|
||||
"relative_l2": 0.08617285484739436,
|
||||
"max_abs_error": 0.9095754623413086,
|
||||
"reference_rms": 1.9661056736696203,
|
||||
"output_rms": 1.9646358442896732
|
||||
},
|
||||
"v_new_22": {
|
||||
"relative_l2": 0.0960272875256176,
|
||||
"max_abs_error": 0.2511986494064331,
|
||||
"reference_rms": 0.7362191931025958,
|
||||
"output_rms": 0.737060867326014
|
||||
},
|
||||
"k_new_23": {
|
||||
"relative_l2": 0.09015898262872088,
|
||||
"max_abs_error": 0.6080676317214966,
|
||||
"reference_rms": 1.6005997999291703,
|
||||
"output_rms": 1.5959975427626747
|
||||
},
|
||||
"v_new_23": {
|
||||
"relative_l2": 0.1097689271525209,
|
||||
"max_abs_error": 0.3053623288869858,
|
||||
"reference_rms": 0.6675198669572269,
|
||||
"output_rms": 0.6584432008476448
|
||||
},
|
||||
"k_new_24": {
|
||||
"relative_l2": 0.08953121158633887,
|
||||
"max_abs_error": 0.6620829105377197,
|
||||
"reference_rms": 1.6337684549178757,
|
||||
"output_rms": 1.6408286721000613
|
||||
},
|
||||
"v_new_24": {
|
||||
"relative_l2": 0.11272639051542711,
|
||||
"max_abs_error": 0.23123958706855774,
|
||||
"reference_rms": 0.6240472225015637,
|
||||
"output_rms": 0.6254292367718036
|
||||
},
|
||||
"k_new_25": {
|
||||
"relative_l2": 0.07944159313144433,
|
||||
"max_abs_error": 0.43733835220336914,
|
||||
"reference_rms": 1.527601662385539,
|
||||
"output_rms": 1.5323928692984328
|
||||
},
|
||||
"v_new_25": {
|
||||
"relative_l2": 0.10095419365698416,
|
||||
"max_abs_error": 0.3811544179916382,
|
||||
"reference_rms": 0.9133071626950193,
|
||||
"output_rms": 0.9081464219762729
|
||||
},
|
||||
"k_new_26": {
|
||||
"relative_l2": 0.07294061710221367,
|
||||
"max_abs_error": 0.4177415370941162,
|
||||
"reference_rms": 1.4905787414732559,
|
||||
"output_rms": 1.4929379627971777
|
||||
},
|
||||
"v_new_26": {
|
||||
"relative_l2": 0.11269209239312523,
|
||||
"max_abs_error": 0.25589676201343536,
|
||||
"reference_rms": 0.7009595279765859,
|
||||
"output_rms": 0.7040098493200752
|
||||
},
|
||||
"k_new_27": {
|
||||
"relative_l2": 0.09138018211515632,
|
||||
"max_abs_error": 0.5336480140686035,
|
||||
"reference_rms": 1.5453936433107067,
|
||||
"output_rms": 1.5465945575535849
|
||||
},
|
||||
"v_new_27": {
|
||||
"relative_l2": 0.09594949828965257,
|
||||
"max_abs_error": 0.25312620401382446,
|
||||
"reference_rms": 0.6731545154533489,
|
||||
"output_rms": 0.6815830406876052
|
||||
}
|
||||
},
|
||||
"cache_max_relative_l2": 0.11272639051542711,
|
||||
"limits": [
|
||||
"The historical source export does not attest an exact checkpoint revision.",
|
||||
"The fixture is synthetic and has no token-to-audio quality tolerance.",
|
||||
"No predictor, vocoder, persistent cache loop or complete TTS stream was tested.",
|
||||
"Requested compute unit is not actual placement without a device profile."
|
||||
]
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"timestamp_utc": "2026-09-24T04:44:26.190951+00:00",
|
||||
"qai_hub_version": "0.55.0",
|
||||
"facility": "Qualcomm AI Hub Workbench",
|
||||
"job_id": "jgolry1kg",
|
||||
"url": "https://workbench.aihub.qualcomm.com/jobs/jgolry1kg/",
|
||||
"status": "SUCCESS",
|
||||
"status_message": "",
|
||||
"options": "--target_runtime qnn_dlc --qnn_options default_graph_htp_precision=FLOAT16",
|
||||
"hub_version": "aihub-2026.09.11.0",
|
||||
"device": {
|
||||
"name": "Samsung Galaxy S25",
|
||||
"os": "15",
|
||||
"attributes": [
|
||||
"os:android",
|
||||
"framework:tflite",
|
||||
"framework:onnx",
|
||||
"abi:aarch64-android",
|
||||
"vendor:samsung",
|
||||
"format:phone",
|
||||
"chipset:qualcomm-snapdragon-8-elite-for-galaxy",
|
||||
"chipset:sm8750-ac",
|
||||
"hexagon:v79",
|
||||
"soc-model:69",
|
||||
"htp-supports-fp16:true",
|
||||
"htp-supports-weight-sharing:true",
|
||||
"framework:qnn"
|
||||
]
|
||||
},
|
||||
"source_model_id": "mq3xre4rq",
|
||||
"target_model_id": "mnlzdl4oq"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"timestamp_utc": "2026-09-24T04:40:12.164649+00:00",
|
||||
"facility": "Qualcomm AI Hub Workbench",
|
||||
"qai_hub_version": "0.55.0",
|
||||
"source_model_id": "mq3xre4rq",
|
||||
"device": "Samsung Galaxy S25",
|
||||
"options": "--target_runtime qnn_dlc --qnn_options default_graph_htp_precision=FLOAT16",
|
||||
"kind": "compile",
|
||||
"status": "SUBMITTED",
|
||||
"job_id": "jgolry1kg",
|
||||
"url": "https://workbench.aihub.qualcomm.com/jobs/jgolry1kg/"
|
||||
}
|
||||
BIN
Binary file not shown.
+33
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"timestamp_utc": "2026-09-24T04:51:05.518616+00:00",
|
||||
"qai_hub_version": "0.55.0",
|
||||
"facility": "Qualcomm AI Hub Workbench",
|
||||
"job_id": "jg9zmv98p",
|
||||
"url": "https://workbench.aihub.qualcomm.com/jobs/jg9zmv98p/",
|
||||
"status": "SUCCESS",
|
||||
"status_message": "",
|
||||
"options": "--compute_unit npu",
|
||||
"hub_version": "aihub-2026.09.11.0",
|
||||
"device": {
|
||||
"name": "Samsung Galaxy S25",
|
||||
"os": "15",
|
||||
"attributes": [
|
||||
"os:android",
|
||||
"framework:tflite",
|
||||
"framework:onnx",
|
||||
"abi:aarch64-android",
|
||||
"vendor:samsung",
|
||||
"format:phone",
|
||||
"chipset:qualcomm-snapdragon-8-elite-for-galaxy",
|
||||
"chipset:sm8750-ac",
|
||||
"hexagon:v79",
|
||||
"soc-model:69",
|
||||
"htp-supports-fp16:true",
|
||||
"htp-supports-weight-sharing:true",
|
||||
"framework:qnn"
|
||||
]
|
||||
},
|
||||
"model_id": "mnlzdl4oq",
|
||||
"input_dataset_id": "d7dw6pgy2",
|
||||
"outputs": "device_output.npz"
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"timestamp_utc": "2026-09-24T04:44:41.995200+00:00",
|
||||
"facility": "Qualcomm AI Hub Workbench",
|
||||
"qai_hub_version": "0.55.0",
|
||||
"model_id": "mnlzdl4oq",
|
||||
"input_dataset_id": "d7dw6pgy2",
|
||||
"device": "Samsung Galaxy S25",
|
||||
"options": "--compute_unit npu",
|
||||
"kind": "inference",
|
||||
"status": "SUBMITTED",
|
||||
"job_id": "jg9zmv98p",
|
||||
"url": "https://workbench.aihub.qualcomm.com/jobs/jg9zmv98p/"
|
||||
}
|
||||
+3
-1
@@ -2,11 +2,13 @@
|
||||
|
||||
**The retained Qwen3-TTS Code2Wav export does not yet have a numerically qualified SA8775P or RB3 GPU path.** A fresh inference on the exact hosted SA8775P ADP returned a severely saturated waveform on the same input for which original ONNX Runtime CPU and prior S25 GPU outputs remained unsaturated. RB3 produced an unsaturated but divergent GPU-requested waveform. Explicit CPU routes on both devices matched the original ONNX CPU waveform and passed node-placement profiling, but their measured vocoder latency remains a complete-stream concern.
|
||||
|
||||
A new [two-frame S25 export](s25/qnn_short_chunk/README.md) preserves 72 history frames and locally matches the eager decoder at 2.96e-6 relative L2 on one fixture. Its FP16 QNN DLC failed NPU-requested inference at Workbench's reported memory limit. A [TFLite GPU-requested version](s25/tflite_short_chunk/README.md) returned a finite waveform at 2.325% relative L2 versus local ONNX CPU; 100 component samples measured p50/p95 0.559/1.052 s for 0.16 s of audio, with 403 CPU and 335 GPU placement rows. This mixed route has median component RTF 3.49 and no listening-quality pass or complete stream.
|
||||
|
||||
The historical Workbench source model `mqyer339n` is a 423,655,047-byte ONNX graph with one FP32 input `[1,512,97]` and one 48,000-sample output. The [manifest](artifact_manifest.json) pins its SHA256, the retained Workbench fixture dataset `d7m80jl32`, a local ONNX Runtime 1.29 CPU output, compiled target downloads, and the prior [S25 GPU output](s25_reference_output.npz). The source export script identifies the Qwen3-TTS 0.6B CustomVoice model family, but did not attest the exact checkpoint revision; these results must not be promoted to a revision-qualified release claim. Large source/target artifacts and the fixture remain outside Git under `/home/zhout/project/edge_infer/models/`.
|
||||
|
||||
The [S25 historical inference](s25_reference_inference.json) on the same fixture differed from local FP32 ONNX CPU by **4.24% relative L2 / 27.46 dB SNR** ([comparison](s25_cpu_comparison.json)); that waveform has no listening-quality tolerance. A fresh [SA8775P inference](sa8775p/inference_report.json) used historical compiled TFLite model `mnze95don` and requested GPU. Its [output](sa8775p/device_output.npz) had **96.63%** of samples at absolute amplitude at least 0.999, RMS **0.989** versus CPU **0.0837**, relative L2 **11.832**, and SNR **−21.46 dB**. The fresh [profile](sa8775p/profile_report.json) attributed 403 execution-detail rows to CPU and 335 to GPU; 100 component samples had nearest-rank p50/p95 **1.776/1.880 s** (minimum 1.675 s). The [audit](sa8775p/audit_report.json) pins all output hashes, waveform differences and placement. This is measured execution of a **numerically failed** output, not a usable TTS performance result. The [SA8775P compile record](sa8775p/compile_report.json) pins the artifact and source IDs.
|
||||
|
||||
The S25 target's [historical producer job](s25/cpu_control/compile_report.json) was recovered from the exact compiled model used above. A new [CPU-requested inference](s25/cpu_control/inference_report.json) of that same target and fixture returned a finite unsaturated waveform at **4.04e-6 relative L2 / 107.86 dB SNR** versus original ONNX CPU. Its [placement profile](s25/cpu_control/profile_report.json) returned **100** component samples at nearest-rank p50/p95 **4.418/4.641 s**, with all **738 execution-detail rows on CPU** and reported inference peak memory **867,893,248 bytes**. The 2.585 s estimated-time field is the sample minimum. The [full audit](s25/cpu_control/audit_report.json) binds the numerical output, exact historical target and placement. This is a numerically matching component CPU route, not a playable complete stream.
|
||||
The S25 target's [historical producer job](s25/cpu_control/compile_report.json) was recovered from the exact compiled model used above. A new [CPU-requested inference](s25/cpu_control/inference_report.json) of that same target and fixture returned a finite unsaturated waveform at **4.04e-6 relative L2 / 107.86 dB SNR** versus original ONNX CPU. Its [placement profile](s25/cpu_control/profile_report.json) returned **100** component samples at nearest-rank p50/p95 **4.418/4.641 s**, with all **738 execution-detail rows on CPU** and reported inference peak memory **867,893,248 bytes**. The 2.585 s estimated-time field is the sample minimum. The [full audit](s25/cpu_control/audit_report.json) binds the numerical output, exact historical target and placement. This is a numerically matching component CPU route, not a playable complete stream. A separate [S25 FP16 QNN DLC compile](s25/qnn_fp16/compile_report.json) succeeded, but its [NPU-requested inference](s25/qnn_fp16/inference_report.json) failed with Workbench reporting that model memory usage exceeded device limits. No waveform or placement samples were returned; the [runtime log](s25/qnn_fp16/logs/jprl0k47p_runtime.log.gz) is retained. This is a failure of this fixed 97-frame FP16 artifact on the hosted S25, not a general S25 NPU impossibility.
|
||||
|
||||
A matching [S24 TFLite CPU fallback compile](s24/cpu_fallback/compile_report.json) succeeded from the same ONNX source. Its [same-fixture CPU-requested inference](s24/cpu_fallback/inference_report.json) returned a finite unsaturated waveform at **4.04e-6 relative L2 / 107.86 dB SNR** versus original ONNX CPU. The [placement profile](s24/cpu_fallback/profile_report.json) returned **100** component samples at nearest-rank p50/p95 **4.826/4.958 s**, with all **738 execution-detail rows on CPU** and reported inference peak memory **851,140,608 bytes**. The 3.583 s estimated-time field is the sample minimum. The [full audit](s24/cpu_fallback/audit_report.json) binds output and placement. This is a numerically matching component route, not a complete playable TTS stream.
|
||||
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"timestamp_utc": "2026-09-24T04:42:29.587601+00:00",
|
||||
"qai_hub_version": "0.55.0",
|
||||
"facility": "Qualcomm AI Hub Workbench",
|
||||
"job_id": "jp3z9k4n5",
|
||||
"url": "https://workbench.aihub.qualcomm.com/jobs/jp3z9k4n5/",
|
||||
"status": "SUCCESS",
|
||||
"status_message": "",
|
||||
"options": "--target_runtime qnn_dlc --qnn_options default_graph_htp_precision=FLOAT16",
|
||||
"hub_version": "aihub-2026.09.11.0",
|
||||
"device": {
|
||||
"name": "Samsung Galaxy S25",
|
||||
"os": "15",
|
||||
"attributes": [
|
||||
"os:android",
|
||||
"framework:tflite",
|
||||
"framework:onnx",
|
||||
"abi:aarch64-android",
|
||||
"vendor:samsung",
|
||||
"format:phone",
|
||||
"chipset:qualcomm-snapdragon-8-elite-for-galaxy",
|
||||
"chipset:sm8750-ac",
|
||||
"hexagon:v79",
|
||||
"soc-model:69",
|
||||
"htp-supports-fp16:true",
|
||||
"htp-supports-weight-sharing:true",
|
||||
"framework:qnn"
|
||||
]
|
||||
},
|
||||
"source_model_id": "mqyer339n",
|
||||
"target_model_id": "mmxjy0wyq"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"timestamp_utc": "2026-09-24T04:39:03.317101+00:00",
|
||||
"facility": "Qualcomm AI Hub Workbench",
|
||||
"qai_hub_version": "0.55.0",
|
||||
"source_model_id": "mqyer339n",
|
||||
"device": "Samsung Galaxy S25",
|
||||
"options": "--target_runtime qnn_dlc --qnn_options default_graph_htp_precision=FLOAT16",
|
||||
"kind": "compile",
|
||||
"status": "SUBMITTED",
|
||||
"job_id": "jp3z9k4n5",
|
||||
"url": "https://workbench.aihub.qualcomm.com/jobs/jp3z9k4n5/"
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"timestamp_utc": "2026-09-24T04:48:26.595547+00:00",
|
||||
"qai_hub_version": "0.55.0",
|
||||
"facility": "Qualcomm AI Hub Workbench",
|
||||
"job_id": "jprl0k47p",
|
||||
"url": "https://workbench.aihub.qualcomm.com/jobs/jprl0k47p/",
|
||||
"status": "FAILED",
|
||||
"status_message": "Failed to profile the model because memory usage exceeded device limits.",
|
||||
"options": "--compute_unit npu",
|
||||
"hub_version": "aihub-2026.09.11.0",
|
||||
"device": {
|
||||
"name": "Samsung Galaxy S25",
|
||||
"os": "15",
|
||||
"attributes": [
|
||||
"os:android",
|
||||
"framework:tflite",
|
||||
"framework:onnx",
|
||||
"abi:aarch64-android",
|
||||
"vendor:samsung",
|
||||
"format:phone",
|
||||
"chipset:qualcomm-snapdragon-8-elite-for-galaxy",
|
||||
"chipset:sm8750-ac",
|
||||
"hexagon:v79",
|
||||
"soc-model:69",
|
||||
"htp-supports-fp16:true",
|
||||
"htp-supports-weight-sharing:true",
|
||||
"framework:qnn"
|
||||
]
|
||||
},
|
||||
"model_id": "mmxjy0wyq",
|
||||
"input_dataset_id": "d7m80jl32"
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"timestamp_utc": "2026-09-24T04:42:48.493125+00:00",
|
||||
"facility": "Qualcomm AI Hub Workbench",
|
||||
"qai_hub_version": "0.55.0",
|
||||
"model_id": "mmxjy0wyq",
|
||||
"input_dataset_id": "d7m80jl32",
|
||||
"device": "Samsung Galaxy S25",
|
||||
"options": "--compute_unit npu",
|
||||
"kind": "inference",
|
||||
"status": "SUBMITTED",
|
||||
"job_id": "jprl0k47p",
|
||||
"url": "https://workbench.aihub.qualcomm.com/jobs/jprl0k47p/"
|
||||
}
|
||||
BIN
Binary file not shown.
+38
@@ -0,0 +1,38 @@
|
||||
# Two-frame S25 Code2Wav candidate
|
||||
|
||||
The original 25-frame vocoder graph takes 72 prior frames plus 25 new frames
|
||||
and produced a 48,000-sample waveform. Its FP16 QNN DLC compiled for S25 but
|
||||
failed inference with a reported device-memory limit. This candidate retains
|
||||
the same pinned Qwen3-TTS 0.6B CustomVoice decoder and 72-frame history, and
|
||||
reduces only the new chunk to two frames: `float32[1,512,74]` in and
|
||||
`float32[1,3840]` out (0.16 s at 24 kHz). The RVQ codebook lookup remains
|
||||
outside this graph, as in the original HTP export.
|
||||
|
||||
The [export report](export_report.json) pins the checkpoint snapshot, weight
|
||||
hash, local fixture, output and ONNX artifact hashes. The ONNX file remains
|
||||
outside Git under `/home/zhout/project/edge_infer/models/`. Local ONNX
|
||||
Runtime CPU matched the eager decoder at **2.96e-6 relative L2**; the eager
|
||||
two-frame waveform matched the first 3,840 samples of the retained 25-frame
|
||||
CPU waveform at **2.83e-6 relative L2**. This is one fixed synthetic window,
|
||||
not a speech-quality test. The [exporter](../../../../../../experiments/export_qwen_tts_vocoder_short_chunk.py)
|
||||
reproduces the graph and parity gate.
|
||||
|
||||
The [local CPU component profile](cpu_profile_report.json) used one warmup and
|
||||
20 serial samples on the HX370 WSL CPU with ONNX Runtime 1.29 and four threads.
|
||||
Nearest-rank p50/p95 was **1.365/1.453 s** for 0.16 s of audio; component
|
||||
median RTF **8.53** is far from playable in this configuration. This CPU
|
||||
number is not an S25 estimate. The [profiler](../../../../../../experiments/profile_qwen_tts_short_vocoder_cpu.py)
|
||||
records the raw samples. A hosted S25 artifact must independently pass
|
||||
numerical, node-placement, memory and complete-stream gates before it can be
|
||||
called supported.
|
||||
|
||||
The source [upload](upload_submission.json) and [one-sample dataset](dataset_submission.json)
|
||||
were compiled to an [S25 FP16 QNN DLC](compile_report.json). Its
|
||||
[NPU-requested same-fixture inference](inference_report.json) **failed** with
|
||||
Workbench reporting that memory usage exceeded device limits. No device
|
||||
waveform, node-placement rows or timing samples were returned. Reducing the
|
||||
new chunk from 25 frames to two did not resolve memory admission for this
|
||||
FP16 QNN artifact. This failure does not rule out a different graph layout,
|
||||
precision or runtime route. The [compressed runtime log](logs/jg9zmvqvp_runtime.log.gz)
|
||||
preserves the failed job trace. A separate S25 TFLite GPU candidate is tracked
|
||||
under [tflite_short_chunk](../tflite_short_chunk/).
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"timestamp_utc": "2026-09-24T05:01:17.953595+00:00",
|
||||
"qai_hub_version": "0.55.0",
|
||||
"facility": "Qualcomm AI Hub Workbench",
|
||||
"job_id": "jp3z9k7x5",
|
||||
"url": "https://workbench.aihub.qualcomm.com/jobs/jp3z9k7x5/",
|
||||
"status": "SUCCESS",
|
||||
"status_message": "",
|
||||
"options": "--target_runtime qnn_dlc --qnn_options default_graph_htp_precision=FLOAT16",
|
||||
"hub_version": "aihub-2026.09.11.0",
|
||||
"device": {
|
||||
"name": "Samsung Galaxy S25",
|
||||
"os": "15",
|
||||
"attributes": [
|
||||
"os:android",
|
||||
"framework:tflite",
|
||||
"framework:onnx",
|
||||
"abi:aarch64-android",
|
||||
"vendor:samsung",
|
||||
"format:phone",
|
||||
"chipset:qualcomm-snapdragon-8-elite-for-galaxy",
|
||||
"chipset:sm8750-ac",
|
||||
"hexagon:v79",
|
||||
"soc-model:69",
|
||||
"htp-supports-fp16:true",
|
||||
"htp-supports-weight-sharing:true",
|
||||
"framework:qnn"
|
||||
]
|
||||
},
|
||||
"source_model_id": "mng2vv4em",
|
||||
"target_model_id": "mq80223jn"
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"timestamp_utc": "2026-09-24T04:58:52.103377+00:00",
|
||||
"facility": "Qualcomm AI Hub Workbench",
|
||||
"qai_hub_version": "0.55.0",
|
||||
"source_model_id": "mng2vv4em",
|
||||
"source_sha256": "e563541bf77200ac4c4ca9d6e01cd7e25c09f9274233a8d82eeccc57580830d2",
|
||||
"device": "Samsung Galaxy S25",
|
||||
"options": "--target_runtime qnn_dlc --qnn_options default_graph_htp_precision=FLOAT16",
|
||||
"kind": "compile",
|
||||
"status": "SUBMITTED",
|
||||
"job_id": "jp3z9k7x5",
|
||||
"url": "https://workbench.aihub.qualcomm.com/jobs/jp3z9k7x5/"
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"scope": "one fixed two-frame Code2Wav component on HX370 WSL ORT CPU; no complete TTS stream",
|
||||
"status": "component_cpu_profiled",
|
||||
"platform": "Linux-6.18.33.2-microsoft-standard-WSL2-x86_64-with-glibc2.43",
|
||||
"cpu": "AMD Ryzen AI 9 HX 370 w/ Radeon 890M",
|
||||
"python_version": "3.12.13",
|
||||
"checkpoint_revision": "85e237c12c027371202489a0ec509ded67b5e4b5",
|
||||
"power_condition": "not recorded",
|
||||
"ort_version": "1.29.0",
|
||||
"provider": [
|
||||
"CPUExecutionProvider"
|
||||
],
|
||||
"threads": 4,
|
||||
"model_sha256": "e563541bf77200ac4c4ca9d6e01cd7e25c09f9274233a8d82eeccc57580830d2",
|
||||
"fixture_sha256": "77aea3554c51b9daf808748257ebfc5e0496172c4d34c8267288be984d8a0f55",
|
||||
"load_s": 0.5960357000003569,
|
||||
"rss_after_load_bytes": 638189568,
|
||||
"warmups": 1,
|
||||
"sample_count": 20,
|
||||
"samples_s": [
|
||||
1.4534642749931663,
|
||||
1.354645981977228,
|
||||
1.3775672700139694,
|
||||
1.3591304540168494,
|
||||
1.3296460009878501,
|
||||
1.40560842998093,
|
||||
1.4525224060053006,
|
||||
1.3785532070323825,
|
||||
1.3530683669960126,
|
||||
1.3806309230276383,
|
||||
1.3724001089576632,
|
||||
1.3896296580205671,
|
||||
1.3652083780034445,
|
||||
1.374573242967017,
|
||||
1.3268145270412788,
|
||||
1.3424656029674225,
|
||||
1.3449684209772386,
|
||||
1.3345086729968898,
|
||||
1.3748839889885858,
|
||||
1.3425294969929382
|
||||
],
|
||||
"nearest_rank_p50_s": 1.3652083780034445,
|
||||
"nearest_rank_p95_s": 1.4525224060053006,
|
||||
"audio_duration_s": 0.16,
|
||||
"median_component_rtf": 8.532552362521528,
|
||||
"limits": [
|
||||
"The input is one retained synthetic window, and no talker or predictor ran.",
|
||||
"This host CPU timing cannot be transplanted to the S25 or another SoC."
|
||||
]
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"timestamp_utc": "2026-09-24T04:59:30.129187+00:00",
|
||||
"facility": "Qualcomm AI Hub Workbench",
|
||||
"qai_hub_version": "0.55.0",
|
||||
"fixture_sha256": "77aea3554c51b9daf808748257ebfc5e0496172c4d34c8267288be984d8a0f55",
|
||||
"input_name": "quantized",
|
||||
"input_shape": [
|
||||
1,
|
||||
512,
|
||||
74
|
||||
],
|
||||
"input_dtype": "float32",
|
||||
"sample_count": 1,
|
||||
"dataset_id": "d7ovqp0w2",
|
||||
"status": "UPLOADED"
|
||||
}
|
||||
BIN
Binary file not shown.
+49
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"scope": "one synthetic first short vocoder window; no device execution or complete TTS stream",
|
||||
"model_snapshot": "/home/zhout/.cache/huggingface/hub/models--Qwen--Qwen3-TTS-12Hz-0.6B-CustomVoice/snapshots/85e237c12c027371202489a0ec509ded67b5e4b5",
|
||||
"model_weight_sha256": "836b7b357f5ea43e889936a3709af68dfe3751881acefe4ecf0dbd30ba571258",
|
||||
"source_fixture_sha256": "dfca9e8d2a724a568a31b6cd18ff6a52fdc205fd34e13cbf1cd75f0f7937e82d",
|
||||
"long_cpu_reference_sha256": "8de78b94b59f01e49852f7706adbd2508a9976b8e2705cfd3b94d07bb3606cb1",
|
||||
"context_frames": 72,
|
||||
"chunk_frames": 2,
|
||||
"input_shape": [
|
||||
1,
|
||||
512,
|
||||
74
|
||||
],
|
||||
"output_shape": [
|
||||
1,
|
||||
3840
|
||||
],
|
||||
"export_s_not_inference": 7.429020452953409,
|
||||
"onnx_sha256": "e563541bf77200ac4c4ca9d6e01cd7e25c09f9274233a8d82eeccc57580830d2",
|
||||
"short_fixture_sha256": "77aea3554c51b9daf808748257ebfc5e0496172c4d34c8267288be984d8a0f55",
|
||||
"eager_output_sha256": "542113d24feeb4ff58b895ce7d96fc7aa5240b046a3a0d1d3922c7ab23ea0a7c",
|
||||
"ort_output_sha256": "989307db317d77be054f684211ae0c6a2fd24d93bcd74307c597fed430ba2a37",
|
||||
"ort_vs_eager": {
|
||||
"relative_l2": 2.9623994746865784e-06,
|
||||
"snr_db": 110.56712755941491,
|
||||
"max_abs": 1.3685785233974457e-06,
|
||||
"reference_rms": 0.04131376905845152,
|
||||
"output_rms": 0.04131374650145444
|
||||
},
|
||||
"short_eager_vs_25_frame_prefix": {
|
||||
"relative_l2": 2.826486997305525e-06,
|
||||
"snr_db": 110.97506016170293,
|
||||
"max_abs": 1.3941898941993713e-06,
|
||||
"reference_rms": 0.04131374658894702,
|
||||
"output_rms": 0.04131376905845152
|
||||
},
|
||||
"limits": [
|
||||
"The short-window graph still requires its prior 72 quantized frames from a model adapter.",
|
||||
"Prefix agreement is tested on one retained synthetic fixture, not a speech-quality set.",
|
||||
"CPU export parity does not establish target compilation, placement or memory admission."
|
||||
],
|
||||
"model_snapshot_revision": "85e237c12c027371202489a0ec509ded67b5e4b5",
|
||||
"torch_version": "2.13.0+cpu",
|
||||
"onnx_version": "1.22.0",
|
||||
"onnxruntime_version": "1.29.0",
|
||||
"actual_opsets": {
|
||||
"ai.onnx": 18
|
||||
}
|
||||
}
|
||||
BIN
Binary file not shown.
+32
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"timestamp_utc": "2026-09-24T05:11:41.882897+00:00",
|
||||
"qai_hub_version": "0.55.0",
|
||||
"facility": "Qualcomm AI Hub Workbench",
|
||||
"job_id": "jg9zmvqvp",
|
||||
"url": "https://workbench.aihub.qualcomm.com/jobs/jg9zmvqvp/",
|
||||
"status": "FAILED",
|
||||
"status_message": "Failed to profile the model because memory usage exceeded device limits.",
|
||||
"options": "--compute_unit npu",
|
||||
"hub_version": "aihub-2026.09.11.0",
|
||||
"device": {
|
||||
"name": "Samsung Galaxy S25",
|
||||
"os": "15",
|
||||
"attributes": [
|
||||
"os:android",
|
||||
"framework:tflite",
|
||||
"framework:onnx",
|
||||
"abi:aarch64-android",
|
||||
"vendor:samsung",
|
||||
"format:phone",
|
||||
"chipset:qualcomm-snapdragon-8-elite-for-galaxy",
|
||||
"chipset:sm8750-ac",
|
||||
"hexagon:v79",
|
||||
"soc-model:69",
|
||||
"htp-supports-fp16:true",
|
||||
"htp-supports-weight-sharing:true",
|
||||
"framework:qnn"
|
||||
]
|
||||
},
|
||||
"model_id": "mq80223jn",
|
||||
"input_dataset_id": "d7ovqp0w2"
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"timestamp_utc": "2026-09-24T05:01:33.608651+00:00",
|
||||
"facility": "Qualcomm AI Hub Workbench",
|
||||
"qai_hub_version": "0.55.0",
|
||||
"model_id": "mq80223jn",
|
||||
"input_dataset_id": "d7ovqp0w2",
|
||||
"device": "Samsung Galaxy S25",
|
||||
"options": "--compute_unit npu",
|
||||
"kind": "inference",
|
||||
"status": "SUBMITTED",
|
||||
"job_id": "jg9zmvqvp",
|
||||
"url": "https://workbench.aihub.qualcomm.com/jobs/jg9zmvqvp/"
|
||||
}
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
+18
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"timestamp_utc": "2026-09-24T04:58:20.183146+00:00",
|
||||
"facility": "Qualcomm AI Hub Workbench",
|
||||
"qai_hub_version": "0.55.0",
|
||||
"source_path_outside_git": "/home/zhout/project/edge_infer/models/qwen3tts_code2wav_c2_ctx72_20260924.onnx",
|
||||
"source_sha256": "e563541bf77200ac4c4ca9d6e01cd7e25c09f9274233a8d82eeccc57580830d2",
|
||||
"source_model_id": "mng2vv4em",
|
||||
"input_shape": [
|
||||
1,
|
||||
512,
|
||||
74
|
||||
],
|
||||
"output_shape": [
|
||||
1,
|
||||
3840
|
||||
],
|
||||
"status": "UPLOADED"
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
# Two-frame S25 TFLite GPU-requested Code2Wav component
|
||||
|
||||
The same pinned [72-history-plus-two-new-frame source](../qnn_short_chunk/README.md)
|
||||
and [one-sample fixture](../qnn_short_chunk/dataset_submission.json) compiled
|
||||
as a [TFLite artifact](compile_report.json) for Galaxy S25. A
|
||||
[GPU-requested inference](inference_report.json) returned a finite,
|
||||
unsaturated 3,840-sample waveform. The [audit](audit_report.json) binds the
|
||||
source, fixture, target and output hashes: versus local ONNX Runtime CPU on
|
||||
the same fixture, waveform relative L2 was **2.325%**, SNR **32.67 dB**, and
|
||||
maximum absolute difference **0.00810**. This is a numerical measurement,
|
||||
not a listening-quality qualification. The [raw output](device_output.npz)
|
||||
is retained.
|
||||
|
||||
The [placement profile](profile_report.json) returned **100** component
|
||||
samples at nearest-rank p50/p95 **0.559/1.052 s** for **0.16 s of audio**.
|
||||
Its execution detail assigned **403 rows to CPU and 335 to GPU**, so this is
|
||||
a mixed CPU/GPU route, not a GPU-only result. The reported inference peak was
|
||||
**379,121,664 bytes**. The [audit](audit_report.json) ties that profile to
|
||||
the same S25 target and tensor shape as the waveform check; Workbench generated
|
||||
the profile input, while the numerical inference used the retained fixture.
|
||||
Component median real-time factor
|
||||
is **3.49**, before talker, predictor, transfer or playback overhead; this
|
||||
route does not meet playable streaming latency on the measured fixture.
|
||||
|
||||
A complete Qwen3-TTS stream also needs a qualified talker/predictor, history
|
||||
and stage handoff, co-resident memory admission, cancellation, speech-quality
|
||||
checks and sustained playback.
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
{
|
||||
"scope": "one two-frame Qwen3-TTS vocoder component on hosted S25; no complete stream",
|
||||
"status": "component_inference_numeric_and_placement_measured",
|
||||
"device": {
|
||||
"name": "Samsung Galaxy S25",
|
||||
"os": "15",
|
||||
"attributes": [
|
||||
"os:android",
|
||||
"framework:tflite",
|
||||
"framework:onnx",
|
||||
"abi:aarch64-android",
|
||||
"vendor:samsung",
|
||||
"format:phone",
|
||||
"chipset:qualcomm-snapdragon-8-elite-for-galaxy",
|
||||
"chipset:sm8750-ac",
|
||||
"hexagon:v79",
|
||||
"soc-model:69",
|
||||
"htp-supports-fp16:true",
|
||||
"htp-supports-weight-sharing:true",
|
||||
"framework:qnn"
|
||||
]
|
||||
},
|
||||
"source_model_id": "mng2vv4em",
|
||||
"target_model_id": "mq9yrr5yn",
|
||||
"input_dataset_id": "d7ovqp0w2",
|
||||
"jobs": {
|
||||
"compile": "j56876x7g",
|
||||
"inference": "j57e4zzrp",
|
||||
"profile": "jpxl4jo1p"
|
||||
},
|
||||
"route": {
|
||||
"compile_options": "--target_runtime tflite",
|
||||
"run_options": "--compute_unit gpu"
|
||||
},
|
||||
"files": {
|
||||
"fixture": {
|
||||
"bytes": 129614,
|
||||
"sha256": "77aea3554c51b9daf808748257ebfc5e0496172c4d34c8267288be984d8a0f55"
|
||||
},
|
||||
"ort_cpu": {
|
||||
"bytes": 14813,
|
||||
"sha256": "989307db317d77be054f684211ae0c6a2fd24d93bcd74307c597fed430ba2a37"
|
||||
},
|
||||
"eager_cpu": {
|
||||
"bytes": 14818,
|
||||
"sha256": "542113d24feeb4ff58b895ce7d96fc7aa5240b046a3a0d1d3922c7ab23ea0a7c"
|
||||
},
|
||||
"device_output": {
|
||||
"bytes": 9294,
|
||||
"sha256": "fd62eff1aded00728b08418003a0165676b0399bca91b47398e7f54ff0e84c03"
|
||||
}
|
||||
},
|
||||
"ort_cpu_vs_device": {
|
||||
"relative_l2": 0.02325155074513613,
|
||||
"snr_db": 32.67096153711811,
|
||||
"max_abs": 0.008096754550933838,
|
||||
"reference_rms": 0.04131374650145444,
|
||||
"output_rms": 0.041393810541143945,
|
||||
"output_saturated_fraction_abs_ge_0_999": 0.0
|
||||
},
|
||||
"eager_cpu_vs_device": {
|
||||
"relative_l2": 0.023249718394146676,
|
||||
"snr_db": 32.67164606030534,
|
||||
"max_abs": 0.008095551282167435,
|
||||
"reference_rms": 0.04131376905845152,
|
||||
"output_rms": 0.041393810541143945,
|
||||
"output_saturated_fraction_abs_ge_0_999": 0.0
|
||||
},
|
||||
"limits": [
|
||||
"One fixed two-frame waveform has no listening-quality tolerance.",
|
||||
"The 72-frame input history, talker, predictor and stage handoff did not run on the device.",
|
||||
"No persistent state, admission, cancellation or complete TTS stream was tested."
|
||||
],
|
||||
"profile": {
|
||||
"sample_count": 100,
|
||||
"min_us": 414816,
|
||||
"nearest_rank_p50_us": 559081,
|
||||
"nearest_rank_p95_us": 1051787,
|
||||
"reported_peak_memory_bytes": 379121664,
|
||||
"compute_unit_row_counts": {
|
||||
"CPU": 403,
|
||||
"GPU": 335
|
||||
},
|
||||
"profile_input": "Workbench generated input with audited tensor shape; the waveform inference used the retained fixture"
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"timestamp_utc": "2026-09-24T05:08:45.788423+00:00",
|
||||
"qai_hub_version": "0.55.0",
|
||||
"facility": "Qualcomm AI Hub Workbench",
|
||||
"job_id": "j56876x7g",
|
||||
"url": "https://workbench.aihub.qualcomm.com/jobs/j56876x7g/",
|
||||
"status": "SUCCESS",
|
||||
"status_message": "",
|
||||
"options": "--target_runtime tflite",
|
||||
"hub_version": "aihub-2026.09.11.0",
|
||||
"device": {
|
||||
"name": "Samsung Galaxy S25",
|
||||
"os": "15",
|
||||
"attributes": [
|
||||
"os:android",
|
||||
"framework:tflite",
|
||||
"framework:onnx",
|
||||
"abi:aarch64-android",
|
||||
"vendor:samsung",
|
||||
"format:phone",
|
||||
"chipset:qualcomm-snapdragon-8-elite-for-galaxy",
|
||||
"chipset:sm8750-ac",
|
||||
"hexagon:v79",
|
||||
"soc-model:69",
|
||||
"htp-supports-fp16:true",
|
||||
"htp-supports-weight-sharing:true",
|
||||
"framework:qnn"
|
||||
]
|
||||
},
|
||||
"source_model_id": "mng2vv4em",
|
||||
"target_model_id": "mq9yrr5yn"
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"timestamp_utc": "2026-09-24T05:04:49.276829+00:00",
|
||||
"facility": "Qualcomm AI Hub Workbench",
|
||||
"qai_hub_version": "0.55.0",
|
||||
"source_model_id": "mng2vv4em",
|
||||
"source_sha256": "e563541bf77200ac4c4ca9d6e01cd7e25c09f9274233a8d82eeccc57580830d2",
|
||||
"device": "Samsung Galaxy S25",
|
||||
"options": "--target_runtime tflite",
|
||||
"kind": "compile",
|
||||
"status": "SUBMITTED",
|
||||
"job_id": "j56876x7g",
|
||||
"url": "https://workbench.aihub.qualcomm.com/jobs/j56876x7g/"
|
||||
}
|
||||
BIN
Binary file not shown.
+33
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"timestamp_utc": "2026-09-24T05:14:59.315569+00:00",
|
||||
"qai_hub_version": "0.55.0",
|
||||
"facility": "Qualcomm AI Hub Workbench",
|
||||
"job_id": "j57e4zzrp",
|
||||
"url": "https://workbench.aihub.qualcomm.com/jobs/j57e4zzrp/",
|
||||
"status": "SUCCESS",
|
||||
"status_message": "",
|
||||
"options": "--compute_unit gpu",
|
||||
"hub_version": "aihub-2026.09.11.0",
|
||||
"device": {
|
||||
"name": "Samsung Galaxy S25",
|
||||
"os": "15",
|
||||
"attributes": [
|
||||
"os:android",
|
||||
"framework:tflite",
|
||||
"framework:onnx",
|
||||
"abi:aarch64-android",
|
||||
"vendor:samsung",
|
||||
"format:phone",
|
||||
"chipset:qualcomm-snapdragon-8-elite-for-galaxy",
|
||||
"chipset:sm8750-ac",
|
||||
"hexagon:v79",
|
||||
"soc-model:69",
|
||||
"htp-supports-fp16:true",
|
||||
"htp-supports-weight-sharing:true",
|
||||
"framework:qnn"
|
||||
]
|
||||
},
|
||||
"model_id": "mq9yrr5yn",
|
||||
"input_dataset_id": "d7ovqp0w2",
|
||||
"outputs": "device_output.npz"
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"timestamp_utc": "2026-09-24T05:08:59.567198+00:00",
|
||||
"facility": "Qualcomm AI Hub Workbench",
|
||||
"qai_hub_version": "0.55.0",
|
||||
"model_id": "mq9yrr5yn",
|
||||
"input_dataset_id": "d7ovqp0w2",
|
||||
"device": "Samsung Galaxy S25",
|
||||
"options": "--compute_unit gpu",
|
||||
"kind": "inference",
|
||||
"status": "SUBMITTED",
|
||||
"job_id": "j57e4zzrp",
|
||||
"url": "https://workbench.aihub.qualcomm.com/jobs/j57e4zzrp/"
|
||||
}
|
||||
+5362
File diff suppressed because it is too large.
Load diff
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"timestamp_utc": "2026-09-24T05:16:05.792010+00:00",
|
||||
"facility": "Qualcomm AI Hub Workbench",
|
||||
"qai_hub_version": "0.55.0",
|
||||
"target_model_id": "mq9yrr5yn",
|
||||
"input_dataset_id": null,
|
||||
"device": "Samsung Galaxy S25",
|
||||
"options": "--compute_unit gpu",
|
||||
"kind": "profile",
|
||||
"status": "SUBMITTED",
|
||||
"job_id": "jpxl4jo1p",
|
||||
"url": "https://workbench.aihub.qualcomm.com/jobs/jpxl4jo1p/"
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
# Spark-X2.5 1.7B BF16 on WSL CPU
|
||||
|
||||
The complete upstream BF16 checkpoint, previously missing its two weight
|
||||
shards, was downloaded outside Git from
|
||||
`XHToken/Spark-X2.5-1.7B` at revision
|
||||
`14d6e83c13c7add2b62a7c39b2131f4ed1cddcf8`. The
|
||||
[weight manifest](weight_manifest.json) verifies both upstream LFS SHA256
|
||||
digests, file sizes and every tensor name in the checkpoint index. This is a
|
||||
separate artifact from the previously tested INT8 and GGUF variants.
|
||||
|
||||
On the Ryzen AI 9 HX 370 WSL CPU, the current Omni local text path admitted
|
||||
the dense BF16 artifact with a 4,096-token context and an explicit 7.64 GiB
|
||||
host-RAM budget. The [fork-branch acceptance run](accept_branch_report.json) completed all 12
|
||||
named prompts with 128 output tokens each, reported actual CPU placement, and
|
||||
retired an in-flight cancelled request without a stale event. The separate
|
||||
[fork-branch parity run](parity_branch_report.json) compared the Omni path against standalone
|
||||
vLLM on the same checkpoint and found exact greedy token-ID agreement for
|
||||
12/12 prompts at 128 output tokens. The installed vLLM was 0.28.0 while the
|
||||
tested fork-branch Omni package identified as 0.29.0rc2.dev71, so that
|
||||
version pairing and its compatibility warning must be retained with the result.
|
||||
The branch acceptance run observed a 30.36 s load and approximately 6.45 GiB
|
||||
process-tree RSS load delta; neither is a cold-start guarantee or an
|
||||
attribution to model weights alone.
|
||||
The [branch run manifest](branch_run_manifest.json) pins the imported runtime,
|
||||
source-file hashes and all three raw report hashes.
|
||||
|
||||
The [fork-branch 20-request complete-text profile](profile20_branch_report.json) used one warmup,
|
||||
then 20 serial requests with the same 28-token prompt and 64 generated tokens
|
||||
per request. Nearest-rank p50/p95 complete-request wall time was **5.411/5.751 s**;
|
||||
time to first token was **0.129/0.146 s**. These are measurements of the admitted
|
||||
fork-branch Omni BF16 CPU route, not mobile estimates or sustained thermal results. The
|
||||
[profiler](../../../../experiments/profile_spark_bf16_omni_cpu.py) retains all
|
||||
20 raw request samples and runtime provenance. A separately retained
|
||||
[acceptance](accept_report.json), [parity](parity_report.json) and
|
||||
[20-request profile](profile20_report.json) came from a neighboring Omni
|
||||
checkout (`3834de310`, package `0.28.1.dev154`) with the same vLLM 0.28.0
|
||||
and checkpoint. Its 4.808/5.089 s wall p50/p95 and 19.88 s acceptance load
|
||||
are distinct run observations, not the fork-branch timing.
|
||||
|
||||
Reproduce from the repository root with the installed CPU environment, after
|
||||
downloading the pinned checkpoint into the path below:
|
||||
|
||||
```bash
|
||||
export PYTHONPATH=/home/zhout/project/edge_infer/vllm-omni-edge
|
||||
/home/zhout/project/edge_infer/.venvs/omni-cpu/bin/python -m vllm_omni.edge.local accept \
|
||||
--model /home/zhout/project/edge_infer/models/Spark-X2.5-1.7B-BF16 \
|
||||
--max-model-len 4096 --max-tokens 128 --json /tmp/spark_bf16_accept_repeat.json
|
||||
/home/zhout/project/edge_infer/.venvs/omni-cpu/bin/python -m vllm_omni.edge.local parity \
|
||||
--model /home/zhout/project/edge_infer/models/Spark-X2.5-1.7B-BF16 \
|
||||
--max-model-len 4096 --max-tokens 128 --json /tmp/spark_bf16_parity_repeat.json
|
||||
/home/zhout/project/edge_infer/.venvs/omni-cpu/bin/python \
|
||||
benchmarks/edge_harness/experiments/profile_spark_bf16_omni_cpu.py \
|
||||
--model /home/zhout/project/edge_infer/models/Spark-X2.5-1.7B-BF16 \
|
||||
--report /tmp/spark_bf16_profile_repeat.json
|
||||
```
|
||||
|
||||
This validates one complete text path and cancellation on WSL CPU. It does
|
||||
not establish native Windows BF16 execution, mobile generation, broader text
|
||||
quality, sustained load, or an incremental GGUF token-stream contract.
|
||||
+7750
File diff suppressed because it is too large.
Load diff
+7750
File diff suppressed because it is too large.
Load diff
+62
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"scope": "fork branch Spark 1.7B BF16 WSL CPU complete text",
|
||||
"source_checkout": "/home/zhout/project/edge_infer/vllm-omni-edge",
|
||||
"source_head": "8978302a1b7b86f17f45d530c544fb87bec8990d",
|
||||
"runtime": {
|
||||
"python": "3.12.13",
|
||||
"platform": "Linux-6.18.33.2-microsoft-standard-WSL2-x86_64-with-glibc2.43",
|
||||
"torch": "2.13.0+cpu",
|
||||
"vllm": "0.28.0",
|
||||
"vllm_omni": "0.29.0rc2.dev71+g00510ce38.d20260922",
|
||||
"vllm_omni_file": "/home/zhout/project/edge_infer/vllm-omni-edge/vllm_omni/__init__.py",
|
||||
"vllm_file": "/home/zhout/project/edge_infer/.venvs/omni-cpu/lib/python3.12/site-packages/vllm/__init__.py",
|
||||
"checkouts": {
|
||||
"/home/zhout/project/edge_infer/vllm-omni-edge": "8978302a1b7b86f17f45d530c544fb87bec8990d-dirty",
|
||||
"/home/zhout/project/edge_infer": "758b3af238b19e2c2abc668f23a767bb835a4a22-dirty"
|
||||
}
|
||||
},
|
||||
"checkpoint_revision": "14d6e83c13c7add2b62a7c39b2131f4ed1cddcf8",
|
||||
"commands": "PYTHONPATH=/home/zhout/project/edge_infer/vllm-omni-edge; accept/parity CLI --max-model-len 4096 --max-tokens 128; profile script 1 warmup + 20 serial 64-token requests",
|
||||
"code_files": [
|
||||
{
|
||||
"path": "vllm_omni/edge/local/engine.py",
|
||||
"bytes": 34926,
|
||||
"sha256": "ad2427a0a7a65201fa7463ad879ef42ac0190af76a59c88a6cb5021f9ea3a0f6"
|
||||
},
|
||||
{
|
||||
"path": "vllm_omni/edge/local/plan.py",
|
||||
"bytes": 28619,
|
||||
"sha256": "d4665e68b47513dd62d746091e840f652270f37467da0c5c5528613a06ed9fe3"
|
||||
},
|
||||
{
|
||||
"path": "vllm_omni/edge/local/cli.py",
|
||||
"bytes": 21877,
|
||||
"sha256": "c3b5685125b39474008df1a030779cd3e3188495af5080a189c7473f5a8041bc"
|
||||
},
|
||||
{
|
||||
"path": "benchmarks/edge_harness/experiments/profile_spark_bf16_omni_cpu.py",
|
||||
"bytes": 4857,
|
||||
"sha256": "2af5d2b4520850c6f46a5af2db508e976c1c976dd24c50de5e3ee869917b5285"
|
||||
}
|
||||
],
|
||||
"reports": [
|
||||
{
|
||||
"path": "benchmarks/edge_harness/results/e2e_expansion_20260924/evidence/spark_bf16_wsl_cpu/accept_branch_report.json",
|
||||
"bytes": 164113,
|
||||
"sha256": "a26c29eab57097c598bb9a86ce1bf30bd94134e3b0f281c13add7c0a15d3e15a"
|
||||
},
|
||||
{
|
||||
"path": "benchmarks/edge_harness/results/e2e_expansion_20260924/evidence/spark_bf16_wsl_cpu/parity_branch_report.json",
|
||||
"bytes": 58645,
|
||||
"sha256": "eca6ef32c708580d4dcda4584b4f5fe811bbe37a6f28dc606b053949a8c7db44"
|
||||
},
|
||||
{
|
||||
"path": "benchmarks/edge_harness/results/e2e_expansion_20260924/evidence/spark_bf16_wsl_cpu/profile20_branch_report.json",
|
||||
"bytes": 110420,
|
||||
"sha256": "2dbe6ca73a3f009c5a6de26500eb7f585fd7dd732f079d8730c892ef40ee42f8"
|
||||
}
|
||||
],
|
||||
"accepted": true,
|
||||
"greedy_exact_prompts": 12,
|
||||
"measured_requests": 20
|
||||
}
|
||||
+3694
File diff suppressed because it is too large.
Load diff
+3694
File diff suppressed because it is too large.
Load diff
+4193
File diff suppressed because it is too large.
Load diff
+4192
File diff suppressed because it is too large.
Load diff
+23
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"status": "verified",
|
||||
"repo": "XHToken/Spark-X2.5-1.7B",
|
||||
"revision": "14d6e83c13c7add2b62a7c39b2131f4ed1cddcf8",
|
||||
"format": "dense BF16 safetensors",
|
||||
"index_sha256": "cc2b212985f5d0469bf926903e4bd7ee81856687baa0c6c6b55ff200d4cdc63f",
|
||||
"config_sha256": "16aa5d3619d0d893e7157f2499675430844eb7b383c80ecc1b3e8e8928a75d52",
|
||||
"files": [
|
||||
{
|
||||
"file": "model-00001-of-00002.safetensors",
|
||||
"bytes": 1997108320,
|
||||
"sha256": "b1629719b3f6de5de922abb3c90e45927550dd6f790f43030dc812cafce1af87",
|
||||
"tensor_count": 116
|
||||
},
|
||||
{
|
||||
"file": "model-00002-of-00002.safetensors",
|
||||
"bytes": 1418232176,
|
||||
"sha256": "3537675bfb657cb6d1f70bb1fab9b83fcb79ce5693f2557992548eb6d2bf13a0",
|
||||
"tensor_count": 110
|
||||
}
|
||||
],
|
||||
"weights_outside_git": true
|
||||
}
|
||||
@@ -8,6 +8,8 @@ A [follow-up MiniCPM-o storage experiment](../../../e2e_expansion_20260923/evide
|
||||
|
||||
The [WSL CPU Spark GGUF Omni profile](../../../e2e_expansion_20260923/evidence/spark_omni_wsl_cpu/README.md) adds a separate current-Omni complete-request path to the earlier vLLM INT8 CPU result. It passed two named prompts, 20/20 serial measured inventory requests at p50/p95 7.82/7.97 s, a public text request, context refusal and cancellation cleanup. The CPU-only llama.cpp build required explicit CPU-buffer placement evidence because it omits the Windows offload-count log line. This does not establish token streaming or broad quality.
|
||||
|
||||
A complete pinned [Spark 1.7B BF16 WSL CPU checkpoint and acceptance run](../../../e2e_expansion_20260924/evidence/spark_bf16_wsl_cpu/README.md) adds a second current-Omni text artifact to the GGUF route. Twelve prompts produced 128 tokens each with clean cancellation; all 12 token-ID sequences exactly matched standalone vLLM on the same checkpoint. One warmup plus 20 serial 28-prompt-token/64-output-token requests measured p50/p95 complete-request wall time 5.411/5.751 s and TTFT 0.129/0.146 s on the fork branch. This is WSL CPU full-text scope, not mobile generation or broad quality qualification.
|
||||
|
||||
On a hosted [Galaxy S24 Spark attention-layer experiment](../../../e2e_expansion_20260923/evidence/spark_s24_full_attention/README.md), a real one-layer W8A16 QDQ artifact executed on NPU and matched prior S25 component outputs exactly on one dataset. The 100-sample layer p50/p95 was 1.109/1.205 ms; the service's 1.098 ms estimated-time field was the sample minimum. FP32-source versus S24 output hidden-state relative L2 was 1.351% without a downstream token-quality gate. This adds component C evidence only; device-local generation remains absent.
|
||||
|
||||
The same W8A16 layer also ran on hosted [Snapdragon X Elite CRD](../../../e2e_expansion_20260923/evidence/spark_xelite_full_attention/README.md) and [SA8775P ADP](../../../e2e_expansion_20260923/evidence/spark_sa8775_full_attention/README.md) NPUs, with pinned-fixture outputs identical to S24/S25; the 100-sample component p50/p95 was 1.433/1.606 ms and 1.837/2.079 ms, respectively. On [RB3 Gen 2 / QCS6490](../../../e2e_expansion_20260923/evidence/spark_rb3_full_attention/README.md), that W8A16 graph failed QNN DLC loading even after target-specific recompilation. An FP32 ONNX CPU layer then passed with source-relative L2 below 9e-7, while a calibrated W8A8 NPU layer executed but had 20.9% hidden-state relative L2 and remains numerically unqualified. These hosted component outcomes do not establish full generation or comparable device speed.
|
||||
@@ -40,7 +42,7 @@ NOT E2E means no complete device/model workload was verified. “Scoped E2E” i
|
||||
|
||||
| Device | Spark-X2.5 | Qwen3-TTS 0.6B CustomVoice | Qwen3.8-27B | MiniCPM-o 4.5 | InternVLA-A1 |
|
||||
|---|---|---|---|---|---|
|
||||
| PC HX370: CPU / WSL | scoped E2E: Omni GGUF Spark text | scoped E2E: Omni CPU text → complete WAV | NOT E2E | scoped E2E: Omni GGUF combined image+audio → text+speech | synthetic policy pass: Omni CPU |
|
||||
| PC HX370: CPU / WSL | scoped E2E: Omni GGUF or BF16 Spark text | scoped E2E: Omni CPU text → complete WAV | NOT E2E | scoped E2E: Omni GGUF combined image+audio → text+speech | synthetic policy pass: Omni CPU |
|
||||
| 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 (native-storage 20-run profile) | synthetic policy pass: Omni CPU |
|
||||
| PC HX370 + RTX 5090 Laptop / WSL | profile completed | profile completed | scoped E2E: text + image | scoped E2E: text/image/audio → speech | synthetic policy pass: admitted Omni CUDA |
|
||||
| PC HX370 + RTX 5090 Laptop / Windows | profile completed | profile completed; 30-min repeat no collapse, brief playback jitter | NOT E2E | scoped E2E: text/image/audio → speech | synthetic policy pass: admitted Omni CUDA |
|
||||
@@ -48,7 +50,7 @@ NOT E2E means no complete device/model workload was verified. “Scoped E2E” i
|
||||
| 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 (one Spark attention layer on NPU) | NOT E2E (CPU talker/vocoder steps; QNN vocoder numeric) | NOT E2E | NOT E2E (NPU speech-head step profiled) | NOT E2E (Cosmos NPU encoder profiled) |
|
||||
| Mobile Galaxy S25 / Snapdragon 8 Elite for Galaxy | NOT E2E (one Spark attention layer on NPU) | NOT E2E (FP16 talker token mismatch; CPU talker + vocoder profiled) | NOT E2E | NOT E2E (NPU speech head step profiled) | NOT E2E (Cosmos NPU encoder profiled) |
|
||||
| Mobile Galaxy S25 / Snapdragon 8 Elite for Galaxy | NOT E2E (one Spark attention layer on NPU) | NOT E2E (FP16 talker token mismatch; CPU talker + vocoder profiled; 25-frame and two-frame QNN vocoder memory failures; short TFLite CPU/GPU component p50 0.559 s for 0.16 s audio) | NOT E2E | NOT E2E (NPU speech head step profiled) | NOT E2E (Cosmos NPU encoder profiled) |
|
||||
| Mobile Galaxy S24 / Snapdragon 8 Gen 3 | NOT E2E (one Spark attention layer on NPU) | NOT E2E (FP16 talker token mismatch; CPU talker + vocoder profiled) | NOT E2E | NOT E2E (NPU speech head step profiled) | NOT E2E (Cosmos encoder numeric and NPU profiled) |
|
||||
| Embedded SA8775P ADP / AI Hub | NOT E2E (one Spark attention layer on NPU) | NOT E2E (CPU talker/vocoder steps; NPU vocoder failed) | NOT E2E | NOT E2E (NPU speech-head step profiled) | NOT E2E (Cosmos NPU encoder profiled) |
|
||||
| Embedded RB3 Gen 2 / QCS6490 / AI Hub | NOT E2E (Spark CPU layer passed; W8A8 NPU quality open) | NOT E2E (CPU talker + vocoder profiled; INT8 NPU vocoder fails numeric gate) | NOT E2E | NOT E2E (CPU speech-head step profiled) | NOT E2E (Cosmos CPU numeric and profiled) |
|
||||
@@ -57,7 +59,7 @@ NOT E2E means no complete device/model workload was verified. “Scoped E2E” i
|
||||
|
||||
| Device | Model | Current profiling disposition | Reason / remaining work | Next step |
|
||||
|---|---|---|---|---|
|
||||
| PC HX370: CPU / WSL | Spark-X2.5 | SCOPED_E2E_OMNI_COMPLETE_REQUEST | The pinned Spark-X2.5-1.7B Q4_K_M GGUF ran on a CPU-only Linux llama.cpp server through the current Omni 0.29 `StageRuntime`/`StagePool` whole-session backend. Both named prompts passed (`Paris`, `1511`); one warmup plus 20/20 serial inventory requests had nearest-rank complete-request wall p50/p95 7.82/7.97 s, excluding 1.61 s startup. The stage verified model/server hashes, explicit CPU-only tensor buffers (`CPU_Mapped`, `CPU_REPACK`) and no usable GPU, reserved 4 GiB host RAM, refused an over-context request without truncation, and after in-flight cancellation returned no stale output or reservation. A separate public `AsyncOmni.generate` text request passed. The Linux CPU-only build omits the Windows 0/29 offload line; the verifier was extended to require positive CPU buffer evidence rather than inferring CPU from an absent GPU count. This is separate from the historical vLLM INT8 CPU profile and does not prove model-wide quality, incremental token streaming, restart-after-cancel, loading peak or sustained performance. | Broaden text/token quality and context suite, qualify matching vLLM 0.29 CPU execution/token parity, then test streaming, restart, loading peak and sustained load; [WSL GGUF Omni raw evidence](../../../e2e_expansion_20260923/evidence/spark_omni_wsl_cpu/README.md). |
|
||||
| PC HX370: CPU / WSL | Spark-X2.5 | SCOPED_E2E_OMNI_COMPLETE_REQUEST; BF16_CPU_ACCEPTANCE_PARITY_AND_PROFILE_PASS | The pinned Spark-X2.5-1.7B Q4_K_M GGUF ran on a CPU-only Linux llama.cpp server through the current Omni 0.29 `StageRuntime`/`StagePool` whole-session backend. Both named prompts passed (`Paris`, `1511`); one warmup plus 20/20 serial inventory requests had nearest-rank complete-request wall p50/p95 7.82/7.97 s, excluding 1.61 s startup. The stage verified model/server hashes, explicit CPU-only tensor buffers (`CPU_Mapped`, `CPU_REPACK`) and no usable GPU, reserved 4 GiB host RAM, refused an over-context request without truncation, and after in-flight cancellation returned no stale output or reservation. A separate public `AsyncOmni.generate` text request passed. The Linux CPU-only build omits the Windows 0/29 offload line; the verifier was extended to require positive CPU buffer evidence rather than inferring CPU from an absent GPU count. A separate pinned 1.7B BF16 checkpoint was completed and verified against the upstream index. The current Omni vLLM CPU text path then passed 12/12 named prompts at 128 generated tokens, cancellation cleanup and exact 12/12 greedy token-ID parity against standalone vLLM on the same BF16 checkpoint. The fork-branch acceptance load was 30.36 s with approximately 6.45 GiB process-tree RSS load delta; the plan reserved 7.64 GiB. One warmup plus 20 serial BF16 complete requests (28 prompt tokens, 64 output tokens) measured nearest-rank wall p50/p95 5.411/5.751 s and TTFT 0.129/0.146 s on HX370 WSL CPU. Separate neighboring-checkout evidence retained a 19.88 s acceptance load and 4.808/5.089 s profile; it is not the fork-branch timing. The installed vLLM was 0.28.0 with 0.29.0rc2 Omni source, so that version pairing is the tested boundary. The GGUF result and historical INT8 result remain distinct artifacts. None establishes broad text quality, incremental GGUF token streaming, restart-after-cancel, loading peak or sustained performance. | Broaden text quality and context, qualify a matching Omni/vLLM version pair, then test streaming, restart and sustained load; [GGUF evidence](../../../e2e_expansion_20260923/evidence/spark_omni_wsl_cpu/README.md) and [BF16 evidence](../../../e2e_expansion_20260924/evidence/spark_bf16_wsl_cpu/README.md). |
|
||||
| PC HX370: CPU / WSL | Qwen3-TTS 0.6B CustomVoice | SCOPED_E2E_OMNI_COMPLETE_REQUEST | The earlier vLLM 0.28 CPU path passed four short streams but had four simulated playback underruns in one measured request; its wheel remains mismatched with Omni 0.29. Separately, the pinned BF16 0.6B CustomVoice checkpoint ran two named text-to-complete-WAV requests through an Omni 0.29 whole-session stage with an isolated CPU worker on WSL. One warmup plus 20 serial measured requests returned identical 3.44 s audio; nearest-rank complete-request wall p50/p95 was 8.27/8.47 s (RTF 2.40/2.46), excluding 19.82 s startup. Pinned Whisper tiny.en transcribed the first measured WAV exactly (WER 0, one-output intelligibility proxy). Public `AsyncOmni` audio output passed; the stage verified weights, interpreter and CPU placement, reserved 10 GiB host RAM, refused 4 GiB before launch, and drained in-flight cancellation with zero remaining reservation. WSL PCM differs from the same-checkpoint native Windows outputs despite the declared settings; its cause is unqualified. Sampled process-tree RSS reached 3.39 GB, not a loading peak. This worker delivers only a complete WAV, not a playable stream. | Qualify cross-OS numerical/quality difference, playable streaming without underruns, post-cancel restart, loading peak, concurrency and sustained power/thermal behavior; [WSL Omni raw evidence](../../../e2e_expansion_20260923/evidence/qwen_tts_omni_wsl_cpu/README.md), [earlier stream evidence](../../../e2e_recovery_20260923/README.md). |
|
||||
| PC HX370: CPU / WSL | Qwen3.8-27B | NOT_E2E_PROFILEABLE | No compatible CPU artifact/deployment for this model was found in the checked model roots. Available Qwen 27B FP8/NVFP4 CUDA artifacts do not establish a CPU route. | Supply and validate the missing matching artifact/backend, then run the complete specified workload. |
|
||||
| PC HX370: CPU / WSL | MiniCPM-o 4.5 | SCOPED_E2E_OMNI_COMPLETE_REQUEST | The BF16/vLLM 0.28 three-stage path previously passed separate text, synthetic red-square image and synthetic 440 Hz audio inputs to text+speech; its 20-request serial **text-only** profile was p50/p95 21.86/22.97 s with swap and shutdown warnings. A separate pinned Q4_K_M/F16 GGUF worker now runs a **combined spoken question+image → text+speech** request through a bounded Omni StageRuntime/StagePool graph stage on WSL CPU, with installed vLLM 0.29 for the controller and CPU-only C++ model execution. All 20 measured requests after one warmup answered “The square in the image is red.”, emitted complete nonzero speech and a terminal audio event; nearest-rank complete-request wall p50/p95 was 22.67/24.83 s, speech duration 1.60–2.92 s, and maximum sampled worker RSS 13.70 GB. The first measured WAV independently transcribed exactly with pinned Whisper tiny.en (WER 0, one-output intelligibility proxy). Ten weight hashes and CPU placement were verified; 24 GiB shared RAM was reserved, 8 GiB was refused before launch, and in-flight cancellation left no stale output or reservation. Host RAM/swap samples covered only part of the profile. One synthetic fixture and variable speech PCM do not establish general quality, playable streaming, loading peak or sustained performance. | Validate real image/audio suites, speech alignment and quality, video input, concurrent admission, post-cancel restart, loading peak and sustained thermal behavior; [GGUF Omni raw evidence](../../../e2e_expansion_20260923/evidence/minicpmo_omni_wsl_cpu/README.md), [BF16/vLLM CPU evidence](../../../e2e_expansion_20260923/README.md), [earlier standalone GGUF run](../../../e2e_expansion_20260923/evidence/minicpmo_cpp_cpu/README.md). |
|
||||
@@ -98,7 +100,7 @@ NOT E2E means no complete device/model workload was verified. “Scoped E2E” i
|
||||
| PC Snapdragon X Elite CRD / AI Hub | MiniCPM-o 4.5 | COMPONENT_SPEECH_HEAD_NPU_NUMERIC_PROFILED; NOT_E2E_PROFILEABLE | The real 20-layer MiniCPM-o speech-head FP16 QNN DLC ran on the exact X Elite CRD. Same-fixture inference returned 41 finite tensors, preserved ONNX CPU top-1 speech token 1867, and had 0.3170% logits relative L2 and 1.221% maximum K/V relative L2. Its 100-sample component profile had nearest-rank p50/p95 9.905/11.037 ms, with all 944 execution-detail rows on NPU. Reported inference peak memory was 79,208,448 bytes and first-load peak 1,081,573,376 bytes. Thinker/encoders/vocoder and a device-local stateful Omni backend remain unqualified. | Validate the complete multimodal pipeline, state, quality, co-resident memory and sustained behavior; [X Elite raw evidence](../../../e2e_expansion_20260924/evidence/minicpmo_tts_qualcomm/README.md). |
|
||||
| PC Snapdragon X Elite CRD / AI Hub | InternVLA-A1 | COMPONENT_COSMOS_NPU_NUMERIC_PROFILED; NOT_E2E_PROFILEABLE | The real Place_Markpen Cosmos FP16 QNN image encoder returned a finite FP32 latent for the six-frame synthetic pattern on exact X Elite CRD. Against the pinned source, relative L2 was 0.0608%, SNR 64.32 dB and cosine 0.999999815. The 100-sample six-frame encoder profile had p50/p95 82.939/83.837 ms, with all 121 execution-detail rows on NPU. Reported component inference peak memory was 24,059,904 bytes and first-load peak 692,891,648 bytes. No real-observation action tolerance, complete policy or local stateful Omni backend exists. | Validate real observations, action units/timing, state, admission, cancellation and sustained behavior; [X Elite Cosmos raw evidence](../../../e2e_expansion_20260924/evidence/internvla_cosmos_qualcomm/README.md). |
|
||||
| Mobile Galaxy S25 / Snapdragon 8 Elite for Galaxy | Spark-X2.5 | COMPONENT_NPU_INFERENCE_PROFILED; NOT_E2E_PROFILEABLE | The real 1.7B checkpoint one-layer W8A16 full-attention decoder artifact executed for a fixed 1,024-token cache bucket. Same-fixture outputs matched S24; the hosted S25 profile had 100 component samples at nearest-rank p50/p95 0.957/1.028 ms with all 73 execution-detail rows on NPU. FP32-source hidden-state relative L2 was 1.351% without a downstream token-quality gate. No full 28-layer prefill/decode, KV/ring, sampling or resident controller ran on S25. | Implement and validate local 128-token generation, 512/1024 transitions, cancellation, resident memory and sustained power; [S25/S24 component evidence](../../../e2e_expansion_20260923/evidence/spark_s24_full_attention/README.md). |
|
||||
| Mobile Galaxy S25 / Snapdragon 8 Elite for Galaxy | Qwen3-TTS 0.6B CustomVoice | TALKER_FP16_NUMERIC_FAIL; CPU_TALKER_AND_VOCODER_NUMERIC_PROFILED; NOT_E2E_PROFILEABLE | Fresh FP16 predictor inference passed; its one output exactly matches the same compiled artifact/dataset reference. The same historical S25 TFLite vocoder target requested on CPU returned a finite unsaturated waveform at 4.04e-6 relative L2 / 107.86 dB SNR versus original ONNX CPU on the retained fixture. Its 100-sample component profile measured nearest-rank p50/p95 4.418/4.641 s, with all 738 execution-detail rows on CPU and reported inference peak memory 867,893,248 bytes. A separate 28-layer TFLite CPU-requested talker step returned 57 finite outputs, preserved ONNX CPU top-1 speech token 80, and had logits relative L2 3.33e-5 and maximum new-cache relative L2 3.41e-5. Its 100-sample component profile measured p50/p95 30.161/31.301 ms, with all 1,800 execution-detail rows on CPU and reported inference peak memory 1,929,318,400 bytes. The FP16 QNN talker step executed on the synthetic cache fixture but changed CPU top-1 speech token 80 to 412 with 8.99% logits relative L2 and maximum new-K/V relative L2 11.71%. This tested NPU artifact is numerically unqualified; no complete co-resident NPU/GPU stream exists. | Improve and revalidate the [talker artifact](../../../e2e_expansion_20260924/evidence/qwen_tts_talker_qualcomm/README.md), then qualify the [device-local predictor/vocoder pipeline](../../../e2e_expansion_20260924/evidence/qwen_tts_vocoder_qualcomm/README.md), output quality, recovery and 30-minute thermal behavior. |
|
||||
| Mobile Galaxy S25 / Snapdragon 8 Elite for Galaxy | Qwen3-TTS 0.6B CustomVoice | TALKER_FP16_NUMERIC_FAIL; CPU_TALKER_AND_VOCODER_NUMERIC_PROFILED; QNN_VOCODER_MEMORY_FAIL; SHORT_TFLITE_MIXED_COMPONENT_PROFILED; NOT_E2E_PROFILEABLE | Fresh FP16 predictor inference passed; its one output exactly matches the same compiled artifact/dataset reference. The same historical S25 TFLite vocoder target requested on CPU returned a finite unsaturated waveform at 4.04e-6 relative L2 / 107.86 dB SNR versus original ONNX CPU on the retained fixture. Its 100-sample component profile measured nearest-rank p50/p95 4.418/4.641 s, with all 738 execution-detail rows on CPU and reported inference peak memory 867,893,248 bytes. A separate 28-layer TFLite CPU-requested talker step returned 57 finite outputs, preserved ONNX CPU top-1 speech token 80, and had logits relative L2 3.33e-5 and maximum new-cache relative L2 3.41e-5. Its 100-sample component profile measured p50/p95 30.161/31.301 ms, with all 1,800 execution-detail rows on CPU and reported inference peak memory 1,929,318,400 bytes. The FP16 QNN talker step executed on the synthetic cache fixture but changed CPU top-1 speech token 80 to 412 with 8.99% logits relative L2 and maximum new-K/V relative L2 11.71%. A separately compiled FP16 QNN DLC talker also changed top-1 to 1720 with 8.77% logits relative L2 and 11.27% maximum new-cache relative L2. Both tested NPU talker artifacts are numerically unqualified. A fresh 25-frame FP16 QNN DLC vocoder compiled for S25, but its NPU-requested inference failed when Workbench reported device memory limits; it returned no waveform or profile samples. A [two-frame short-window export](../../../e2e_expansion_20260924/evidence/qwen_tts_vocoder_qualcomm/s25/qnn_short_chunk/README.md) matched local ONNX CPU at 2.96e-6 relative L2, then its separately compiled S25 FP16 QNN DLC also failed NPU-requested inference with the same reported device-memory limit. Its local HX370 WSL CPU component p50/p95 was 1.365/1.453 s to produce 0.16 s audio, not an S25 estimate. A separate [two-frame TFLite GPU-requested inference](../../../e2e_expansion_20260924/evidence/qwen_tts_vocoder_qualcomm/s25/tflite_short_chunk/README.md) returned finite unsaturated audio at 2.325% relative L2 / 32.67 dB SNR versus local ONNX CPU on one fixture; its 100-sample placement profile measured p50/p95 0.559/1.052 s for 0.16 s audio, with 403 CPU and 335 GPU execution-detail rows and 379,121,664 bytes reported peak. The mixed CPU/GPU component median RTF is 3.49; listening quality and playable streaming remain open. No complete co-resident NPU/GPU stream exists. | Improve and revalidate the [talker artifact](../../../e2e_expansion_20260924/evidence/qwen_tts_talker_qualcomm/README.md), then qualify the [device-local predictor/vocoder pipeline](../../../e2e_expansion_20260924/evidence/qwen_tts_vocoder_qualcomm/README.md), output quality, recovery and 30-minute thermal behavior. |
|
||||
| Mobile Galaxy S25 / Snapdragon 8 Elite for Galaxy | Qwen3.8-27B | NOT_E2E_PROFILEABLE | No complete qualified target artifact and device-local stateful Omni backend. Hub jobs provide component execution, not an on-device generation/streaming controller; ADB has no attached device. | Supply and validate the missing matching artifact/backend, then run the complete specified workload. |
|
||||
| Mobile Galaxy S25 / Snapdragon 8 Elite for Galaxy | MiniCPM-o 4.5 | COMPONENT_FP16_SPEECH_HEAD_NPU_NUMERIC_PROFILED; NOT_E2E_PROFILEABLE | Fresh FP16 speech-head inference passed; all 41 outputs exactly matched the same artifact/dataset reference. Against the recovered original ONNX CPU source on the same fixture, logits relative L2 was 0.3605%, maximum new-K/V relative L2 1.311%, and top-1 speech token 1867 matched. Historical FP16 parity passed; tested W8A16 top-1 parity failed. The 100-sample component profile had p50/p95 7.197/7.615 ms, with all 1,029 execution-detail rows on NPU and reported inference peak memory 185,991,168 bytes. Generated-audio quality and qualified thinker/encoders/vocoder remain unverified. | Qualify a complete mobile checkpoint/export and the full multimodal/stateful pipeline; [speech-head evidence](../../../e2e_expansion_20260924/evidence/minicpmo_tts_qualcomm/README.md). |
|
||||
| Mobile Galaxy S25 / Snapdragon 8 Elite for Galaxy | InternVLA-A1 | COMPONENT_COSMOS_NPU_NUMERIC_PROFILED; SYNTHETIC_ACTION_SENSITIVITY_MEASURED; NOT_E2E_PROFILEABLE | The real Place_Markpen Cosmos image encoder FP32 ONNX export matched its source on two six-frame fixtures. Galaxy S25 FP16 QNN DLC inference returned a finite latent within 0.0524% relative L2 / 65.61 dB SNR of the pinned pattern source. Injecting this device latent into the same real policy on local CPU changed synthetic `[1,50,32]` actions by 0.742% relative L2; the CPU source repeated bitwise identically. The 100-sample six-frame encoder profile had nearest-rank p50/p95 49.665/51.382 ms, all 121 execution-detail rows on NPU, and a reported inference peak of 158,232,576 bytes. No real-observation task tolerance exists, and the action policy was not resident on S25. ADB has no attached device. | Extend the [S25 encoder component](../../../e2e_expansion_20260924/evidence/internvla_cosmos_qualcomm/README.md), then validate real action quality, device-local state, admission, cancellation and sustained behavior. |
|
||||
|
||||
@@ -13,6 +13,24 @@ three-stage text-to-speech functional pass after correcting request embeddings,
|
||||
and an InternVLA real-weight synthetic action forward. Model-quality and device gates
|
||||
remain open; the 2026-09-22 audit remains the historical baseline.
|
||||
|
||||
The [2026-09-24 Spark BF16 WSL CPU evidence](../../benchmarks/edge_harness/results/e2e_expansion_20260924/evidence/spark_bf16_wsl_cpu/README.md)
|
||||
adds a complete pinned dense checkpoint to the fork-branch M0 text route. Twelve
|
||||
128-token requests passed and exactly matched standalone vLLM greedy tokens;
|
||||
one warmup plus 20 serial 64-token requests measured complete-request
|
||||
p50/p95 **5.411/5.751 s** and TTFT **0.129/0.146 s** on HX370 WSL CPU.
|
||||
This closes only the stated BF16 text workload, not M1 mobile generation.
|
||||
For M2, a [two-frame S25 vocoder export](../../benchmarks/edge_harness/results/e2e_expansion_20260924/evidence/qwen_tts_vocoder_qualcomm/s25/qnn_short_chunk/README.md)
|
||||
matched local eager/ONNX CPU on one fixed window, but its FP16 QNN DLC failed
|
||||
NPU-requested inference at the hosted device-memory limit. The earlier
|
||||
25-frame FP16 artifact failed the same memory gate. Different precision or
|
||||
graph layout, and a complete device-local stream, remain separate work.
|
||||
A [TFLite GPU-requested two-frame S25 component](../../benchmarks/edge_harness/results/e2e_expansion_20260924/evidence/qwen_tts_vocoder_qualcomm/s25/tflite_short_chunk/README.md)
|
||||
returned finite audio at 2.325% relative L2 against local ONNX CPU on one
|
||||
fixture. Its 100-sample component profile measured p50/p95 0.559/1.052 s
|
||||
for 0.16 s audio, with 403 CPU and 335 GPU node rows and median component
|
||||
RTF 3.49. It still needs listening quality and playable complete streaming
|
||||
before M2 can advance.
|
||||
|
||||
The [Spark hosted Qualcomm component expansion](../../benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/spark_s24_full_attention/README.md) advances M1 only to one real fixed-shape decoder attention layer. The same W8A16 QNN DLC ran on S24, Snapdragon X Elite CRD and SA8775P ADP NPUs with identical outputs on one pinned fixture; S25 had prior separate component evidence. On [RB3 Gen 2](../../benchmarks/edge_harness/results/e2e_expansion_20260923/evidence/spark_rb3_full_attention/README.md), the tested W8A16 graph failed QNN loading even after an exact-device compile. FP32 ONNX ran on CPU with near-source parity, while calibrated W8A8 ran on NPU but had 20.9% hidden-state relative L2 and remains numerically unqualified. These are component C results, not full M1: device-local 28-layer prefill/continuous decode, KV/ring, sampling, token quality, admission/cancellation, complete-request timing and sustained power/thermal gates remain open. AI Hub is the test facility, not a deployment dependency.
|
||||
|
||||
The [Qwen3-TTS Code2Wav Qualcomm follow-up](../../benchmarks/edge_harness/results/e2e_expansion_20260924/evidence/qwen_tts_vocoder_qualcomm/README.md) adds a retained same-fixture numerical check to M2. A fresh SA8775P GPU-requested output saturated 96.63% of samples and differs from original ONNX CPU by 11.832 relative L2, so that route fails the numerical gate despite profiling. The same binary's CPU-requested output on the exact SA device matched original ONNX CPU within 4.13e-6 relative L2; its 100-sample CPU-requested component profile passed placement (738/738 execution-detail rows on CPU) at nearest-rank p50/p95 5.384/5.534 s, still without a full stream. A FP32-preserving GPU-option control still saturated 84.89% of samples, so that option did not fix the tested route. RB3 TFLite GPU-requested inference returned an unsaturated but 15.73%-relative-L2 divergent waveform; its fresh 100-sample mixed CPU/GPU component p50/p95 was 3.099/3.133 s. The same binary requested on exact-RB3 CPU matched original ONNX CPU within 4.13e-6 relative L2 on the retained fixture; its 47-sample component profile measured p50/p95 12.727/13.424 s with all 738 execution-detail rows on CPU. That measured component latency is a major blocker for playable streaming on this route. A one-fixture-calibrated RB3 INT8 QNN vocoder returned a finite but 66.93%-relative-L2 divergent waveform (3.49 dB SNR) versus ONNX CPU, with 100 NPU component samples at p50/p95 1.971/1.992 s and all 728 execution-detail rows on NPU; it fails the numerical gate even on its calibration fixture. X Elite ONNX CPU inference matched the local ONNX Runtime output with 8.09e-7 relative L2; its 94-sample component profile was p50/p95 6.384/6.644 s with all execution-detail rows on CPU. Corrected DirectML inference and profile both failed during provider initialization; separate FP16 QNN DLC inference returned an unsaturated waveform at 1.138% relative L2 / 38.88 dB SNR versus local ONNX CPU, but its placement profile timed out during QNN graph preparation without samples. A separate SA8775P FP16 QNN DLC vocoder compile passed, but NPU-requested same-fixture inference failed after compilation without waveform or placement samples. Fresh S24 and S25 CPU-requested TFLite vocoder inferences matched ONNX CPU within 4.04e-6 relative L2 on the retained fixture. S25 measured 100 component samples at p50/p95 4.418/4.641 s with all 738 execution-detail rows on CPU; S24 measured 100 at 4.826/4.958 s with all 738 rows on CPU. Separate explicit INT8 and W8A16 QDQ ONNX exports checked on local ORT CPU failed the same-fixture numerical gate at 246.97% and 331.83% waveform relative L2, respectively. S25 CPU talker inference preserved token 80 and its 100-sample component profile measured p50/p95 30.161/31.301 ms with all 1,800 rows on CPU. M2 still requires a quality-passing talker/predictor/vocoder set, device-local co-residency and handoff, playable streaming and sustained memory/power validation.
|
||||
|
||||
Reference in new issue
Block a user