Rdkx5 yolo推理帧率低 BPU占用也低

问题定位完成!:bullseye:

从日志看,瓶颈非常清晰

环节 耗时 状态
USB 取图 - :white_check_mark: 正常 (200+ FPS)
等待 52-106ms :cross_mark: 严重瓶颈
BPU 推理 3.3ms :white_check_mark: 正常 (对应 300+ FPS)
预处理 0.0ms :white_check_mark: 正常
后处理 0.4ms :white_check_mark: 正常

结论:BPU 推理本身没问题(3.3ms 对应 300+ FPS),问题出在线程同步等待上,等待时间占总时间的 80%+。


根本原因

你的代码是双线程架构(线程 0/线程 1),但存在同步阻塞

线程 0: 取图 → 等待锁 → 推理 → 释放锁
线程 1: 取图 → 等待锁 → 推理 → 释放锁

Server 版系统的线程调度策略更保守,导致线程间切换和锁等待时间显著增加。


解决方案

方案 1:改用无锁队列(推荐):star:

使用 std::atomic 和环形缓冲区替代互斥锁:

#include <atomic>
#include <array>

template<typename T, size_t N = 4>
class LockFreeQueue {
private:
    std::array<T, N> buffer;
    std::atomic<size_t> head{0};
    std::atomic<size_t> tail{0};

public:
    bool push(const T& item) {
        size_t current_tail = tail.load(std::memory_order_relaxed);
        size_t next_tail = (current_tail + 1) % N;
        if (next_tail == head.load(std::memory_order_acquire)) {
            return false; // 队列满
        }
        buffer[current_tail] = item;
        tail.store(next_tail, std::memory_order_release);
        return true;
    }

    bool pop(T& item) {
        size_t current_head = head.load(std::memory_order_relaxed);
        if (current_head == tail.load(std::memory_order_acquire)) {
            return false; // 队列空
        }
        item = buffer[current_head];
        head.store((current_head + 1) % N, std::memory_order_release);
        return true;
    }
};

// 使用示例
LockFreeQueue<cv::Mat> frame_queue;

方案 2:减少线程数量(快速验证)

先改为单线程测试,确认是否是线程同步问题:

// 暂时注释掉第二个推理线程
// std::thread infer_thread_1(infer_loop, 1);
std::thread infer_thread_0(infer_loop, 0);

如果单线程帧率恢复正常,说明是线程同步问题。

方案 3:优化同步机制

如果必须用双线程,改用条件变量替代忙等待:

#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
bool frame_ready = false;

// 生产者
{
    std::lock_guard<std::mutex> lock(mtx);
    frame = get_frame();
    frame_ready = true;
    cv.notify_one();
}

// 消费者
{
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, []{ return frame_ready; });
    frame_ready = false;
    // 处理 frame
}

方案 4:检查是否有隐式同步

常见坑点:

// ❌ 避免:在推理线程中调用阻塞的 USB 读取
auto frame = usb_camera.read(); // 可能阻塞

// ✅ 改为:取图和推理完全分离
// 线程 1: 只负责取图 → 放入队列
// 线程 2: 只负责从队列取图 → 推理

验证步骤

1. 先测单线程

# 修改代码只保留一个推理线程,重新编译运行
# 预期:帧率应该接近 100+ FPS

2. 检查锁的使用

# 搜索代码中的锁相关调用
grep -rn "mutex\|lock\|wait" your_cpp_code/

3. 使用 perf 分析线程等待

# 安装 perf
sudo apt install linux-tools-generic

# 运行程序时采样
sudo perf record -g -p <your_pid>

# 查看线程等待时间
sudo perf report

参考案例

社区有类似优化案例:


下一步

请尝试方案 2(单线程测试),5 分钟内就能验证是否是线程同步问题。如果是,再实施方案 1(无锁队列)。

需要我帮你审查具体的线程同步代码吗?可以贴出关键的线程创建和同步部分。