diff --git a/docker-compose.yml b/docker-compose.yml index 0a1846e..5b5a806 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,7 +18,8 @@ services: # --- VPU/NPU/RGA/GPU 硬件访问 --- - /dev/mpp_service:/dev/mpp_service - /dev/rga:/dev/rga - - /dev/dri:/dev/dri + - /dev/dri:/dev/dri + - /dev/dma_heap/system:/dev/dma_heap/system - source: /sys/bus/iio/devices/iio:device0 target: /sys/bus/iio/devices/iio:device0 diff --git a/monitor b/monitor new file mode 100755 index 0000000..8a6a65c Binary files /dev/null and b/monitor differ diff --git a/rknn_perf_monitor.cpp b/rknn_perf_monitor.cpp new file mode 100644 index 0000000..8640c24 --- /dev/null +++ b/rknn_perf_monitor.cpp @@ -0,0 +1,163 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ========================================== +// 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; +} \ No newline at end of file diff --git a/src/rknn_test/DmaBuffer.h b/src/rknn_test/DmaBuffer.h new file mode 100644 index 0000000..ed682b7 --- /dev/null +++ b/src/rknn_test/DmaBuffer.h @@ -0,0 +1,53 @@ +#include +#include +#include +#include +#include + +#include +#include + +class DmaBuffer { +public: + int fd; + void* vaddr; // 虚拟地址(仅供调试或CPU必须介入时使用,如画字) + size_t size; + + DmaBuffer(size_t size, const std::string& heap_name = "/dev/dma_heap/system") { + this->size = size; + this->vaddr = MAP_FAILED; + this->fd = -1; + + int heap_fd = open(heap_name.c_str(), O_RDONLY | O_CLOEXEC); + if (heap_fd < 0) { + perror("Failed to open dma heap"); + return; + } + + struct dma_heap_allocation_data data = {0}; + data.len = size; + data.fd_flags = O_RDWR | O_CLOEXEC; + + if (ioctl(heap_fd, DMA_HEAP_IOCTL_ALLOC, &data) < 0) { + perror("dma heap alloc failed"); + close(heap_fd); + return; + } + + this->fd = data.fd; + close(heap_fd); + + // 如果需要CPU访问(例如写OSD文字),则映射,否则可以不映射 + this->vaddr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, this->fd, 0); + if (this->vaddr == MAP_FAILED) { + perror("mmap failed"); + } + } + + ~DmaBuffer() { + if (vaddr != MAP_FAILED) + munmap(vaddr, size); + if (fd >= 0) + close(fd); + } +}; \ No newline at end of file