bonus-edge-proxy/rknn_perf_monitor.cpp

163 lines
5.7 KiB
C++
Raw Normal View History

2026-01-16 18:18:17 +08:00
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <thread>
#include <chrono>
#include <iomanip>
#include <numeric>
#include <algorithm>
// ==========================================
// CPU 监控类 (保持不变)
// ==========================================
class CpuMonitor {
public:
CpuMonitor() { get_usage(); }
float get_usage() {
std::ifstream file("/proc/stat");
std::string line;
if (!std::getline(file, line)) return 0.0f;
std::istringstream ss(line.substr(3));
unsigned long long user, nice, system, idle, iowait, irq, softirq, steal;
ss >> user >> nice >> system >> idle >> iowait >> irq >> softirq >> steal;
unsigned long long current_idle = idle + iowait;
unsigned long long current_non_idle = user + nice + system + irq + softirq + steal;
unsigned long long current_total = current_idle + current_non_idle;
unsigned long long total_diff = current_total - prev_total;
unsigned long long idle_diff = current_idle - prev_idle;
prev_idle = current_idle;
prev_total = current_total;
if (total_diff == 0) return 0.0f;
return (float)(total_diff - idle_diff) * 100.0f / total_diff;
}
private:
unsigned long long prev_idle = 0;
unsigned long long prev_total = 0;
};
// ==========================================
// NPU 读取函数 (修改为读取所有核心)
// ==========================================
std::string get_npu_usage_str() {
std::ifstream file("/sys/kernel/debug/rknpu/load");
if (!file.is_open()) return "N/A (No Perm)";
std::string line;
if (std::getline(file, line)) {
// RK3588 通常格式: "NPU load: Core0: 0%, Core1: 0%, Core2: 0%,"
// 我们去掉前面的 "NPU load:" 前缀,只保留 Core 信息
size_t pos = line.find("NPU load:");
if (pos != std::string::npos) {
line = line.substr(pos + 9);
}
// 简单的字符串清理:去掉多余空格,去掉结尾逗号
std::string clean_line;
bool last_space = false;
for (char c : line) {
if (c == ',') continue; // 去掉逗号
if (isspace(c)) {
if (!last_space) {
clean_line += ' ';
last_space = true;
}
} else {
clean_line += c;
last_space = false;
}
}
return clean_line;
}
return "Idle";
}
// ==========================================
// RGA 读取函数 (根据你找到的路径修改)
// ==========================================
std::string get_rga_usage_str() {
std::ifstream file("/sys/kernel/debug/rkrga/load");
if (!file.is_open()) return "N/A";
std::string line;
std::stringstream ss;
bool found_any = false;
int core_idx = 0;
while (std::getline(file, line)) {
// 忽略第一行 "num of scheduler"
if (line.find("scheduler") != std::string::npos && line.find("=") != std::string::npos && line.find("%") == std::string::npos) {
continue;
}
// 寻找包含 "%" 的行,通常负载都在这些行里
if (line.find("%") != std::string::npos) {
// 尝试提取这一行里的最后一个数字
// 假设格式类似: "scheduler[0]: full_load = 0.0%, load = 12.5%"
// 或者简单点: "load = 12%"
// 简单粗暴法:找到 "%" 前面的数字
size_t percent_pos = line.rfind('%'); // 找最后一个 %
if (percent_pos != std::string::npos && percent_pos > 0) {
// 向前回溯找到数字起始位置
size_t num_end = percent_pos;
size_t num_start = num_end;
while (num_start > 0 && (isdigit(line[num_start-1]) || line[num_start-1] == '.')) {
num_start--;
}
if (num_start < num_end) {
std::string num_str = line.substr(num_start, num_end - num_start);
try {
float load = std::stof(num_str);
ss << "C" << core_idx++ << ":" << std::fixed << std::setprecision(0) << load << "% ";
found_any = true;
} catch (...) {}
}
}
}
}
if (!found_any) return "Idle (fmt err)";
return ss.str();
}
// ==========================================
// 主函数
// ==========================================
int main() {
CpuMonitor cpu_mon;
std::cout << "=== RK3588 System Monitor ===" << std::endl;
// 打印更宽的表头
std::cout << "----------------------------------------------------------------------------------" << std::endl;
std::cout << "| CPU | NPU (3 Cores) | RGA (Cores) |" << std::endl;
std::cout << "----------------------------------------------------------------------------------" << std::endl;
while (true) {
float cpu = cpu_mon.get_usage();
std::string npu = get_npu_usage_str();
std::string rga = get_rga_usage_str();
// 格式化输出
// CPU: 占用 6 格
// NPU: 占用 38 格 (预留给 Core0: xx% Core1: xx% Core2: xx%)
// RGA: 占用 28 格
std::cout << "\r| "
<< std::fixed << std::setprecision(1) << std::setw(5) << cpu << "% | "
<< std::left << std::setw(38) << npu << " | "
<< std::setw(28) << rga << " |"
<< std::flush;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
return 0;
}