跳至主要内容

基準測試您的模型

欄位
類別模型與推論
難度初級
預估閱讀時間5-10 minutes
標籤benchmark, synthetic, latency, throughput, power

第 001 章和第 002 章展示了如何執行模型一次,然後如何以非同步方式驅動它。本章回答了下一個實際問題:「此模型在設備上的執行速度如何?」基準測試 API 故意設計得較小。您載入模型,選擇要測量的樣本數量,呼叫 benchmark(...),並讀取傳回的 BenchmarkReport

基準測試使用模型的 input_specs() 來建立確定性的合成輸入。這使得它對於快速的模型初步基準測試以及比較已編譯的模型變體非常有用,但它不是相機基準測試。它不包括相機解碼、實際的預處理變化、動態輸入大小或依賴資料的後處理行為。

操作指南

載入模型

從先前模型教程中使用的相同的已編譯 .tar.gz 檔案開始。由於基準測試會根據模型聲明的輸入規格建立合成張量,因此不需要任何圖像。

C++: 從檔案路徑建置 simaai::neat::Model

Python: 從檔案路徑建置 pyneat.Model

tutorials/003_benchmark_your_model/benchmark_your_model.cpp
simaai::neat::Model model(model_path);

執行基準測試

呼叫 benchmark(samples)。API 會預熱非同步模型執行器,測量非同步推送/拉取窗口,將摘要列印到標準輸出,並在 BenchmarkReport 中傳回相同的主要值。

樣本數量是測量的合成輸入的數量。對於更穩定的吞吐量和功耗數字,請使用較大的數量;當您只想進行快速的初步檢查時,請使用較小的數量。

其路徑以 BoxDecode 結尾的檢測模型也可以使用 BenchmarkOptions。設定 original_widthoriginal_heightresize_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 幾何形狀。

tutorials/003_benchmark_your_model/benchmark_your_model.cpp
simaai::neat::BenchmarkReport report = model.benchmark(samples);
if (report.latency_ms <= 0.0 || report.fps <= 0.0)
throw std::runtime_error("benchmark produced no measured latency/fps");

閱讀報告

傳回的報告僅保留大多數使用者需要的標題欄位:以毫秒為單位的平均端到端延遲、以每秒幀數為單位的吞吐量、如果有的話,以瓦特為單位的平均板載功耗,以及如果有的話,以焦耳為單位的測量能量。

功耗遙測取決於板載支援。如果執行階段無法對當前目標進行功耗軌的取樣,基準測試仍會報告延遲和吞吐量,並將功耗欄位設定為零。

tutorials/003_benchmark_your_model/benchmark_your_model.cpp
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";

執行

執行它,您應該會看到 benchmark() 輸出的基準測試摘要,後面接著從傳回的報告中輸出的相同值。從 Neat 安裝根目錄(包含 share/lib/ 的目錄)執行 PythonC++(預先建置) 命令;從 儲存庫根目錄執行 從原始碼建置 命令。

C++ (prebuilt):

./lib/sima-neat/tutorials/tutorial_003_benchmark_your_model \
--model /tmp/resnet_50.tar.gz --samples 100

C++ (build from source):

./build.sh --target tutorial_003_benchmark_your_model
./build/tutorials-standalone/tutorial_003_benchmark_your_model \
--model /tmp/resnet_50.tar.gz --samples 100

預期的輸出(確切的數字取決於模型、板載和當前負載;C++ 建置還會輸出尾部的 [OK] 行):

NEAT Benchmark
Input: synthetic
Samples: 100
Latency: 12.4 ms
FPS: 80.6
Power avg: 2.3 W
Energy: 2.8 J
report_latency_ms=12.4
report_fps=80.6
report_avg_power_watts=2.3
report_energy_joules=2.8
[OK] 003_benchmark_your_model

若要將本章的 C++ 原始碼整合到您自己的專案中,並使用自訂的 CMakeLists.txt(無需額外的資料夾),請參閱登陸頁面上的 如何執行教學

實務應用

當您需要快速了解已編譯的模型封存檔時,請使用此基準測試:它是否能正常執行?測得的非同步吞吐量是多少?以及在此目標平台上,主要的板卡功耗是多少?

對於應用程式效能,也請基準測試實際的管線。合成模型輸入是故意設計為穩定的,因此它不代表相機抖動、編解碼器成本、實際的預處理、主機在負載下的排程,或下游應用程式邏輯。若要針對手動建立的非同步執行來調整佇列深度和反壓,請參閱調整吞吐量和佇列深度

Model::benchmark() 需要具體的 input_specs() 尺寸。如果輸入形狀是動態或非具體的,基準測試將明確失敗,而不是猜測一個形狀。

完整原始碼

顯示完整原始碼程式
tutorials/003_benchmark_your_model/benchmark_your_model.cpp
// Benchmark a compiled model with deterministic synthetic inputs.
//
// Usage:
// tutorial_003_benchmark_your_model --model /path/to/model.tar.gz [--samples 100]

#include "neat.h"

#include <iostream>
#include <stdexcept>
#include <string>

namespace {

bool get_arg(int argc, char** argv, const std::string& key, std::string& out) {
for (int i = 1; i + 1 < argc; ++i) {
if (key == argv[i]) {
out = argv[i + 1];
return true;
}
}
return false;
}

int parse_int_arg(int argc, char** argv, const std::string& key, int def) {
std::string value;
if (!get_arg(argc, argv, key, value))
return def;
return std::stoi(value);
}

} // namespace

int main(int argc, char** argv) {
try {
std::string model_path;
if (!get_arg(argc, argv, "--model", model_path)) {
std::cerr << "Usage: tutorial_003_benchmark_your_model --model <path> [--samples <n>]\n";
return 1;
}
const int samples = parse_int_arg(argc, argv, "--samples", 100);

// CORE LOGIC
simaai::neat::Model model(model_path);

simaai::neat::BenchmarkReport report = model.benchmark(samples);
if (report.latency_ms <= 0.0 || report.fps <= 0.0)
throw std::runtime_error("benchmark produced no measured latency/fps");

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 << "[OK] 003_benchmark_your_model\n";
return 0;
} catch (const std::exception& e) {
std::cerr << "[FAIL] " << e.what() << "\n";
return 1;
}
}

來源