Files
rtos_llm_opt/项目框架1-基于RTOS的五类场景AI实时性研究/10-研究框架/03-加速器协同调度.md
T

19 KiB
Raw Blame History

方向3: 加速器协同调度 (CPU + NPU/GPU)

1. 问题陈述

任务关键系统中的人工智能目标负载往往依赖专用加速器(NPU/GPU/DSP)与 CPU 协同完成计算。RTOS 需要协调 CPU 与加速器协同工作。核心问题:

  1. 速度不匹配: CPU和加速器的速度比通常是1:5~1:10,容易产生stall
  2. 状态不可见: NPU驱动通常封闭,无法精确感知NPU状态
  3. 数据传输开销: CPU↔NPU的数据传输是瓶颈
  4. 同步开销: barrier/semaphore的实时性分析复杂

1.1 本方向在总课题中的角色

本方向聚焦:

  • 如何让 RTOS 对人工智能目标负载的设备计算阶段建立可管理的节拍;
  • 如何避免 CPU、加速器、DMA 和中断之间的协同开销侵蚀关键保障负载边界;
  • 如何把异构设备协同从黑盒调用,转化为可分析、可限流、可恢复的系统机制。

因此,这一方向服务的是总课题中的“设备协同与异构执行可预测性”主线。

1.2 与验证矩阵的对应关系

加速器协同在 T5~T1 中的实现方式差异很大,因此需要按部署形态看重点:

部署形态 加速器协同侧重点
T5 控制端 无加速器或轻量 DSP/NPU 下的简化协同
T4 终端设备 SoC 内 CPU 与片上 NPU 的同步与拷贝开销
T3 边缘节点 多核 CPU 与外设/NPU/GPU 的流水线协同
T2 单机工作站 CPU 与独立 GPU 的队列、DMA 与中断协同
T1 服务器/集群 多 GPU、多 NUMA 域与多进程协同执行

2. 加速器架构分析

2.1 常见加速器类型

┌─────────────────────────────────────────────────────┐
│  Accelerator Types                                   │
├──────────────────┬───────────────────────────────────┤
│  NPU             │ Neural Processing Unit            │
│                  │ • 专为矩阵乘设计                    │
│                  │ • 低精度(INT8/FP16)               │
│                  │ • 固定function, 可编程interface    │
│                  │ 例: 骁龙Hexagon, RK3588 NPU       │
├──────────────────┼───────────────────────────────────┤
│  GPU             │ Graphics Processing Unit          │
│                  │ • 通用并行计算                    │
│                  │ • 高带宽, 高功耗                  │
│                  │ • 成熟软件栈(CUDA/OpenCL)         │
│                  │ 例: Adreno, Mali, PowerVR        │
├──────────────────┼───────────────────────────────────┤
│  DSP             │ Digital Signal Processor          │
│                  │ • 向量/标量并行                   │
│                  │ • 低功耗, 适合小模型              │
│                  │ 例: Hexagon DSP, Kryo             │
├──────────────────┼───────────────────────────────────┤
│  DPU             │ Deep Learning Processing Unit     │
│                  │ • 固定功能, 低延迟                │
│                  │ • 适合known architecture          │
│                  │ 例: Xilinx DPU, 平头哥玄铁        │
└──────────────────┴───────────────────────────────────┘

2.2 CPU-加速器通信路径

              CPU                          Accelerator
        ┌─────────────┐              ┌──────────────┐
        │             │  DMA/Bus     │              │
        │  Task Queue │─────────────→│  Command Q   │
        │             │              │              │
        │  Memory     │←──DMA/Bus───│  Memory      │
        │  Pool       │              │  Pool        │
        │             │              │              │
        │  Event Q    │←────────────│  Interrupt   │
        └─────────────┘              └──────────────┘

通信机制:
  1. Shared Memory: 零拷贝,通过DMA传递数据
  2. Command Queue: CPU写入命令,加速器执行后完成
  3. Interrupt: 加速器完成后的异步通知
  4. Memory Barrier: 保证CPU和加速器看到的内存一致性

3. 协同调度模型

3.1 典型LLM推理的CPU-加速器交互

