Orin TensorRT FP32 部署與 A/B 量測
歷史結論快照(2026-09-04) · orin-agx-1 · SenseVoice v5.8.0
結論:採用 TensorRT FP32。Orin 圖層推論在 3/6 秒快 1.83–1.86 倍、15 秒快 1.16 倍;
KITT 服務層的 3/6/15 秒 final recognizer 延遲快 1.10–2.09 倍,辨識文字一致。RTX 4090 與 Orin 都受益,
但平台內加速幅度不同;目前部署的 cache-warm TRT 服務常駐 RSS 約 9.20 GB。
真正預建的 EP context model 在隔離 sherpa-onnx 程序中,recognizer-ready PSS 則由 cache-warm 的 5.66 GB
降到 0.96 GB,session 載入中位數由 21.74 秒降到 11.42 秒。
新增的上限量測顯示 T=2000 時 TRT 反而慢 12.5%,因此 120 秒 profile 是相容上限,不代表該長度仍有加速。
1 · 結論與計畫
目標是先保留既有 CUDA FP32 基準,再只對 Orin 主 SenseVoice 模型切換 ORT TensorRT EP;TurnSense 維持 CUDA,模型與精度不變。
- 設計:2026-09-04-orin-tensorrt-deployment-design.md
- 計畫:2026-09-04-orin-tensorrt-deployment.md
- 4090 對照來源:2026-09-01-model-quantization-eval.html 第 7.2/7.5 節
- 部署映像:
v5.8.0-dirty-orin@sha256:69012fbc…afce4
2 · 代號與名詞
2.1 ID 對照
| ID | 定義 |
|---|---|
A1 | Orin runtime image 的 TensorRT 動態函式庫閉包完整。 |
A2 | 只有 Orin 主模型改成 TensorRT FP32,其他部署與 TurnSense 不變。 |
A3 | 動態 shape profile 與目標機持久 engine cache 生效。 |
A4 | TensorRT 不得靜默整體降級;以程序 maps、cache、provider guard 交叉驗證。 |
A5 | CUDA 與 TensorRT 以固定 seed、相同音檔和 warm-up 公平比較。 |
A6 | 離線與 Orin live 行為回歸結果完整揭露。 |
A7 | 以全新 Pod/程序分開量 CUDA、TRT cache-warm 與 TRT offline/預建的啟動及 3/6/15 秒記憶體。 |
R1 | 重測兩平台相同 FP32 模型、tokens 與固定音訊。 |
R2 | 固定形狀圖層延遲及獨立 profiler provider 證據。 |
R3 | 全新 recognizer 程序的載入與記憶體;本次未涵蓋 fresh-Pod cgroup 同尺比較。 |
R4 | CUDA/TRT 各三輪 WebSocket bulk/realtime 服務量測。 |
R5 | 逐項歷史比較,揭露不可比條件與文字重複性。 |
2.2 名詞定義
| 名詞 | 本輪含義與重要性 |
|---|---|
| ORT / EP | ONNX Runtime 與 Execution Provider;EP 決定每一段圖由 TensorRT、CUDA 或 CPU 執行。 |
| TensorRT online compile | 用原始 ONNX 在目標 GPU 建 engine;本輪 Orin cold build 約 68.19 秒。這是一次性的 artifact 建置,不是服務載入成本。 |
| TensorRT engine cache / cache-warm | 已有 sm87 engine cache,但 ORT 仍讀原始 ONNX、切圖及建立 network 以算 cache key;命中 cache 不等於 offline compile。 |
| TensorRT offline/預建 | 用 ORT EP context model 直接引用已編譯的 sm87 engine,只做 deserialize;本輪原始 ONNX 移開後仍可由 sherpa-onnx 載入並辨識。 |
| FP32 | 32-bit 浮點。本輪固定精度,避免把量化收益混進 provider 比較。 |
| 圖層 | 沿用 2026-09-01 報告的術語:固定 shape 的合成 feature 直接執行 ONNX graph;不包含 fbank/LFR/CMVN、stream 建立、ITN 或 WebSocket。 |
| 服務層 | 沿用 2026-09-01 報告的術語:包含 sherpa-onnx recognizer 前端與解碼。本輪由 KITT WebSocket 路徑觸發,表中數字是服務端 final recognizer latency,不是包含送音時間的 client 端到端時間。 |
| bulk / realtime | 本輪服務層的兩種送音模式:bulk(快速送音)仍切成 20 ms frame、但不按牆鐘等待;realtime(20 ms 即時送音)每送一個 frame 等待約 20 ms,模擬 Web UI。 |
| p50 / p95 | 第 50 / 95 百分位延遲;圖層各跑 50 次,避免只用單次最好值。 |
| RTF | Real-Time Factor,推論時間除以音訊時間;小於 1 才能快於即時播放。 |
| RSS / PSS / cgroup | RSS 是程序映射的常駐頁,會重複計入共用 library/檔案頁;PSS 按共享比例分攤;Pod cgroup 是該隔離量測實際被計帳的統一記憶體。Orin 無法再拆成獨立 CPU RAM 與 GPU VRAM。 |
| sm87 / sm89 | NVIDIA GPU compute capability 代號;Orin 是 sm87、RTX 4090 是 sm89。TensorRT engine 綁定 GPU 架構,必須在各目標機重建,不可直接跨機搬移。 |
| VAD | 語音活動偵測;它提供開始與停止事件,界定 STT turn 與 final 時機。 |
| fbank / LFR / CMVN | 音訊特徵、低幀率堆疊與正規化;TurnSense golden 的 3 個 macOS 差異發生在這條前處理,不是 TensorRT 主模型。 |
3 · Orin A/B 與 4090 對照
圖層:固定 seed synthetic feature,T=50/100/250,各 10 次 warm-up + 50 次正式執行。服務層:同一組 3/6/15 秒 WAV、3 次 warm-up、單一 WebSocket series。
3.1 圖層
| 硬體 | 約當音訊 | CUDA FP32 p50 | TRT FP32 p50 | TRT p95 | 加速 |
|---|---|---|---|---|---|
| RTX 4090(sm89) | 3 秒(T=50) | 26.35 ms | 6.14 ms | — | 4.29×(-76.7%) |
| Orin AGX(sm87) | 3 秒(T=50) | 36.30 ms | 19.83 ms | 19.89 ms | 1.83×(-45.4%) |
| RTX 4090(sm89) | 6 秒(T=100) | 26.59 ms | 6.19 ms | — | 4.30×(-76.7%) |
| Orin AGX(sm87) | 6 秒(T=100) | 37.07 ms | 19.97 ms | 20.03 ms | 1.86×(-46.1%) |
| Orin AGX(sm87) | 15 秒(T=250) | 45.18 ms | 38.84 ms | 38.93 ms | 1.16×(-14.0%) |
4090 的上一份報告只記錄 T=50/100 的 p50,沒有 p95,也沒有同尺的 T=250;缺值不以推測補齊。
3.2 服務層(KITT WebSocket 路徑)
測試經過真正的 WebSocket 與 frame 流程,但表內取 final frame 的 server_latency_ms:
服務端準備 recognizer stream、等待 recognizer lock、解碼及 ITN 的時間;不包含 3/6/15 秒送音時間或
WebSocket/client backlog。因此它是上一份報告所稱的「服務層」,不是完整產品端到端延遲。
| 送音模式 | 音訊 | CUDA final recognizer 延遲 | TRT final recognizer 延遲 | 加速 |
|---|---|---|---|---|
| bulk(快速送音) | 3 秒 | 89.26 ms | 51.75 ms | 1.72×(-42.0%) |
| bulk(快速送音) | 6 秒 | 112.76 ms | 60.50 ms | 1.86×(-46.3%) |
| bulk(快速送音) | 15 秒 | 258.13 ms | 218.89 ms | 1.18×(-15.2%) |
| realtime(20 ms 即時送音) | 3 秒 | 79.75 ms | 45.28 ms | 1.76×(-43.2%) |
| realtime(20 ms 即時送音) | 6 秒 | 98.52 ms | 47.25 ms | 2.09×(-52.0%) |
| realtime(20 ms 即時送音) | 15 秒 | 193.56 ms | 175.51 ms | 1.10×(-9.3%) |
六組都由 TensorRT 較快;3/6 秒降幅 42–52%,15 秒降幅縮至 9–15%,所以不能只用短句倍數外推長句。
3.3 同 shape 圖層:兩平台各自的 CUDA/TRT 收益
兩份報告都使用出貨中的 SenseVoice FP32 graph、batch 1、相同動態 profile
T=1/100/2000,且都有 T=50/100 的 p50;這是跨硬體最接近同口徑的一組。
同尺數據已合併在 第 3.1 節;兩台平台都從 TRT 受益,但平台內收益不同:
4090 約 4.30 倍,Orin 約 1.83–1.86 倍。
相同 T 下,4090 與 Orin 的 TensorRT bar 都短於各自 CUDA;4090 的平台內收益約 4.3×、Orin 約 1.83–1.86×。這證明收益高度依賴硬體與軟體棧,不能把 4090 的倍數直接外推到 Orin。
3.4 服務層:兩份報告只能比較平台內收益
4090 的數字是 sherpa-onnx recognizer 端到端 p50,Orin 是由實際 WebSocket 路徑觸發的 final recognizer latency, 量測邊界、輸入組合與執行環境不同,所以 14.32 ms 與 Orin 的絕對延遲不能當成硬體排名。能安全比較的是 同一列內從 CUDA 切到 TRT 的方向與比例:4090 是 1.22 倍,Orin 的六組服務路徑是 1.10–2.09 倍。
| 平台 | 量測邊界 | CUDA FP32 | TRT FP32 | 平台內加速 |
|---|---|---|---|---|
| RTX 4090 | sherpa-onnx recognizer 端到端 p50 | 14.32 ms | 11.75 ms | 1.22× |
| Orin AGX | KITT 服務端 final recognizer latency;bulk / realtime、3 / 6 / 15 秒 | 79.75–258.13 ms | 45.28–218.89 ms | 1.10–2.09× |
4090 原報告另記錄三次服務層結果為 1.07×/1.22×/1.31×,共用 GPU 的變異較大; 因此本表用 1.22× 作該次正式列值,但不主張它比 Orin 的收益低。來源: 4090 報告第 7.5.3 節。
3.5 Orin 圖層最大 profile:延遲與記憶體
這一節只回答「直接執行 ONNX graph 到最大 profile」;3/6/15 秒 sherpa-onnx recognizer 的 啟動及推論後記憶體另列於 第 3.6 節,部署中服務的穩態 RSS 則列於 第 7.2 節。
同一個 FP32 ONNX、batch 1、T=2000、固定 seed,各 provider 在獨立 NVIDIA Kubernetes Job
執行 3 次;穩態延遲取後兩次中位數。CUDA profiler 記到 CUDA 與 CPU shape-op 節點,TRT profiler
只記到 TensorrtExecutionProvider,沒有 CUDA/CPU 節點 fallback。
| Provider | 穩態延遲 | session ready cgroup | T=2000 後 cgroup | 長句增量 | T=2000 後 RSS | VmHWM |
|---|---|---|---|---|---|---|
| CUDA FP32 | 474.24 ms | 2,189 MB | 3,229 MB | +1,040 MB | 3,277 MB | 3,342 MB |
| TensorRT FP32 | 533.47 ms | 6,503 MB | 6,779 MB | +276 MB | 7,237 MB | 8,592 MB |
T=2000 後的 Job cgroup
比 CUDA 高 3,550 MB,程序 RSS 高 3,960 MB;但從 session ready 到最大 shape 的額外配置只有
276 MB,比 CUDA 的 1,040 MB 少 73.5%。速度曲線也翻轉:TRT 533.47 ms 比 CUDA 474.24 ms 慢 12.5%。
因此 TRT 適合目前 3–6 秒正常語音,但最大錄音時限仍應落實,不能假設超長語音也有相同加速。Orin 使用統一記憶體,cgroup 與程序 RSS 是兩個獨立 Job 間的主要比較尺。tegrastats
量的是全機 RAM;量測時 production TRT service 與 cache 已常駐,因此其全機增量只作交叉檢查,不當成
TRT 的獨立總 footprint。
3.6 sherpa-onnx 啟動與 3/6/15 秒統一記憶體
每列都在全新 NVIDIA Kubernetes Pod/Python process 中載入同一個 FP32 模型、num_threads=2,
先解一次相同 3 秒 WAV 暖機,再解指定 3/6/15 秒 WAV。TRT cache-warm 命中 persistent engine cache,
但仍讀原始 ONNX、切圖並建立 network;TRT offline 則以 12,273-byte EP context model 直接引用
984,896,180-byte sm87 engine。
| 載入方式 | 音訊 | session 載入 | ready RSS | ready PSS | ready cgroup | 推論後 RSS | 推論後 PSS | 推論後 cgroup | 取樣峰值 RSS / cgroup |
|---|---|---|---|---|---|---|---|---|---|
| CUDA FP32 | 3 秒 | 3.46 s | 2,817.7 MB | 1,649.8 MB | 1,625.5 MB | 2,861.2 MB | 1,676.0 MB | 1,637.3 MB | 2,861.2 / 1,658.0 MB |
| CUDA FP32 | 6 秒 | 3.65 s | 2,831.7 MB | 1,663.8 MB | 1,639.5 MB | 2,920.8 MB | 1,735.2 MB | 1,690.0 MB | 2,920.8 / 1,690.3 MB |
| CUDA FP32 | 15 秒 | 3.58 s | 2,849.6 MB | 1,681.9 MB | 1,657.5 MB | 2,963.4 MB | 1,778.2 MB | 1,733.0 MB | 2,963.4 / 1,733.3 MB |
| TRT FP32 · cache-warm | 3 秒 | 21.29 s | 7,097.3 MB | 5,656.6 MB | 5,497.3 MB | 7,127.0 MB | 5,664.0 MB | 5,523.9 MB | 7,852.1 / 6,627.3 MB |
| TRT FP32 · cache-warm | 6 秒 | 21.74 s | 7,095.8 MB | 5,655.3 MB | 5,486.2 MB | 7,141.5 MB | 5,662.7 MB | 5,525.0 MB | 7,850.6 / 6,568.1 MB |
| TRT FP32 · cache-warm | 15 秒 | 22.55 s | 7,100.3 MB | 5,659.8 MB | 5,475.2 MB | 7,162.0 MB | 5,667.2 MB | 5,529.9 MB | 7,855.1 / 6,573.7 MB |
| TRT FP32 · offline EP context | 3 秒 | 11.26 s | 2,218.1 MB | 961.9 MB | 958.8 MB | 2,264.6 MB | 986.6 MB | 975.3 MB | 2,366.7 / 1,340.4 MB |
| TRT FP32 · offline EP context | 6 秒 | 11.42 s | 2,218.0 MB | 962.0 MB | 897.5 MB | 2,292.6 MB | 998.7 MB | 925.9 MB | 2,403.5 / 1,277.3 MB |
| TRT FP32 · offline EP context | 15 秒 | 11.60 s | 2,218.1 MB | 962.0 MB | 897.6 MB | 2,326.1 MB | 1,015.8 MB | 943.3 MB | 2,400.4 / 1,305.3 MB |
TensorrtExecutionProvider 節點事件。以三次中位數比較,offline 的 ready PSS 為 962 MB,
比 cache-warm 的 5,657 MB 少 83.0%;ready cgroup 約 898 MB,比 5,486 MB 少 83.6%;session 載入也快 47.5%。Orin 的 CPU 與 GPU 共用 LPDDR,因此不存在可另外填的 per-process GPU VRAM。RSS 會把共用 TensorRT library/檔案頁整份算進每個 process,
所以部署容量判斷應優先看 PSS 與 Pod cgroup;tegrastats 的 RAM 是全機值,只作交叉檢查。
4 · 實作與驗收
- Orin image 加入 TensorRT 10.3 runtime libraries,build-time
ldd擋 unresolved dependency。 config-k3s-orin.yaml覆寫主模型為trt:/app/config-trt-orin.config;base 仍是 CUDA。- profile:batch=1,T=1/100/2000;engine/timing cache 掛到
/data/srdc/kitt-stt-trt-cache。 - Pod 內確認
libnvinfer.so.10與 ORT TRT provider 常駐,產出 984,899,100-bytesm87.engine。
| ID | 結果 | 證據 |
|---|---|---|
| A1 | ✓ PASS | Docker build assertion + Pod ldd 無 not found。 |
| A2 | ✓ PASS | 主模型 TRT FP32;TurnSense log 顯示 CUDAExecutionProvider。 |
| A3 | ✓ PASS | sm87 engine/profile/timing cache 均非空且持久掛載。 |
| A4 | ✓ PASS | /proc/1/maps 有 libnvinfer;provider guard 通過。 |
| A5 | ✓ PASS | 同尺圖層與服務層 3/6/15 秒 A/B 已完成。 |
| A6 | ⚠ PARTIAL | 功能路徑通過;完整套件有 3 個 macOS golden 差異與 1 個 production-disabled debug endpoint。 |
| A7 | ✓ PASS | CUDA、TRT cache-warm、TRT offline EP context 均以全新 Pod/process 完成啟動與 3/6/15 秒記憶體量測。 |
✅ 5 · 測試結果(累積追溯表)
所有測試的累積結果。這張表只增不減——過去每一輪的測試都要繼續通過。
依 docs/spec.md CLAUDE.md section 8 第 4 點,此表只增不減:沿用歷輪聯集的所有列,
只新增或更新(SW-DOC-02 機械把關)。
離線完整套件:615 passed / 3 failed / 3 skipped。3 個失敗都在
turnsense/test_frontend.py 的 Linux golden 與 macOS ARM 計算結果逐位元比較,最大差
6.51e-05;與 TensorRT 路徑無關。Orin live:38 passed / 1 failed;唯一失敗是
K3s 安全設定刻意關閉無驗證的 /debug/logs,該測試取得預期的 404。推論、壓力、多人、
wake、bypass、timeout 與動態設定案例均通過。
本輪直接相關的 test_trt_provider_guard.py:19 passed / 1 skipped;
另含平台不相容時正確跳過的 patched binding 模組。
(a) Feature 總覽
計數基準:數的是行為契約(SW_id)的條數,不是測試個數——多條 SW_id
可共用同一個測試檔。驗證方式(離線/live)不影響分組,只出現在「測試」欄。
| PRD F_id | Feature | 有 STT SW_id? | 條數 | 最近驗證 |
|---|---|---|---|---|
| F_1 | 多音區識別/控制 | ✗ 下游 / OOS(權限·多區) | — | —(STT 提供 per-user_id hook) |
| F_2 | One-shot(喚醒詞 + 指令連說) | ✓ SW-W-03/04/05/08/09 · SW-WM-01 | 6 | ✓ PASS 6 / 6 |
| F_3 | 聆聽等待智慧斷句 | ✓ SW-W-01/10/11/13 · SW-X-01/02 · SW-TURN-01/02/03 · SW-WM-02 · SW-EOT-01/02/03/04(EOT 四條承接自 2026-08-12/2026-08-27) | 14 +1 廢止 | ⚠ PARTIAL SW-EOT-03 的 macOS golden 3 個 case 未逐位元相同 |
| F_3.4c | 最大錄音時限自動停止 | ✗ MISSING(GAP-1,Cycle 1 起追蹤) | — | 仍未解決,且不是 kitt-stt 的:2026-08-31 那一輪查證歸屬在 kitt-web-ui(vad.py::stop_user_vad() 加一個 max-utterance-duration watchdog,與現有 audio-stall watchdog 對稱)。⚠️ 2026-09-01 量化評估輪與它相關的一點是 前輪長句 profile 追蹤:TensorRT 的 shape profile 是硬邊界,若採用 GPU 路線,解碼長度上限就從「品質議題」變成「不加就會拋錯」(CLAUDE.md section 7.4.8) |
| F_4.1 | 語音打斷_背景併行 | ✗ 下游(DM/TTS) | — | — |
| F_4.2 | 語音打斷_後令壓前令 | ✗ 下游(DM 仲裁) | — | — |
| F_4.3 | 語音打斷 Barge-in / 解除喚醒 | ✓ SW-X-04 · SW-WM-03 | 2 | ✓ PASS 2 / 2 |
| F_5 | 連續指令 | ✗ 下游(NLU 拆解) | — | — |
| F_6 | 上下文理解 | ✗ 下游(DM 快取) | — | — |
| STT_EXTRA | 免喚醒 / WebUI 按鈕 / 自定義 / ITN / 排程韌性 | ✓ SW-B/UI/CFG/X/PERF/ITN | 20 +2 廢止 | ✓ PASS 20 / 20 |
| SW_id | 行為 | 測試(file::test) | 最近驗證 |
|---|---|---|---|
| SW-W-03 | 喚醒詞 + 指令連說(句首過濾喚醒詞) | test_wake::test_wake_immediate | ✓ PASS |
| SW-W-04 | 喚醒詞 <停頓> 指令 | test_wake::test_wake_pause | ✓ PASS |
| SW-W-05 | 喚醒詞不在句首不觸發 | test_standby::test_standby_wake_not_at_start | ✓ PASS |
| SW-W-08 | Active 句首喚醒詞過濾 | test_active::test_active_wake_filter | ✓ PASS |
| SW-W-09 | Active 句首喚醒詞 + smart-turn | test_active::test_active_smart_turn_wake_head | ✓ PASS |
| SW-WM-01 | 喚醒詞比對與剝除:大小寫無關、分隔字元剝除、喚醒詞後可直接接指令、剝除後指令完整保留(F_2.1/F_2.2) | test_wake_matcher.py(56,offline) | ✓ PASS |
| SW_id | 行為 | 測試(file::test) | 最近驗證 |
|---|---|---|---|
| SW-W-01 | 非喚醒不出文字、不往後送 | test_standby::test_standby_rejection | ✓ PASS |
| SW-W-10 | Active smart-turn 跨段黏合 | test_active::test_active_smart_turn | ✓ PASS |
| SW-W-11 | Active 第二句喚醒詞不過濾 | test_smart_turn_wake::test_active_smart_turn_wake_2nd | ✓ PASS |
SW-W-02 互斥),由 SW-W-13 取代 | — | 廢止 | |
| SW-W-13 | Standby 第一句未命中 → turn 關閉,第二句喚醒詞正常觸發 | test_smart_turn_wake::test_standby_smart_turn_wake_2nd | ✓ PASS |
| SW-X-01 | Timeout 15s 回 standby | test_timeout::test_timeout_deactivate | ✓ PASS |
| SW-X-02 | 重新喚醒後 timeout 重算 | test_timeout::test_timeout_reset | ✓ PASS |
| SW-TURN-01 | 一個 turn 只有第一個 VAD segment 是 turn head,其餘為續段、不跑偵測 | test_turn_arbitration.py(11,offline) | ✓ PASS |
| SW-TURN-02 | 續段送出權依 bypass 種類授權:prefix 授予、exact 不授予 | 同上 | ✓ PASS |
| SW-TURN-03 | 新 turn head 清除上一個 turn 的指令送出權,續段則保留 | 同上 | ✓ PASS |
| SW-WM-02 | alias 只買回實測誤聽,不得擴大誤觸發(F_3.4b) | test_wake_matcher.py(含於 0) | ✓ PASS |
| SW_id | 行為 | 測試(file::test) | 最近驗證 |
|---|---|---|---|
| SW-X-04 | 解除喚醒詞(退下/安靜/離開/暫停)→ 切 Standby | test_exit_word(offline,0) | ✓ PASS |
| SW-WM-03 | 退出詞 alias 必須錨定到已設定的退出詞(F_4.3.2) | test_wake_matcher.py(含於 0) | ✓ PASS |
| SW_id | 行為 | 測試(file::test) | 最近驗證 |
|---|---|---|---|
| SW-B-01 | Prefix 觸發整句往後送 | test_bypass_prefix::test_prefix_trigger | ✓ PASS |
| SW-B-02 | Prefix 不在句首不觸發 | test_bypass_prefix::test_prefix_not_at_start | ✓ PASS |
| SW-B-03 | Prefix + smart-turn 合併 | test_bypass_prefix::test_prefix_smart_turn | ✓ PASS |
SW-B-10 取代 | — | 廢止 | |
| SW-B-05 | 特定指令觸發往後送 | test_bypass_cmd::test_cmd_trigger | ✓ PASS |
| SW-B-06 | 特定指令不在句首不觸發 | test_bypass_cmd::test_cmd_not_at_start | ✓ PASS |
| SW-B-07 | 特定指令句中夾雜其他話不觸發 | test_bypass_cmd::test_cmd_extra_words | ✓ PASS |
| SW-B-08 | 特定指令 smart-turn 第一句只傳指令(2026-08-17 修復) | test_bypass_cmd::test_standby_cmd_smart_turn | ✓ PASS |
SW-B-11 取代 | — | 廢止 | |
| SW-B-10 | 第二句句首 Prefix 正常觸發 | test_smart_turn_bypass::test_standby_smart_turn_prefix_2nd | ✓ PASS |
| SW-B-11 | 第二句句首特定指令正常觸發 | test_smart_turn_bypass::test_standby_smart_turn_cmd_2nd | ✓ PASS |
| SW-X-03 | 按 WebUI 按鈕回 standby | test_btn_control::test_btn_deactivate | ✓ PASS |
| SW-UI-01 | WebUI 按鈕啟動喚醒;按鈕喚醒後說話辨識往後送 | test_btn_control::test_btn_activate · ::test_btn_standby_voice | ✓ PASS |
| SW-UI-03 | 連點切換穩定(active) | test_btn_control::test_btn_rapid_toggle_active | ✓ PASS |
| SW-UI-04 | 連點後語音喚醒 | test_btn_control::test_btn_rapid_toggle_wake | ✓ PASS |
| SW-UI-05 | 講話中切 standby 不卡字 | test_btn_control::test_btn_standby_mid | ✓ PASS |
| SW-UI-06 | 講話中切 mic 靜音,WebUI 不卡字 | —(web-ui 側,無 STT 測試) | OOS |
| SW-MU-01..08 | 多使用者/多車喚醒同步、隔離 沿用 2026-08-17 的區間寫法;該輪之後 main 也加入了多使用者併發的 live 測試,但那不在2026-09-01 量化評估輪範圍內 | —(web-ui 側;STT 提供 per-user_id / ?car= hook) | OOS |
| SW-CFG-01 | 客製化喚醒/免喚醒詞 | test_stt_config::test_custom_stt_config_active | ✓ PASS |
| SW-CFG-02 | 刪除客製化詞後不再觸發 | test_stt_config::test_custom_stt_config_deleted | ✓ PASS |
| SW-PERF-01 | 連續長句(≥90s):interim 重新解碼排程不得失控 | test_audio_stress(live,4) | ✓ PASS |
| SW-PERF-02 | 反應式 interim 排程的設定解析 | test_audio_cfg(0) | ✓ PASS |
| SW-ITN-01 | final 的 ITN:中文數字正規化 + 繁簡轉換 | test_text_converter::test_all | ✓ PASS |
| SW-ITN-02 | interim 只做 s2t()、final 做完整 itn()——兩者數字可不同是設計不是 bug | test_batch_asr_manager_itn_split(0) | ✓ PASS |
數量由 pytest --collect-only 直接輸出;「來源」欄為該檔首次加入的 cycle。
| SW_id | 行為 | 測試(數量) | 來源 | 最近驗證 |
|---|---|---|---|---|
| SW-OPS-01 | 模型解析:純函式保證、只在缺失時 pull、錯誤訊息須指名該跑的指令 | test_model_manager.py(15) | 2026-08-12 | ✓ PASS |
| SW-OPS-02 | 出貨模型五處一致:config、註冊表、三個 Dockerfile、deploy.sh、.dockerignore 白名單。2026-09-01 量化評估輪擴充:必要檔清單改由 quant_int8 推導(CLAUDE.md section 1.3) | test_augment.py(32,與 SW-FT-04 共用) | 2026-08-12 | ✓ PASS |
| SW-FT-01 | 訓練語料建構;AISHELL-3 全程只當評估、永不進訓練 | test_finetune_corpus.py(130) | 2026-08-12 | ✓ PASS |
| SW-FT-02 | MODEL/PRODUCT 雙軸、三軸判定、checkpoint 選擇規則 | test_finetune_eval.py(91) | 2026-08-12 | ✓ PASS |
| SW-FT-03 | LoRA 接線:不可達目標須拋錯、merge 後權重確實改變 | test_finetune_lora.py(52,finetune venv) | 2026-08-12 | 未跑(另一 venv) |
| SW-FT-04 | 波形增強;預設 AUG_RATIO=0(乾淨語料) | test_augment.py(與 SW-OPS-02 共用) | 2026-08-12 | ✓ PASS |
| SW-FT-05 | 論文基準計分不得與 產品驗收計分共用程式碼。2026-09-01 量化評估輪擴充:--model-file 精度選擇進 report JSON | test_paper_bench.py(27) | 2026-08-14 | ✓ PASS |
| SW-FT-06 | 2026-09-01 量化評估輪新增:模型量化匯出——sherpa-onnx metadata 在 INT8/FP16 後逐鍵存活;FP16 保持 fp32 graph I/O;INT8 參數只存在一處;finetune 匯出預設產生 int8 | test_quantize_bundle.py(10) | 2026-08-18 | ✓ PASS |
| SW-FT-07 | 2026-09-01 量化評估輪新增:量測後端可換為 ONNX——--onnx-dir 與 --init-param 互斥;付費語料快取缺失時不得計費(先檢查、後請求) | test_eval_onnx_backend.py(19) | 2026-08-18 | ✓ PASS |
| SW-FT-08 | 2026-09-01 量化評估輪新增:運算子的裝置可攜性——量化替換掉的運算子在目標 provider 上是被接受還是退回 CPU,必須能在沒有語料的邊緣機器上重新量測;且「provider 未載入」與「運算子退回」必須分開報告(混為一談會把假的 GPU 量測讀成真的) | test_op_support.py(26) | 2026-08-18 | ✓ PASS |
| SW-OPS-05 | 2026-09-01 量化評估輪新增:live 測試 harness 不得產生 false pass——tests/docker-test.sh 重用映像的新鮮度檢查,必須涵蓋 Dockerfile 所有 COPY 進映像的路徑,且清單以 Dockerfile 為來源推導驗證而非手工維護。起因:漏看 sherpa-onnx/build 讓套件對著不是受測版本的 binding 跑出綠燈(CLAUDE.md section 7.5.5) | test_augment.py(32,與 SW-FT-04/SW-OPS-02 共用檔) | 2026-08-21 | ✓ PASS |
| SW-OPS-06 | 2026-09-01 量化評估輪新增:provider=trt 不得靜默降級成 CUDA,兩層——① TensorRT runtime closure、Orin FP32 profile、persistent cache;TensorRT EP 註冊失敗時 vendored sherpa-onnx 中止行程(CLAUDE.md section 7.7.3);② recognizer 建好之後 libnvinfer 未常駐則啟動失敗,涵蓋 engine 因 sm/TRT 版本不符反序列化失敗那一種(CLAUDE.md section 7.7.4)。起因:漏設 LD_LIBRARY_PATH 讓2026-09-01 量化評估輪量到一組標著 TensorRT、實際跑在 CUDA 的數字 | test_trt_provider_guard.py(20) | 2026-09-01 | ✓ PASS |
| SW-DOC-01 | 新測試檔必須在 SW 規格留下紀錄;規格不得引用已刪測試檔 | test_spec_traceability.py(3) | 2026-08-17 | ✓ PASS |
| SW-DOC-02 | 累積 ledger 對歷輪聯集只增不減;報告檔名須對應 cycle stem | test_report_integrity.py(2) | 2026-08-17 | ✓ PASS |
| SW-DOC-03 | 報告用到的技術名詞與報告自創的說法都必須在名詞表定義,且要寫出「2026-09-01 量化評估輪為什麼重要」而非可貼自維基的定義 | test_report_glossary.py(2) | 2026-08-21 | ✓ PASS |
| SW-DOC-04 | 每張圖需有 aria-label;每張數據圖需有 caption,且 caption 要寫出結論而非重複標題 | test_report_charts.py(2) | 2026-08-21 | ✓ PASS |
| SW-DOC-05 | 報告的 CLAUDE.md section N 交叉引用必須指得到章節——重新編號時同步改引用;既有 4 份報告的 12 個懸空引用列成明帳,只減不增 | test_report_crossrefs.py(12) | 2026-08-21 | ✓ PASS |
| SW-DOC-06 | 報告的 ID 對照表要逐項定義它引用的每個 A/D/E/F/R ID——只定義家族與範圍不算數 | test_report_ids.py(6) | 2026-08-21 | ✓ PASS |
| — | STT_LIVE_URI 解析——測試設施自身,刻意不給 ID | test_live_uri.py(3) | 2026-07-28 | ✓ PASS |
承接 main(rebase 併入,2026-09-01 量化評估輪未改動;離線與 live 全套一起重跑) | ||||
| SW-EOT-01 | STT 是唯一 EOT authority:每個 VAD stop 以語尾模型評分 turn tail(跨 segment、最後 8 秒),COMPLETE 立即結束 turn,其餘依 P(incomplete) 等待 | test_eot_state.py(13)· turnsense/test_policy.py(22) | 2026-08-12 | ✓ PASS |
| SW-EOT-02 | KWS 事件(standby 無匹配/離開詞/agent_standby/連線結束)一律丟棄 turn,不等語尾模型 | test_eot_kws_precedence.py(16) | 2026-08-12 | ✓ PASS |
| SW-EOT-03 | 語尾模型的音訊前處理必須與訓練時逐位元相同(fbank 80 → LFR 7/6 → CMVN) | turnsense/test_frontend.py(10) | 2026-08-12 | ⚠ 7 PASS / 3 FAIL macOS ARM 與 Linux golden 最大差 6.51e-05 |
| SW-EOT-04 | 語尾模型只在 CUDA 上執行:provider 未生效時伺服器拒絕啟動而非降級到 CPU與2026-09-01 量化評估輪 SW-OPS-06 同一種「不得靜默降級」的形狀 | turnsense/test_runtime.py(12) | 2026-08-12 | ✓ PASS |
| SW-OPS-03 | Per-turn debug log 檢索端點(GET <base>/debug/logs):關閉時回 404;開啟時依 WS 握手的 ?trace_id= 只取回該連線自己的 log | test_debug_log_endpoint.py(14)· test_debug_log_buffer.py(7)· test_debug_log_config.py(3)· live test_debug_logs.py | 2026-08-20 | ✓ PASS |
| SW-OPS-04 | 狀態頁設定介面:EOT 等待秒數的滑桿上下界即 clamp() 實際夾制的範圍;整頁只有一個儲存動作 | test_status_page_settings.py(3) | 2026-08-27 | ✓ PASS |
| SW-PERF-03 | 整車多人同時講話(1 連線 4 座位):排程不得因共用辨識器的鎖爭用而卡住,每個座位都要拿到自己的 final | test_interim_concurrency.py(13)· test_itn_off_frame_path.py(3)· live test_multiuser_concurrency.py(5) | 2026-08-18 | ✓ PASS |
| —(已移除) | 2026-08-31 | n/a | ||
| 合計 | 各來源列保留首次登記時的歷史題數,不能跨 cycle 直接相加;2026-09-04 的完整現況以本節頂端摘要為準。 | ⚠ 615 PASS / 3 FAIL / 3 SKIP | ||
6 · 架構與 Frame 資料流
6.1 STT SW stack
主 SenseVoice 圖優先交給 TensorRT;CUDA/CPU 只保留未支援節點的分區 fallback。TurnSense 獨立維持 CUDA,因此本輪速度差可歸因於主模型 provider。
6.2 Frame 處理流程
TensorRT 位於 final/interim 共用的 recognizer 底層,沒有改 frame 分支、喚醒判斷或 EOT;live 測試也顯示這些控制流程保持一致。
6.3 Frame I/O 契約
| Frame | 方向 | 觸發 | 動作 | 位置 |
|---|---|---|---|---|
| AudioRawFrame | IN | 每個音訊 chunk | preroll 或累積 utterance,排程 interim。 | kitt_stt_service.py:884 |
| VADUserStartedSpeakingFrame | IN | 開始說話 | 開啟 turn、重置 utterance 狀態。 | kitt_stt_service.py:679 |
| VADUserStoppedSpeakingFrame | IN | 停止說話 | 快照 buffer 並執行 final / TurnSense。 | kitt_stt_service.py:781 |
| InterimTranscriptionFrame | OUT | interim 文字改變 | 送出暫時文字。 | kitt_stt_service.py:1379 |
| TranscriptionFrame | OUT | final 可送出 | 送權威文字與 metadata。 | kitt_stt_service.py:1691 |
| TTSSpeakFrame | OUT | 純喚醒詞 | 送固定招呼語。 | kitt_stt_service.py:1812 |
7 · 記憶體、冷啟動與限制
7.1 Orin 部署限制
- 常駐 RSS:CUDA 約 4.02 GB;TRT 穩態約 9.20 GB,增加約 5.18 GB。TRT 首次建 engine 的 VmHWM 約 9.81 GB。
- 三種生命週期:online cold build 約 68.19 秒;cache-warm sherpa session 載入中位數 21.74 秒;offline EP context 載入中位數 11.42 秒。只有最後一種跳過 builder。
- profile 邊界:T 最大 2000,超界不是效能下降而是 shape 不符合;最大點 TRT 533.47 ms,較 CUDA 474.24 ms 慢 12.5%。最大錄音時限仍是跨 repo 的既有 gap。
- live 例外:
/debug/logs在 Orin K3s 刻意關閉,避免無驗證端點暴露實際語音 log,因此該單一 live case 不適用。 - 靜態 gate:本輪兩個 Python 修改檔 ruff lint/format 與 pyright 都是 0 error;全 repo 仍有既存的 ruff 29 項與 pyright 107 項型別債,本輪未擴張範圍修理。
7.2 4090/Orin 記憶體與資源對照
7.2.1 Orin 三種載入方式:offline 欄位
3/6/15 秒各一個全新 Pod;表內「中位數」取三個音長 arm 的中間值,15 秒列則直接取 15 秒 arm。
| 量 | CUDA FP32 | TRT FP32 · cache-warm | TRT FP32 · offline EP context |
|---|---|---|---|
| session 載入中位數 | 3.58 s | 21.74 s | 11.42 s |
| recognizer-ready RSS 中位數 | 2,831.7 MB | 7,097.3 MB | 2,218.1 MB |
| recognizer-ready PSS 中位數 | 1,663.8 MB | 5,656.6 MB | 962.0 MB |
| recognizer-ready cgroup 中位數 | 1,639.5 MB | 5,486.2 MB | 897.6 MB |
| 15 秒推論後 RSS | 2,963.4 MB | 7,162.0 MB | 2,326.1 MB |
| 15 秒推論後 PSS | 1,778.2 MB | 5,667.2 MB | 1,015.8 MB |
| 15 秒推論後 cgroup | 1,733.0 MB | 5,529.9 MB | 943.3 MB |
| 取樣峰值 cgroup 中位數 | 1,690.3 MB | 6,573.7 MB | 1,305.3 MB |
| 獨立 GPU VRAM | 不適用 | 不適用 | 不適用 |
這是隔離 sherpa-onnx recognizer,不是整個 KITT service Pod;offline 數字不能直接取代目前部署的 9.20 GB 服務 RSS, 但足以證明主要額外記憶體來自 cache-warm 載入時仍存在的 ONNX 解析/TensorRT builder 路徑。
7.2.2 4090 與 Orin:只能比較各平台內方向
| 量 | RTX 4090 報告 | Orin 實測 | 解讀限制 |
|---|---|---|---|
| 穩態 RSS:CUDA → TRT | 1.586 → 7.818 GB(+6.232 GB) | 4.02 → 9.20 GB(+5.18 GB) | 4090 是服務 harness;Orin 是部署中的 Pod process,絕對值不可直接相減。 |
| 首次 engine build / ready | 空閒卡 21.3 秒;忙碌時曾觀察 167.9 秒 | 隔離 cold build 68.19 秒 | 都是目標機編 engine;GPU 負載與軟體棧不同,不能跨機排名。 |
| cache-warm 載入 | 約 5.30 秒;RSS 5,710 MB | 中位數 21.74 秒;ready PSS 5,657 MB、cgroup 5,486 MB | 4090 舊報告與 Orin 本輪的記憶體尺不同;共同點是仍解析 ONNX、仍建 network。 |
| offline EP context 載入 | 2.38 秒;RSS 2,144 MB | 中位數 11.42 秒;ready RSS 2,218 MB、PSS 962 MB、cgroup 898 MB | 兩邊都只 deserialize 預建 engine;Orin 是統一記憶體,不可把 PSS/cgroup 當 4090 RSS。 |
| FP32 engine | 約 994 MB,sm89 | 984,899,100 bytes(約 985 MB),sm87 | 體積接近不代表可共用;兩份 engine 必須各自在目標 GPU 重建。 |
| T=2000:session 後長句增量 | CUDA +1,034 MB;TRT +448 MB | Job cgroup:CUDA +1,040 MB;TRT +276 MB | 4090 是獨立顯存,Orin 是統一記憶體 cgroup;只能比較「TRT 增量較小」的方向,不能直接比較絕對 MB。 |
| T=2000 後記憶體 | 獨立 GPU:CUDA 2,456 MB;TRT 1,958 MB | Job cgroup:CUDA 3,229 MB;TRT 6,779 MB | Orin TRT 基礎 footprint 較高,雖然長句增量較小,最後仍比 CUDA 多 3,550 MB。 |
| Orin Job 程序 RSS / HWM | — | CUDA 3,277 / 3,342 MB;TRT 7,237 / 8,592 MB | 這是隔離 benchmark process,不等同部署中服務的 4.02 / 9.20 GB,但 provider 差異方向一致。 |
4090 資源來源:第 7.2.4 節、 第 7.5.3 節、 第 7.6.2 節。跨平台最可靠的結論是「兩台都需要自己的 engine 與量測」; 不能用 4090 的 4.30× 或記憶體配置直接預測 Orin。Orin 短句記憶體見 第 3.6 節,最大 profile 見 第 3.5 節。
8 · 產出與採用判定
| 產出 | 位置 |
|---|---|
| Orin TRT provider 設定 | config-trt-orin.config |
| Orin deployment override | config-k3s-orin.yaml、deployment/k3s-orin/deployment.yaml |
| CUDA / TRT 圖層 artifacts | tests/batch_decode/results/orin_agx_graph_3s6s15s_20260904/{cuda,trt}.json(gitignored) |
| CUDA / TRT 服務層 artifacts | tests/batch_decode/results/orin_agx_*_fp32_3s6s15s_20260904/results.json(gitignored) |
| CUDA / TRT cache-warm sherpa 記憶體 | tests/batch_decode/results/orin_agx_sherpa_memory_3s6s15s_20260904/(gitignored) |
| TRT offline EP context 記憶體 | tests/batch_decode/results/orin_agx_trt_offline_memory_3s6s15s_20260904/{offline-3s,offline-6s,offline-15s,summary}.json(gitignored) |
| CUDA / TRT T=2000 記憶體 artifacts | tests/batch_decode/results/orin_agx_t2000_memory_20260904/{cuda,trt,summary}.json(gitignored) |
| 4090 比較來源 | 2026-09-01 model quantization eval 第 7.2/7.5 節 |
| 驗收測試 | tests/test_trt_provider_guard.py |
T=2000 沒有加速,最大錄音時限的既有 gap 仍應優先補齊。9 · 2026-09-05 同 cycle 重測
Orin 短句收益重現;4090 舊 CUDA 圖層基準未重現;服務文字並非逐次完全相同。 兩台各完成 CUDA/TRT × 3/6/15 秒 × bulk/realtime × 三輪,共 72 個成功 final。 完整 JSON(含每次數字、文字、hash、版本與 shell 命令)見 本輪原始量測摘要。 原正式服務未切換、未重启,僅使用臨時容器。Orin image digest 與 2026-09-04 報告相同,因此無須 cross compile sherpa-onnx。
9.1 量測條件與可比範圍
兩台 source 均為 49f0488,模型/tokens 及兩個主要服務 source SHA-256 逐一相同。
4090:ORT 1.23.2 / TRT 10.13.3.9;Orin:ORT 1.24.0 / TRT 10.3。
FP32、batch=1、T=1/100/2000;graph 固定 seed 42、threads=2、10 次暖機與 50 次取樣,計時時關閉 ORT profiler,另起程序證明 provider。
服務沿用 hardware_profile.py、3 次暖機、每 provider 三個獨立 series,保留 streaming interim 與 Perfetto。
音檔由版控 multiuser-10s.wav 的 PCM 重複並裁切為 3/6/15 秒,兩台 hash 一致;
舊 WAV 未保存,故未宣稱與歷史音檔逐位元一致。15 秒在第 10 秒拼接;只能作本次兩 provider 的共同 workload。
GPU 仍與既有程序共用,未鎖 GPU clocks。服务 latency 是 server final recognizer,不包含 browser、LiveKit 或送音時間。
每組只有三次,範圍代表觀測到的波動,不是信賴區間。
9.2 圖層基準:4090 的舊 CUDA 數字不宜直接沿用
| 平台 | 音長 | 舊 CUDA / TRT ms | 新 CUDA / TRT ms | 新加速比 | 相對舊值 |
|---|---|---|---|---|---|
| 4090 | 3s | 26.35 / 6.14 | 8.10 / 5.87 | 1.38× | CUDA -69.3%; TRT -4.4% |
| 4090 | 6s | 26.59 / 6.19 | 8.20 / 5.86 | 1.40× | CUDA -69.2%; TRT -5.3% |
| 4090 | 15s | — | 10.54 / 9.88 | 1.07× | 無同尺舊值 |
| orin | 3s | 36.30 / 19.83 | 35.26 / 19.69 | 1.79× | CUDA -2.9%; TRT -0.7% |
| orin | 6s | 37.07 / 19.97 | 36.19 / 20.08 | 1.80× | CUDA -2.4%; TRT +0.6% |
| orin | 15s | 45.18 / 38.84 | 44.99 / 38.85 | 1.16× | CUDA -0.4%; TRT +0.0% |
Orin 的舊圖層數字接近重現;4090 CUDA 明顯比舊值低,不能沿用舊 4.3× 倍數。
4090 改 threads=0/2/4 都約 8 ms;額外啟用 ORT profiler 後,T=50/100 的 p50 為 19.82/21.64 ms。profiler 確實大幅增加 CUDA 的多節點執行開銷, 但舊腳本缺失,這不是舊 26 ms 根因的證明。兩台 TRT 的獨立 profiler 證明皆只有 TensorRT node events。 Profiling 的數字只用於開銷實驗,不混入主比較表。
9.3 WebSocket 服務:短句收益較穩,長句與共享 GPU 波動須揭露
| 平台 | 送音 | 秒 | CUDA 中位數 [min,max] ms | TRT 中位數 [min,max] ms | 加速比 / 延遲降幅 | 舊 Orin CUDA / TRT ms |
|---|---|---|---|---|---|---|
| 4090 | bulk | 3 | 22.36 [21.81, 22.37] | 15.18 [14.35, 15.27] | 1.47× / 32.1% | — |
| 4090 | bulk | 6 | 27.55 [27.08, 30.45] | 17.02 [16.34, 20.79] | 1.62× / 38.2% | — |
| 4090 | bulk | 15 | 39.06 [38.79, 47.44] | 35.61 [34.19, 40.01] | 1.10× / 8.8% | — |
| 4090 | realtime | 3 | 30.05 [22.40, 31.42] | 10.56 [9.35, 23.98] | 2.85× / 64.9% | — |
| 4090 | realtime | 6 | 24.36 [21.00, 39.39] | 23.31 [10.85, 27.79] | 1.05× / 4.3% | — |
| 4090 | realtime | 15 | 39.02 [28.01, 67.94] | 26.07 [22.81, 33.03] | 1.50× / 33.2% | — |
| orin | bulk | 3 | 87.55 [87.09, 90.50] | 54.30 [53.97, 55.73] | 1.61× / 38.0% | 89.26 / 51.75 |
| orin | bulk | 6 | 98.23 [96.58, 104.43] | 61.15 [56.96, 69.86] | 1.61× / 37.7% | 112.76 / 60.50 |
| orin | bulk | 15 | 225.19 [220.57, 235.31] | 206.14 [205.27, 234.66] | 1.09× / 8.5% | 258.13 / 218.89 |
| orin | realtime | 3 | 81.90 [76.68, 93.02] | 48.81 [46.81, 49.96] | 1.68× / 40.4% | 79.75 / 45.28 |
| orin | realtime | 6 | 82.68 [79.93, 93.99] | 45.99 [45.49, 46.95] | 1.80× / 44.4% | 98.52 / 47.25 |
| orin | realtime | 15 | 189.43 [180.07, 217.87] | 170.87 [167.32, 211.04] | 1.11× / 9.8% | 193.56 / 175.51 |
Orin 的 3/6 秒延遲下降約 38–44%,15 秒約 8–10%;4090 某些 realtime 組的範圍重疊,不能把單次值當穩定倍數。
9.4 文字重複性:單獨 recognizer 一致,服務仍有差異
兩平台 × 三個音長 × CUDA/cache-warm/offline,各三次直接 recognizer 解碼,共 54 次, 同平台同音長的三種 provider 輸出一致。服務則有 15 秒「風量開」/「風量開大」與斷句差異; Orin realtime 3 秒也有逗號/句號差異。Orin 15 秒 CUDA 與 TRT 兩邊都出現變體, 因此不能將它歸因於 TensorRT 降精度;也不能再把本次完整服務結果稱為逐次文字完全一致。 本輪只確認現象,未定位到具體排程/前處理根因,未修改產品程式。逐組變體已保存於 JSON。
9.5 載入與記憶體:offline 的收益保留,cgroup 未作歷史同尺比較
每個 arm 使用全新 recognizer 程序,最後一輪已停止全部臨時服務。下表的中位數取三個音長 arm, 不是同一個音長重啟三次。load 計時含 sherpa/soundfile import 與 recognizer 建構;ready 指尚未暖機。 PSS 是按比例分攤共享頁的程序記憶體;MiB=2²⁰ bytes。本次共用同一個臨時容器,cgroup 會累積 page cache, 所以不與原報告的 fresh-Pod cgroup 總量直接比較。舊 MB 標記也不假設等同 MiB。 這是 isolated recognizer,不能取代整個 production service 的 RSS。
| 平台 | 載入方式 | 載入秒 中位數 [min,max] | ready PSS MiB 中位數 [min,max] | 15s 後 PSS MiB |
|---|---|---|---|---|
| 4090 | cuda | 1.29 [1.27, 1.30] | 1273 [1261, 1279] | 1328 |
| 4090 | trt | 6.01 [5.67, 6.13] | 7530 [7530, 7530] | 7540 |
| 4090 | offline | 1.69 [1.69, 1.73] | 923 [923, 923] | 986 |
| orin | cuda | 2.96 [2.91, 2.99] | 1160 [843, 1166] | 1218 |
| orin | trt | 23.77 [15.97, 44.89] | 5539 [5538, 5545] | 5549 |
| orin | offline | 8.24 [8.23, 8.51] | 852 [850, 854] | 909 |
兩台 cache-warm 仍有較高常駐程序記憶體;offline ready PSS 均低於 1 GiB。
新的空 cache 建置時間:4090 22.78 秒,Orin 69.15 秒 (舊 Orin 68.19 秒)。EP context 複製必要 metadata 後,在原始 ONNX 暫時移開的狀態下仍可辨識;兩台 offline profiler 都只有 TensorRT 節點。 沒有把 cache hit 改名成 offline。Orin cache-warm 載入範圍仍達 15.97–44.89 秒,單一 21.74 秒不能代表每次啟動。 目前正式部署仍用 cache-warm,本次没有改 release 載入路徑。
9.6 最大 profile:T=2000 仍非 TensorRT 甜蜜點
| 平台 | CUDA p50 ms | TRT p50 ms | TRT 耗時差 |
|---|---|---|---|
| 4090 | 82.96 | 103.72 | +25.0% |
| orin | 471.62 | 531.47 | +12.7% |
每 provider 全新程序,1 次暖機、3 次正式執行;這是 graph 的最大形狀,不是 120 秒 WebSocket 服務測試。 不能把短句倍數外推到這個上限。
9.7 驗證、產物與未覆蓋範圍
- 全套離線入口
./tests/test.sh:625 passed / 28 skipped,15.49 秒。TurnSense 模型未在新 worktree materialize,22 條相關測試 skip;其餘 skip 保留於 log。完整 live suite 本次未重跑;實際跑的是 72 組服務 benchmark。 - 新增量測腳本有
--self-check;Ruff 與 diff whitespace 檢查通過;報告/追溯測試 39 passed,Playwright 截圖已人工檢視。首次 sandbox executor hang 不算產品失敗,外部執行同套件通過。 - 臨時 Docker 與 Orin Pod 已刪除;正式 Orin Pod 仍 1/1、零 restart,原 4090 四個推論程序保留。原始 log、每次 JSON、WAV、命令與 engine 保存在
tests/batch_decode/results/recheck_20260905/(gitignored);可審查的精簡 JSON 已進版控。 - 本輪驗收 R1(同模型與音訊)、R2(graph 與 provider 證據)、R4(服務三輪)、R5(歷史比較)完成;R3(程序記憶體)完成,fresh-Pod cgroup 的歷史同尺比較未覆蓋。
- 下一個需要獨立定位的問題是服務 15 秒文字重複性;本輪不將它修補或歸罪於 TensorRT。
重跑 graph 的最小命令(在備齊本平台 CUDA/TRT 函式庫的容器內):
python3 tests/batch_decode/provider_recheck.py --provider cuda --model /app/models/sherpa-onnx-sense-voice-kitt-wake-lora-v1/model.onnx --cache /bench/cache --frames 50,100,250 --threads 2 --warmup 10 --repeats 50 --out /bench/graph-cuda.json
# 改 --provider trt 為同平台 TensorRT;--profile 只另跑 provider 證據,不混入主計時。
python3 tests/batch_decode/hardware_profile.py --target ws://127.0.0.1:19242/stt/sensevoice --lengths 3,6,15 --warmup 3 --out /bench/service-cuda-1
所有 orchestration shell 全文保存在 JSON 的 commands;provider_recheck.py 為版控腳本。
EP context 相對 engine 路徑的限制依據 ONNX Runtime TensorRT 官方文件;本次亦實際驗證絕對路徑會被拒絕。
10 · deploy.sh 與新 image 重測(完整量測,已發布)
更新時間:2026-09-05T22:21:14.012602+08:00。最終 72 個服務測項已完成;15 秒差異保留為未定位事項。
10.1 建置與部署:首次 Orin 75 分 26 秒
同一 worktree,HEAD 5405eac;應用程式碼未修改。Orin 由 deploy.sh 完整 build/push/deploy;4090 由 Dockerfile 重新 build,另加 TensorRT 10.13.3.9 測試相依層,兩 provider 使用相同 image。此輪不 commit。
| 項目 | 已測時間 | 條件/狀態 |
|---|---|---|
| 4090 原始 image build | 793.47 s(13 分 13 秒) | 相依層命中快取;與 Orin build 並行 |
| 4090 TensorRT 相依層 | 522.80 s(8 分 43 秒) | 另計;未修改 STT source |
| Orin 首次 deploy.sh | 4526.42 s(75 分 26 秒) | 包含 DVC、下載、build、push、rollout;已成功 |
| Orin 首次 sherpa 安裝完成 | 1942.1 s | 首次 build 使用固定 -j16;此值為安裝完成時間 |
| Orin 動態 CPU sherpa build 步驟 | 1892.7 s(31 分 33 秒) | 已通過;nproc / 2、最少 1 |
| Orin 動態 CPU deploy.sh | 2308.95 s(38 分 29 秒) | 已成功;前置相依層有快取 |
Dockerfile.orin 已改為 max(1, floor(nproc / 2))。本機 32 CPU 對應 16 jobs,已驗證 1/2/3/8/32 CPU 算式;沒有用這兩次 build 宣稱並行設定帶來加速。基底下載、磁碟 I/O 與快取狀態不同,兩次時間不能當受控效能比較。QEMU 是在 x86 上執行 arm64 建置程序的模擬層,本次 sherpa 不是原生 x86 編譯。
10.2 同碼圖層:兩平台短句 TRT 收益重現
兩平台的 model.onnx、tokens.txt、batch_asr_manager.py、kitt_stt_service.py SHA-256 完全相同。固定 seed、T=50/100/250、10 次暖機、50 次正式執行;主計時不開 profiler。音長是 shape 約當值,實際 WAV 服務量測另列。4090 ORT 1.23.2,Orin ORT 1.24.0,平台 runtime 不同。
| 平台 | 音長/shape | CUDA p50 ms | TRT p50 ms | 加速比 |
|---|---|---|---|---|
| 4090 | 3s / T=50 | 8.17 | 6.09 | 1.34× |
| 4090 | 6s / T=100 | 8.17 | 5.88 | 1.39× |
| 4090 | 15s / T=250 | 10.55 | 9.90 | 1.06× |
| orin | 3s / T=50 | 37.35 | 19.86 | 1.88× |
| orin | 6s / T=100 | 38.48 | 20.04 | 1.92× |
| orin | 15s / T=250 | 45.93 | 38.82 | 1.18× |
4090 的 CUDA 仍約 8 ms,沒有重現歷史 26 ms;Orin TRT 與前次接近。
10.3 記憶體:每個 recognizer 測項使用新容器/Pod
3/6/15 秒各啟動一個新程序與新容器,使用 cache-warm TRT。表內 ready 是模型載入後、暖機前;PSS/RSS/cgroup current 為三個音長測項中位數,程序 HWM 為三個測項的最大值。單位均為 MiB。cgroup 包含檔案快取;Orin 的統一記憶體不能拆成獨立 GPU VRAM。
| 平台 | provider | ready PSS | ready RSS | 程序最高 RSS | ready cgroup current |
|---|---|---|---|---|---|
| 4090 | cuda | 1266.2 | 1270.7 | 1358.3 | 1083.7 |
| 4090 | trt | 7531.7 | 7536.2 | 9419.6 | 5448.9 |
| orin | cuda | 1128.4 | 2312.2 | 2382.1 | 2059.4 |
| orin | trt | 5509.4 | 6949.7 | 8601.0 | 6763.1 |
兩平台 TensorRT cache-warm recognizer 的程序 PSS 都高於 CUDA;本表不包含完整服務。
Orin kernel 提供 memory.current,未提供 memory.peak,因此容器峰值標示為不可用;程序 VmHWM 仍有記錄。本輪尚未重測 offline EP context,舊數據保留在第 7/9 節,不能視為這輪新 image 的驗證結果。
10.4 4090 服務歷史批次:與編譯並行的 36 個有效測項
CUDA/TRT × 3 音長 × bulk/realtime × 3 輪,共 36 個有效 final。表為三輪中位數。服務量測與 Orin 交叉編譯共用 x86 主機,不能當作無編譯負載的最終基準;尤其 CUDA bulk 与 15 秒比上一輪偏高,編譯結束後的結果見 第 10.6 節。主機仍有其他 GPU 程序。
| 送音 | 音長 s | CUDA final ms | TRT final ms |
|---|---|---|---|
| bulk | 3 | 50.46 | 12.56 |
| bulk | 6 | 60.64 | 17.64 |
| bulk | 15 | 106.64 | 68.84 |
| realtime | 3 | 28.72 | 11.22 |
| realtime | 6 | 37.46 | 16.36 |
| realtime | 15 | 83.43 | 56.59 |
這批服務結果是在編譯負載下量到;數據差異尚不能判定為程式回歸。
| provider | 時間點 | PSS MiB | RSS MiB | 程序 HWM MiB | cgroup current MiB | cgroup peak MiB |
|---|---|---|---|---|---|---|
| cuda | ready | 2524.4 | 2531.6 | 2548.2 | 2251.3 | 2278.3 |
| cuda | end | 2658.0 | 2665.2 | 2705.2 | 2455.8 | 2981.5 |
| trt | ready | 10978.1 | 10985.3 | 11960.4 | 10038.3 | 10962.8 |
| trt | end | 11097.2 | 11104.4 | 11960.4 | 10157.4 | 10962.8 |
此 TensorRT 服務首次使用空 engine cache,包含 target-side 建 engine 的成本;暖快取完整服務記憶體見 第 10.7 節。最初另有一個無效嘗試:客戶端冷載入模組約 40 秒,導致 keepalive timeout,沒有送達音訊;已保留 log 並排除。客戶端改為連線前載入模組後,三輪成功,服務 code 未修改。
10.5 前期驗證與可重現資料
| 驗證項目 | 本輪狀態 |
|---|---|
| 完整離線 ./tests/test.sh | 652 passed / 1 skipped,39.97 秒 |
| CPU 計算邊界 | 1→1、2→1、3→1、8→4、32→16 jobs |
| 同模型/同程式雜湊 | 兩平台一致 |
| 3/6/15 秒 recognizer 與 graph | 兩平台完成;每個模型測項新容器/Pod |
| 4090 服務三輪 | 並行批次 36 個有效 final;編譯後另有 36 個有效 final |
| Orin 最終部署的服務三輪 | 36 個有效 final,見第 10.6 節 |
| 完整 live regression suite | 本輪未執行;服務 benchmark 與 offline 分開記錄 |
| Git | 未 commit、未 push |
資料:本輪完整 JSON;原始 log、WAV、指令位於 tests/batch_decode/results/deploy_recheck_20260905/。模型量測的 Orin image 為 v5.8.0-recheck-20260905-orin,最終服務使用 v5.8.0-recheck-ncpu-20260905-orin,兩者僅建置並行數的寫法不同;精確 image 參照在 JSON。後續更新沿用本 cycle,保留中途失敗與历史數據。
10.6 最終服務:兩平台 72 個測項成功,4090 的 15 秒仍有差異
本節為編譯結束後的服務補測,各平台 CUDA/TRT × 3/6/15 秒 × bulk/realtime × 三輪,共 72 個有效 final。表內為三輪中位數。4090 用相同新 image 與暖 engine cache;Orin TRT 直接測最終 deploy.sh 部署的 Pod,CUDA 使用同 image 的獨立測試 Pod。GPU 與其他既有工作共用,未鎖 clocks,因此不是專用硬體的無負載基準。
| 平台 | 送音 | 音長 s | CUDA final ms | TRT final ms | TRT 相對 CUDA |
|---|---|---|---|---|---|
| 4090 | bulk | 3 | 22.45 | 13.34 | -40.6% |
| 4090 | bulk | 6 | 26.83 | 17.97 | -33.0% |
| 4090 | bulk | 15 | 72.64 | 75.10 | +3.4% |
| 4090 | realtime | 3 | 28.21 | 17.98 | -36.3% |
| 4090 | realtime | 6 | 30.55 | 13.37 | -56.2% |
| 4090 | realtime | 15 | 74.55 | 54.44 | -27.0% |
| orin | bulk | 3 | 90.42 | 55.89 | -38.2% |
| orin | bulk | 6 | 99.14 | 59.50 | -40.0% |
| orin | bulk | 15 | 228.90 | 211.27 | -7.7% |
| orin | realtime | 3 | 81.78 | 44.54 | -45.5% |
| orin | realtime | 6 | 86.71 | 45.47 | -47.6% |
| orin | realtime | 15 | 191.45 | 172.99 | -9.6% |
4090 的 15 秒 bulk TRT 為 75.10 ms、CUDA 為 72.64 ms;本次不是每組 TRT 都較快。
Orin 的 3/6 秒 TRT 約降低 38–48%,15 秒約降低 8–10%。
4090 前一輪 overlay 的 15 秒 bulk CUDA/TRT 為 39.06/35.61 ms,本輪為 72.64/75.10 ms;realtime 由 39.02/26.07 ms 到 74.55/54.44 ms。新 image 的 graph 數字卻接近前輪,因此不能直接歸因於模型 kernel 退化。並行編譯曾使 3/6 秒 CUDA bulk 高到 50.46/60.64 ms,補測回到 22.45/26.83 ms;15 秒差異則仍在,需要另查服務前處理、排程與 runtime 載入差異,本輪未聲稱已定位根因。
文字方面,Orin 本輪 15 秒各 provider 及送音模式回覆一致;4090 CUDA 的 15 秒仍有「風量開/風量開大」與句讀差異,TRT 本輪三輪一致。這是小樣本重複性觀測,不足以證明哪一個 provider 精度更好,也未修改服務辨識行為。
10.7 最終完整服務記憶體:暖快取與首次建 engine 分列
以下為完整服務,而非 10.3 的独立 recognizer。ready 為 HTTP health 通過、送音前,end 為三輪測試後;單位 MiB。Orin 正式 Pod 的 HWM 自本次啟動起累計。兩平台 RSS/PSS 的差異也受共享 library 頁面分攤影響。
| 平台 | provider | 時點 | PSS | RSS | 程序 HWM | cgroup current | cgroup peak |
|---|---|---|---|---|---|---|---|
| 4090 | cuda | ready | 2470.0 | 2477.3 | 2584.0 | 2142.3 | 2256.3 |
| 4090 | cuda | end | 2603.2 | 2610.5 | 2649.1 | 2275.4 | 2799.5 |
| 4090 | trt | ready | 9158.1 | 9165.3 | 9795.3 | 7885.7 | 8526.7 |
| 4090 | trt | end | 9143.4 | 9288.9 | 9795.3 | 8009.5 | 8533.4 |
| orin | cuda | ready | 1792.2 | 4035.9 | 4147.3 | 3976.9 | kernel 未提供 |
| orin | cuda | end | 1908.9 | 4174.7 | 4214.4 | 4118.5 | kernel 未提供 |
| orin | trt | ready | 6303.4 | 8723.1 | 9452.4 | 7114.6 | kernel 未提供 |
| orin | trt | end | 6400.7 | 8895.1 | 9452.4 | 7285.4 | kernel 未提供 |
完整服務的 TRT PSS 高於 CUDA;這裡的服務數字不能與獨立 recognizer 當成相同範圍。
4090 TRT 首次從空 engine cache 啟動時 ready PSS 為 10978.1 MiB,暖快取重啟為 9158.1 MiB(約 10.72 → 8.94 GiB)。記憶體報告應指出是否包含首次建 engine,不能混用。4090 獨立 recognizer 的整卡 VRAM 在載入前均約 9569 MiB,CUDA ready 約 10998 MiB,TRT 約 11076 MiB;觀測增量約 1429/1507 MiB,整卡仍包含其他程序,不當作程序專屬分配量。
10.8 驗證與交付狀態
- 兩次 deploy.sh 成功:首次 4526.42 秒,動態 CPU 版本 2308.95 秒;第二次有前置 layer cache,不能把時間差當成 CPU 公式效益。
- 完整離線測試 652 passed/1 skipped;文件測試 39 passed。完整 live suite 未跑,這次服務 benchmark 獨立記錄為最終 72 次成功,加上並行編譯時 36 次成功。
- 測試客戶端冷載入的 keepalive timeout、過早建立 port-forward 的 readiness 失敗均保留 log,排除於有效測項。
- 測試 Pod/Docker 容器已清理;Orin 保留新部署。此輪不 commit、不 push。
- 使用者已確認公開目的地與內容,報告已發布至 Cloudflare Pages。