基準測試您的模型
| 欄位 | 值 |
|---|---|
| 類別 | 模型與推論 |
| 難度 | 初級 |
| 預估閱讀時間 | 5-10 minutes |
| 標籤 | benchmark, synthetic, latency, throughput, power |
第 001 章和第 002 章展示了如何執行模型一次,然後如何以非同步方式驅動它。本章回答了下一個實際問題:「此模型在設備上的執行速度如何?」基準測試 API 故意設計得較小。您載入模型,選擇要測量的樣本數量,呼叫 benchmark(...),並讀取傳回的 BenchmarkReport。
基準測試使用模型的 input_specs() 來建立確定性的合成輸入。這使得它對於快速的模型初步基準測試以及比較已編譯的模型變體非常有用,但它不是相機基準測試。它不包括相機解碼、實際的預處理變化、動態輸入大小或依賴資料的後處理行為。
操作指南
載入模型
從先前模型教程中使用的相同 的已編譯 .tar.gz 檔案開始。由於基準測試會根據模型聲明的輸入規格建立合成張量,因此不需要任何圖像。
C++: 從檔案路徑建置 simaai::neat::Model。
Python: 從檔案路徑建置 pyneat.Model。
simaai::neat::Model model(model_path);
執行基準測試
呼叫 benchmark(samples)。API 會預熱模型,測量單次執行(single-flight)延遲,接著在另一個非同步推送/拉取階段中測量吞吐量,將摘要列印到標準輸出,並在 BenchmarkReport 中傳回相同的主要值。
每個階段都會持續執行,直到至少測量了 samples 個輸入且已經過 10 秒,因此吞吐量階段的功耗和溫度讀數會涵蓋多個樣本。設定 BenchmarkOptions::min_duration_ms 可變更此下限;設為 0 則可進行快速的初步檢查,讓每個階段在測量 samples 個輸入後即停止。
其路徑以 BoxDecode 結尾的檢測模型也可以使用 BenchmarkOptions。設定 original_width、original_height 和 resize_mode,以描述源圖像幾何形狀,BoxDecode 在將檢測映射到模型座標時使用該幾何形狀。合成張量仍然保持模型形狀:
simaai::neat::BenchmarkOptions options;
options.num_samples = 100;
options.original_width = 1920;
options.original_height = 1080;
options.resize_mode = simaai::neat::ResizeMode::Letterbox;
auto report = model.benchmark(options);
Python 會透過 pyneat.BenchmarkOptions 公開相同的欄位。設定原始的兩個維度,或省略這兩個維度;如果省略,基準測試會從已解析的模型路徑推斷幾何形狀。每次執行的基準測試幾何形狀優先於 ModelOptions 中已棄用的 BoxDecode 幾何形狀。
simaai::neat::BenchmarkOptions options;
options.num_samples = samples;
options.include_mla_layer_stats = has_flag(argc, argv, "--include-mla-layer-stats");
options.include_mla_stage_stats = has_flag(argc, argv, "--include-mla-stage-stats");
simaai::neat::BenchmarkReport report = model.benchmark(options);
if (report.latency_ms <= 0.0 || report.fps <= 0.0)
throw std::runtime_error("benchmark produced no measured latency/fps");
閱讀報告
傳回的報告以大多數使用者需要的標題欄位開頭:以毫秒為單位的平均端到端延遲、以每秒幀數為單位的吞吐量、以瓦特為單位的平均與峰值 SoM 功耗,以及處理 samples 個輸入所需的能量(以焦耳為單位) 。throughput_duration_ms 會回報吞吐量階段執行了多久。
功耗資料來自 Sentinel,也就是 Neat 安裝程式所設定的板子遙測常駐程式。report.telemetry 還包含吞吐量階段的電源軌功耗、晶粒與板子溫度、CPU 使用率以及 MLA 記憶體;各欄位說明請參閱測量模型執行效能。如果 Sentinel 未執行,基準測試仍會報告延遲和吞吐量,將功耗欄位保持為零,並將 report.telemetry.status 設定為原因。
std::cout << "report_latency_ms=" << report.latency_ms << "\n";
std::cout << "report_fps=" << report.fps << "\n";
std::cout << "report_avg_power_watts=" << report.avg_power_watts << "\n";
std::cout << "report_energy_joules=" << report.energy_joules << "\n";
std::cout << "report_peak_power_watts=" << report.peak_power_watts << "\n";
std::cout << "report_throughput_duration_ms=" << report.throughput_duration_ms << "\n";
std::cout << "report_telemetry_status=" << report.telemetry.status << "\n";
進階:MLA 層與階段統計資料
兩個選用選項會在基準測試後執行 mla-rt,測量已編譯 MLA 程式碼的時間。兩者預設皆停用,且需要沒有其他 MLA 工作負載的閒置 devkit。在任一教學命令中加入 --include-mla-layer-stats 或 --include-mla-stage-stats,或透過 API 啟用:
simaai::neat::BenchmarkOptions options;
options.include_mla_layer_stats = true;
options.include_mla_stage_stats = true;
auto report = model.benchmark(options);
options = pyneat.BenchmarkOptions()
options.include_mla_layer_stats = True
options.include_mla_stage_stats = True
report = model.benchmark(options)
從 report.mla_layer_stats.layers 讀取每個已編譯 MLA 層從零開始的 stage_index、name 與 latency_us:在只執行該層的一次剖析執行中測得的硬體執行時間。執行時間為零的 no-op 項目也會保留。各層延遲的總和不等於階段延遲,也不等 於整體延遲。
從 report.mla_stage_stats.stages 讀取每個 MLA 階段的 stage_index 與 latency_us:該階段連續不中斷執行 200 次的平均硬體時間。階段延遲包含 MLA 運算,以及程式對 DRAM 的讀取與寫入;不含模型載入、主機與 EV74 處理,以及管線額外負擔。
若找不到 mla-rt、其執行失敗或逾時,benchmark() 仍會傳回主要測量值,清單保持為空,並將原因寫入 report.mla_layer_stats.status 或 report.mla_stage_stats.status。其他情況下,各狀態為 "not requested" 或 "ok"。mla-rt 執行失敗、逾時或當機後,MLA 可能仍有未完成的工作,因此同一行程中之後的剖析會略過並記錄此原因。在確認 MLA 已復原之前,請讓 DevKit 保持閒置。
MLA 層統計會遵循所選的終端政策:只測量所選推論路徑中的 MLA 階段,且每個階段保留其在完整模型中的 stage_index。
if (options.include_mla_layer_stats) {
std::cout << "mla_layer_stats.status=" << report.mla_layer_stats.status << "\n";
for (const auto& layer : report.mla_layer_stats.layers) {
std::cout << " stage_index=" << layer.stage_index << " name=" << layer.name
<< " latency_us=" << layer.latency_us << "\n";
}
}
if (options.include_mla_stage_stats) {
std::cout << "mla_stage_stats.status=" << report.mla_stage_stats.status << "\n";
for (const auto& stage : report.mla_stage_stats.stages) {
std::cout << " stage_index=" << stage.stage_index << " latency_us=" << stage.latency_us
<< "\n";
}
}
儲存報告
呼叫 report.save(path) 即可將完整報告寫入 YAML 或 JSON,包含已要求的 MLA 層與階段統計資料:
auto path = report.save("results/model/yolo_benchmark.yaml");
auto json_path = report.save("results/model/yolo_benchmark.json");
path = report.save("results/model/yolo_benchmark.yaml")
json_path = report.save("results/model/yolo_benchmark.json")
副檔名 .json 選擇 JSON;.yaml 與其他結尾使用 YAML。檔名保持不變。
請指定包含檔名的路徑。不存在的父目錄會自動建立,既有檔案會被取代,並傳回寫入的路徑。儲存需要明確呼叫;benchmark() 不會自動建立報告檔案。
在任一教學命令後加入 --report results/model/yolo_benchmark.yaml。搭配 --include-mla-layer-stats 或 --include-mla-stage-stats,即可同時儲存主要測量值與 MLA 執行時間。
std::string report_path;
if (get_arg(argc, argv, "--report", report_path)) {
std::cout << "report_path=" << report.save(report_path).string() << "\n";
}