┌─────────────────────────────────────────────────────────────┐
│  Phase: Prefill (Batch Inference)                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  CPU:                        Accelerator:                   │
│  ┌──────────┐                ┌──────────────────┐          │
│  │Tokenizer │    DMA→        │                  │          │
│  └──────────┘                │  Embedding       │          │
│       ↓                      └────────┬─────────┘          │
│  ┌──────────┐               ┌────────┴─────────┐          │
│  │Control    │──Cmd──→       │  Attention L1..N │          │
│  │ (plan)   │               └────────┬─────────┘          │
│  └──────────┘               ┌────────┴─────────┐          │
│       ↓                     │  FFN L1..N       │          │
│  ┌──────────┐               └────────┬─────────┘          │
│  │Monitor    │←──IRQ──│              │                    │
│  │ (wait)   │                               ┌────────────┐│
│  └──────────┘          ┌───────────────────┐│  Output   ││
│                         │  KV Cache Write  │└─────┬──────┘│
│                         └───────────────────┘      │      │
└─────────────────────────────────────────────────────────────┘

Timeline:
  CPU: | Tokenize | Plan | Wait | Monitor | Process Output |
  NPU: |-------- Embedding + Layers + Output --------|
  Time: 5ms        20ms (NPU compute)              5ms
  Total E2E: ~30ms (mostly dominated by NPU)

3.2 解码阶段的流水线

Decode Phase (逐token生成):

  Step i:                        Step i+1:
  ─────────                      ─────────
  CPU:  Send Cmd     NPU: Execute Layer 1..N
         Wait ←───────────────→  CPU:  Send Cmd
                                NPU: Execute Layer 1..N

  问题: CPU SendCmd 和 NPU Execute 之间有gap
  原因: NPU完成前CPU需等待

  优化: Double Buffering
  ──────────────────────────────
  CPU:  Send(i)   Send(i+1)  Send(i+2)
  NPU:  Exec(i)   Exec(i+1)  Exec(i+2)

  实现:
    - 两个buffer: buf_A, buf_B
    - CPU写buf_A时,NPU读buf_A
    - 完成后swap: CPU写buf_B,NPU读buf_B
    - 需要RTOS semaphore管理buffer swap

4. 同步与通信机制

4.1 同步原语

// NPU协同同步原语
typedef struct {
    // 命令同步
    SemaphoreHandle_t cmd_complete;  // 命令完成信号
    SemaphoreHandle_t data_ready;    // 数据就绪信号
    
    // 双缓冲管理
    uint8_t *buffers[2];            // 双buffer
    uint8_t active_buf;             // 当前active buffer
    SemaphoreHandle_t buf_swap;     // buffer交换信号
    
    // 事件通知
    EventGroupHandle_t events;      // 事件组
} npu_sync_t;

// 同步流程
void npu_sync_wait(npu_sync_t *sync) {
    // 等待NPU完成当前命令
    xSemaphoreTake(sync->cmd_complete, portMAX_DELAY);
    // 交换buffer
    xSemaphoreTake(sync->buf_swap, portMAX_DELAY);
}

void npu_sync_signal(npu_sync_t *sync) {
    // NPU完成中断回调
    xSemaphoreGiveFromISR(sync->cmd_complete, NULL);
    xSemaphoreGiveFromISR(sync->buf_swap, NULL);
}

4.2 中断处理策略

┌─────────────────────────────────────────────┐
│  Interrupt Hierarchy                         │
├─────────────────────────────────────────────┤
│  Level 0: Hard IRQ (NPU完成中断)             │
│  动作: 提升task优先级, 触发barrier           │
│  时间: <10μs                                │
├─────────────────────────────────────────────┤
│  Level 1: SW IRQ (NPU驱动层)                 │
│  动作: 释放semaphore, 唤醒task               │
│  时间: <50μs                                │
├─────────────────────────────────────────────┤
│  Level 2: Soft IRQ (任务调度)                │
│  动作: 调度下一个task                        │
│  时间: <100μs                               │
└─────────────────────────────────────────────┘

关键设计:
  - NPU完成中断 → 直接唤醒attention task (不经过软中断)
  - 使用Interrupt-to-Semaphore模式, 避免context switch开销
  - 中断处理函数最小化, 尽量defer到task层

