Skip to content

Utils_ThreadUtils

SweerItTer edited this page Feb 21, 2026 · 4 revisions

ThreadUtils API 文档

概述

ThreadUtils 是 utilsCore Utils 模块的线程工具类,提供线程亲和性绑定和实时优先级设置功能。

职责

  • 绑定线程到指定 CPU 核心
  • 设置线程实时优先级
  • 提供重试机制
  • 线程性能优化

适用场景

  • 性能优化(绑定线程到特定核心)
  • 实时任务调度
  • 降低缓存竞争
  • 提高系统吞吐量

平台依赖

  • Linux 平台: 使用 pthread_setaffinity_nppthread_setschedparam
  • ARM/x86: 支持 RK356x 等嵌入式平台

依赖关系

  • 依赖: Linux pthread 库
  • 被依赖: DisplayManager, VisionPipeline, UIRenderer 等模块

类分析

ThreadUtils 类

职责与用途

ThreadUtils 是静态工具类,提供:

  • 线程 CPU 核心绑定
  • 线程亲和性设置
  • 实时优先级设置
  • 重试机制

设计模式

  • 工具类模式: 所有方法都是静态方法
  • 策略模式: 提供不同的绑定策略(简单绑定、带重试绑定)

静态方法

safeBindThread() - 安全绑定线程(带重试)

static bool safeBindThread(std::thread& thread, int cpuCore, int retries = 3)

参数说明:

  • thread (输入): 要绑定的 std::thread 引用
  • cpuCore (输入): CPU 核心编号(0-based)
  • retries (输入): 重试次数(默认 3)

返回值:

  • true: 绑定成功
  • false: 重试次数用尽后失败

所有权归属:

  • 不转移线程的所有权

注意事项:

  1. 如果线程未 joinable,会等待 10ms 后重试
  2. 每次重试失败会等待 10ms
  3. 适用于可能未完全初始化的线程
  4. 控制台输出: 成功时会输出 "Successfully bound thread to core X" 到标准输出
  5. 控制台输出: 失败时会输出 "Failed to bind thread to core X" 到标准输出

使用例程:

std::thread t([]() {
    // 工作线程代码
});

// 安全绑定到 CPU 核心 0,最多重试 3 次
if (ThreadUtils::safeBindThread(t, 0, 3)) {
    // 方法内部已输出成功信息: "Successfully bound thread to core 0"
    printf("Additional success message\n");
} else {
    // 方法内部已输出失败信息: "Failed to bind thread to core 0"
    printf("Additional failure message\n");
}

t.join();

bindCurrentThreadToCore() - 绑定当前线程

static bool bindCurrentThreadToCore(int cpuCore)

参数说明:

  • cpuCore (输入): CPU 核心编号(0-based)

返回值:

  • true: 绑定成功
  • false: 绑定失败

所有权归属:

  • 无所有权转移

注意事项:

  1. 绑定调用线程自身
  2. 适用于主线程或已启动的线程
  3. 使用 pthread_self() 获取当前线程 ID
  4. 控制台输出: 成功时会输出 "Successfully bound current thread to core X" 到标准输出

使用例程:

// 在主线程中调用
if (ThreadUtils::bindCurrentThreadToCore(2)) {
    // 方法内部已输出成功信息: "Successfully bound current thread to core 2"
    printf("Additional success message\n");
}

// 在工作线程中调用
std::thread t([]() {
    if (ThreadUtils::bindCurrentThreadToCore(1)) {
        // 方法内部已输出成功信息: "Successfully bound current thread to core 1"
        printf("Worker thread additional message\n");
    }
    // 工作代码
});

bindThreadToCore() - 绑定指定线程

static void bindThreadToCore(std::thread& thread, int core)

参数说明:

  • thread (输入): 要绑定的 std::thread 引用
  • core (输入): CPU 核心编号(0-based)

返回值: 无(void)

所有权归属:

  • 不转移线程的所有权

注意事项:

  1. 简单绑定,不提供重试机制
  2. 失败时不会抛出异常
  3. 如果需要错误处理,使用 safeBindThread()

使用例程:

std::thread t([]() {
    // 工作线程代码
});

// 直接绑定到 CPU 核心 3
ThreadUtils::bindThreadToCore(t, 3);

t.join();

setRealtimeThread() - 设置实时优先级

static void setRealtimeThread(pthread_t stl_thread_handle, int priority)

参数说明:

  • stl_thread_handle (输入): pthread 线程句柄
  • priority (输入): 优先级(1-99,数值越大优先级越高)

返回值: 无(void)

所有权归属:

  • 无所有权转移

注意事项:

  1. 使用 SCHED_FIFO 调度策略
  2. 优先级范围:1-99
  3. 需要适当的权限(CAP_SYS_NICE)
  4. 失败时会打印错误信息(perror)
  5. 实时优先级适用于关键任务

使用例程:

std::thread t([]() {
    // 关键任务代码
});

// 设置为实时线程,优先级 80
ThreadUtils::setRealtimeThread(t.native_handle(), 80);

t.join();

实际使用示例

DisplayManager 使用示例

// src/pipeline/displayManager.cpp:62-63
void DisplayManager::Impl::start() {
    if (running.exchange(true)) return;
    thread = std::thread(&DisplayManager::Impl::mainLoop, this);
    ThreadUtils::bindThreadToCore(thread, 3);        // 绑定到 CORE 3
    ThreadUtils::setRealtimeThread(thread.native_handle(), 80); // 设置高优先级
}

VisionPipeline 使用示例

// src/pipeline/visionPipeline.cpp:156-157
void VisionPipeline::Impl::start() {
    resume();
    if (running.exchange(true)) return;

    camera->start();
    camera->setThreadAffinity(2);  // 绑定采集线程到 CORE 2

    thread = std::thread(&VisionPipeline::Impl::mainLoop, this);
    ThreadUtils::bindThreadToCore(thread, 1);
    ThreadUtils::setRealtimeThread(thread.native_handle(), 81);
}

UIRenderer 使用示例

// src/pipeline/uiRenderer.cpp:83
void UIRenderer::Impl::start() {
    if (!inited) init();
    Q_ASSERT(QThread::currentThread() == qApp->thread());
    
    // 绑定线程到(主线程) CPU CORE 2
    ThreadUtils::bindCurrentThreadToCore(2);
    // ...
}

线程亲和性原理

CPU 核心绑定

  • 使用 pthread_setaffinity_np 设置线程亲和性
  • cpu_set_t 结构体指定线程可运行的 CPU 核心
  • 绑定后线程只能运行在指定的核心上

性能优势

  • 减少缓存竞争: 不同线程绑定不同核心,减少缓存失效
  • 提高缓存命中率: 线程始终在同一核心运行,缓存更有效
  • 降低上下文切换: 减少线程迁移带来的开销

实时优先级

  • 使用 SCHED_FIFO 调度策略
  • 高优先级线程优先运行
  • 适用于关键任务(如视频渲染、采集)

典型使用场景

场景 1: 多线程绑定不同核心

// 采集线程绑定到 CORE 2
std::thread captureThread([]() {
    ThreadUtils::bindCurrentThreadToCore(2);
    while (running) {
        captureFrame();
    }
});

// 处理线程绑定到 CORE 1
std::thread processThread([]() {
    ThreadUtils::bindCurrentThreadToCore(1);
    while (running) {
        processFrame();
    }
});

// 显示线程绑定到 CORE 3
std::thread displayThread([]() {
    ThreadUtils::bindCurrentThreadToCore(3);
    while (running) {
        displayFrame();
    }
});

场景 2: 带重试的线程绑定

std::thread t([]() {
    // 工作代码
});

// 等待线程完全启动后绑定
std::this_thread::sleep_for(std::chrono::milliseconds(100));

if (ThreadUtils::safeBindThread(t, 0, 5)) {
    printf("Bound successfully\n");
} else {
    printf("Binding failed after 5 retries\n");
}

t.join();

场景 3: 实时任务设置

// 视频采集线程(高优先级)
std::thread captureThread([]() {
    ThreadUtils::bindCurrentThreadToCore(2);
    ThreadUtils::setRealtimeThread(pthread_self(), 90);
    while (running) {
        captureFrame();
    }
});

// 视频处理线程(中优先级)
std::thread processThread([]() {
    ThreadUtils::bindCurrentThreadToCore(1);
    ThreadUtils::setRealtimeThread(pthread_self(), 70);
    while (running) {
        processFrame();
    }
});

注意事项

  1. CPU 核心编号: 从 0 开始,不能超过实际核心数
  2. 权限要求: 设置实时优先级需要 CAP_SYS_NICE 权限
  3. 线程状态: 线程必须 joinable 才能绑定
  4. 重试机制: safeBindThread() 适用于未完全初始化的线程
  5. 实时策略: SCHED_FIFO 是抢占式调度,可能影响其他线程
  6. 优先级范围: 1-99,数值越大优先级越高
  7. 跨平台: 仅支持 Linux 平台
  8. 性能测试: 绑定核心不一定总是提升性能,需要测试验证

相关文档


参考资料

主页

API 文档

DMA 模块

DRM 模块

NET 模块

V4L2 模块

V4L2Param 模块

RGA 模块

MPP 模块

Sys 模块

Mouse 模块

Utils 模块

Clone this wiki locally