5. 调度策略

5.1 Pipeline并行调度

Layer Pipeline (各层在加速器上流水执行):

Layer:    L1         L2         L3         L4
         [Attn][FFN][Attn][FFN][Attn][FFN][Attn][FFN]
CPU:      [Plan]  [Plan]  [Plan]  [Plan]  [Collect]
Time:     ↓         ↓         ↓         ↓

Scheduling:
  1. CPU先plan Layer 1的Attention
  2. L1 Attn执行时, CPU plan L2 Attn
  3. L1 Attn完成 → L1 FFN启动
  4. CPU plan L3 Attn
  ...

RTOS实现:
  - 每个Layer的Attn/FFn是一个task
  - CPU上跑"planner" task
  - 加速器上跑"compute" task
  - 通过barrier同步相邻Layer

5.2 Cross-device Scheduling (多加速器)

Example: SoC with both NPU + GPU

    Request A: Large matrix → NPU (矩阵乘优化)
    Request B: Conv/Embed → GPU (并行度高)
    Request C: Small ops → DSP (低功耗)

调度问题:
  - 哪个加速器处理哪个请求?
  - 资源冲突时如何仲裁?
  - 数据在设备间传输的开销?

调度策略:
  1. Capability-based: 根据加速器能力分配
  2. Load-based: 根据当前负载分配
  3. Hybrid: capability + load

RTOS实现:
  typedef struct {
      enum accel_type { ACCEL_NPU, ACCEL_GPU, ACCEL_DSP } type;
      uint32_t utilization;        // 当前利用率
      uint32_t queue_depth;        // 排队深度
      uint64_t avg_latency_us;     // 平均延迟
      SemaphoreHandle_t lock;      // 资源锁
      QueueHandle_t cmd_queue;     // 命令队列
  } accel_resource_t;

  accel_resource_t* select_accelerate(task_t *task) {
      // 1. Filter by capability
      if (task->compute_type == MATRIX_MUL) return npu;
      if (task->compute_type == CONV) return gpu;
      
      // 2. Pick least loaded
      return min_utilization(all_accelerators);
  }

5.3 Async Pipeline Scheduling

CPU side (RTOS task):
┌────────────────────────────────────────────┐
│  Task: NPU Dispatcher (priority: HIGH)     │
│                                            │
│  while (running) {                         │
│      cmd = dequeue_command();              │
│      send_to_npu(cmd);                     │
│      wait_for_irq();                       │  // 阻塞等待
│      if (complete) {                       │
│          process_result();                 │
│          dispatch_next();                  │
│      }                                     │
│  }                                         │
└────────────────────────────────────────────┘

NPU side (hardware):
┌────────────────────────────────────────────┐
│  Command Queue (FIFO):                      │
│  ├─ Cmd 1: Attention Layer 1               │
│  ├─ Cmd 2: FFN Layer 1                    │
│  ├─ Cmd 3: Attention Layer 2              │
│  └─ ...                                    │
│                                            │
│  Execution: Sequential (FIFO) or           │
│             Out-of-order (with dependencies)│
└────────────────────────────────────────────┘

6. 数据传输优化

6.1 DMA策略

传输类型              | 策略                    | 优化手段
---------------------|------------------------|------------------
CPU→NPU (weights)   | 一次性批量DMA           | PCIe burst
CPU→NPU (input)     | 流水线DMA               | 预读
NPU→CPU (output)    | 完成中断+DMA pull        | 零拷贝
NPU→NPU (cross)     | 共享内存 + cache sync    | invalidate+clean

DMA Descriptor设计:
typedef struct {
    uint32_t src_addr;      // 源地址
    uint32_t dst_addr;      // 目的地址
    uint32_t size;          // 传输大小
    uint32_t flags;         // 同步/异步/中断
    uint32_t completion_irq; // 完成后是否触发中断
    uint32_t next_desc;     // 链式DMA描述符
} dma_desc_t;

// 链式DMA: 多个描述符连成链, 一次性提交
// 减少RTOS调用次数, 提高DMA效率
void dma_chain_submit(dma_desc_t *head) {
    // Submit chain to DMA controller
    // No RTOS calls needed during transfer
    // Only interrupt on last descriptor
}

6.2 零拷贝技术

Before:
  CPU alloc:  malloc(input)    // 分配
  memcpy:     copy(input)      // 拷贝到临时buffer
  DMA:        transfer(temp)   // DMA从temp传输
  Total: 2 copies + 1 DMA

After (zero-copy):
  CPU alloc:  mmap(shared_mem) // 共享内存
  Direct:     write(shared)    // CPU直接写
  DMA:        transfer(shared) // DMA直接从shared传输
  Total: 0 copies + 1 DMA

RTOS实现:
  - 使用mmap或共享内存驱动
  - CPU和NPU使用同一块物理内存
  - 通过memory barrier保证一致性
  - 使用RTOS semaphore管理访问权限

7. 各平台的加速器协同差异

7.1 MCU级

典型: STM32H7 + Cortex-M7 (CPU) + DSP (协处理器)
- 无NPU, 纯CPU/DSP矩阵运算
- 共享SRAM, 无DMA或简单DMA
- 协同简单: CPU调用DSP函数, 等待完成

关键优化:
  - DSP的并行化调度
  - 内存bank切换减少bank冲突
  - 无共享内存, 需手动memcpy

7.2 SoC级

典型: 骁龙8 Gen + Kryo CPU + Hexagon NPU
- NPU驱动封闭, 使用QMI接口通信
- 共享内存通过RPMsg (Remote Processor Messaging)
- 中断: ARM GIC → Hexagon

关键挑战:
  - NPU状态不完全可见
  - QMI通信有固定开销(~100μs)
  - 需估算NPU延迟, 不能精确测量

RTOS策略:
  - 使用QMI异步API
  - 通过Event FD等待NPU完成
  - 双Buffer管理QMI传输

7.3 Edge盒子

典型: Jetson Orin + ARM CPU + NVIDIA GPU
- GPU驱动开放, CUDA API可用
- 成熟的stream/executor模型
- PCIe x16连接

关键优势:
  - 可精确控制GPU调度
  - CUDA Stream可映射为RTOS task
  - NVLink多GPU调度成熟

RTOS集成:
  - CUDA Runtime作为RTOS task的一部分
  - GPU completion → RTOS event
  - DMA between CPU↔GPU via PCIe

7.4 Server级

典型: x86 + 多GPU + NVLink
- 成熟的vLLM/TGI框架
- PCIe/NVLink互联
- NUMA拓扑

RTOS角色:
  - 管理GPU进程
  - 处理NVLink中断
  - 提供实时性保证给GPU inference

调度:
  - vLLM already does PagedAttention scheduling
  - RTOS主要保障中断响应

8. 本方向的验证关注点

为了让本方向与总课题的双目标评价框架对齐,加速器协同机制至少要回答下面三个问题:

  1. 设备协同是否降低了人工智能目标负载的等待时间、传输开销和端到端抖动;
  2. DMA、中断和共享内存竞争是否会冲击关键保障负载的响应时间边界;
  3. 当加速器状态不可见、延迟波动或发生故障时,系统是否仍具备准入、限流和恢复能力。

9. 关键设计决策

决策点 选项 推荐 理由
同步模式 Sync / Async / Event Async + Event 最大化并行度
缓冲策略 Single / Double / Triple Triple 最大化流水线效率
数据传输 Copy / DMA / Shared DMA + Shared 零拷贝+低CPU占用
加速决策 Static / Dynamic Dynamic 根据负载自动选择
中断模式 Polling / Interrupt / Event Interrupt 实时性最好
错误处理 Retry / Skip / Report Retry + Report 保证正确性

10. 开放研究问题

  1. Black-box NPU Scheduling: 加速状态不可知时的调度策略?
  2. Cross-accelerator Load Balancing: 多加速器间的动态负载均衡?
  3. Accelerator Fault Recovery: 加速器故障时的降级调度?
  4. Predictive Pipeline: 预测NPU延迟, 优化pipeline stall?
  5. Heterogeneous Memory: CPU/NPU共享内存的一致性管理?

最后更新: 2026-09-17