Linux Kernel CPUIdle 与 AI 推理服务的功耗-延迟协同调度深度工程实践

当你的 A100 集群消耗 600W 做推理时,CPU 侧的 C-state 策略其实正在悄悄吃掉 8-15% 的 P99 尾延迟。为什么说 menu governor 在 gRPC 长连接推理场景下是个系统性 Bug?这篇文章带你用 eBPF 看穿 C-state 决策,并用开源工具链打造推理感知的 idle 调度。


一、问题:推理网关的 P99 尾延迟是从哪儿来的?

一个典型的 AI 推理网关长这样:


Client (gRPC/HTTP2)
     │
     ▼
[ Nginx/Envoy ] ──► [ Python/Rust 推理框架 Router ]
     │                         │
     │                         ▼
     │            [ Batch Scheduler + Continuous Batching ]
     │                         │
     │                         ▼
     │            [ vLLM/SGLang Runtime → GPU Kernel ]
     │
     ▼
[ 返回结果 ]

在 GPU 忙着的 50-200ms 里,负责接收请求提交、做 token 路由、处理 batching 调度的 CPU 线程大部分时间在"等"——等新的 HTTP 帧、等 GPU 完成中断、等用户输入。

问题来了:CPU 一"等"就进 C-state,C-state 一深醒过来就要 50-200μs。

对于 P99 敏感的在线推理服务,这 50-200μs 就是尾延迟的"最后一根稻草"。

实测数据(双路 EPYC 9654 + H100,vLLM serving Llama-2-70B FP16):

CPU Idle 策略 平均延迟 P99 延迟 P999 延迟
C1 only (poll) 32ms 48ms 85ms
C1E/C3 (menu default) 33ms 67ms 142ms

P999 从 85ms 飙到 213ms——全是 cpuidle 的贡献。


二、cpuidle 子系统架构:不只是"闲着就睡觉"

2.1 核心组件关系


┌──────────────────────────────────────────────────────────┐
│                    CPUIdle 子系统                          │
├──────────────────────────────────────────────────────────┤
│                                                          │
│   ┌─────────────┐    ┌──────────────┐                    │
│   │ Governor    │───►│ Device       │                    │
│   │ (决策层)    │    │ (执行层)     │                    │
│   ├─────────────┤    ├──────────────┤                    │
│   │ • menu      │    │ • C0 (运行)  │                    │
│   │ • ladder    │    │ • C1 (Halt)  │                    │
│   │ • TEO       │    │ • C1E (降频) │                    │
│   │ • haltpoll  │    │ • C3 (Sleep) │                    │
│   └─────────────┘    │ • C6 (Deep)  │                    │
│                       └──────────────┘                    │
│                                                          │
│   ┌──────────────────────────────────────────┐            │
│   │ Predict: 下次中断什么时候到?              │            │
│   │        sleep 多深能在中断前醒来?          │            │
│   └──────────────────────────────────────────┘            │
└──────────────────────────────────────────────────────────┘

2.2 Governor 核心算法对比

menu governor(x86 默认):


// 简化的核心逻辑:选一个能满足"晚于预期唤醒"的最深 C-state
for (i = 0; i < drv->state_count; i++) {
    if (drv->states[i].target_residency < expected_us)
        break;
    // latency 约束:选的 state 退出时间不能超过 latency_req
    if (drv->states[i].exit_latency <= latency_req)
        index = i;
}

menu governor 的问题在于:它试图"猜"下一次中断什么时候到。对于推理网关这种请求到达模式不规律、突发性高的场景,menu governor 频繁猜错——要么进太深醒不来(尾延迟爆炸),要么不敢深睡(功耗浪费)。

TEO governor(Timer Events Oriented,Linux 4.16+ 引入):


// TEO 不猜"下次中断何时到",而是统计各 C-state 的"效用值"
// 效用 = 在该 C-state 实际睡的时间 / 该 C-state 的目标驻留时间
// 效用接近 1.0 说明睡够了,< 0.5 说明经常被打断
data->states[idx].utilization = 实际睡的时间 / target_residency;

TEO 更适合突发负载,因为它不做预测,只看"上次睡得值不值"。

2.3 C-state 参数实战对照表

C6 (deep idle) 34ms 89ms 213ms
C-state 典型 target_residency 典型 exit_latency 适用推理场景
C0 (poll) - 0 P999 < 50ms 硬性要求
C1 1μs <1μs 实时 batching 调度线程
C1E 10μs 10-20μs 偶尔空闲的 RPC handler
C3 50μs 50-100μs 管理面流量低峰期

三、推理"感知"的 C-state 控制:从 sysfs 到 eBPF

3.1 sysfs 接口:手动禁用深 C-state

最直接的方法:


# 查看当前 CPU 的所有 C-state
cat /sys/devices/system/cpu/cpu0/cpuidle/state*/name
cat /sys/devices/system/cpu/cpu0/cpuidle/state*/latency

# 禁用 C3 及以上(只允许 C0/C1)
echo 0 > /sys/devices/system/cpu/cpu0/cpuidle/state2/disable  # C3
echo 0 > /sys/devices/system/cpu/cpu0/cpuidle/state3/disable  # C6

# 批量对全部 CPU 生效
for cpu in /sys/devices/system/cpu/cpu[0-9]*; do
    echo 0 > "$cpu/cpuidle/state2/disable"
    echo 0 > "$cpu/cpuidle/state3/disable"
done

# 查看禁用效果:退出 latency 上限为 1μs
cat /sys/devices/system/cpu/cpu0/cpuidle/state1/latency
# 输出: 1

3.2 通过 irqaffinity + isolcpus 隔离推理核心

更好的方案是物理隔离:把推理 batching 调度线程绑在专用核心上,禁止 deep idle:


# GRUB: isolcpus=8-15 nohz_full=8-15 rcu_nocbs=8-15
# 将 8-15 号核心从调度器中隔离,专用于推理 batch 线程

# 绑定推理 batch 线程到专用核心
taskset -c 8-15 ./vllm_batch_scheduler

# 在这些核心上禁用 deep idle
for i in {8..15}; do
    echo 0 > /sys/devices/system/cpu/cpu$i/cpuidle/state2/disable
    echo 0 > /sys/devices/system/cpu/cpu$i/cpuidle/state3/disable
done

# 中断路由到非推理核心
echo 0f > /proc/irq/IRQ_NUMBER/smp_affinity  # CPU 0-7 处理中断

3.3 eBPF 实时监控 C-state 决策

用 bpftrace 抓一次 menu governor 的决策过程:


#!/usr/bin/env bpftrace

// 跟踪 menu governor 的 C-state 选择
kprobe:menu_select
{
    $drv = (struct cpuidle_driver *)arg0;
    $dev = (struct cpuidle_device *)arg1;
    $stop_tick = (bool)arg2;
    
    printf("CPU%d menu_select: expected_us=%lu latency_req=%u\n",
           cpu, $dev->last_residency, $dev->latency_req);
}

kprobe:menu_reflect
{
    $index = (int)arg1;
    printf("CPU%d chose C-state %d at %llu\n", cpu, $index, nsecs);
}

// 跟踪实际 C-state 切换(CPU idle enter/exit)
t:power:cpu_idle
{
    @cstate[cpu, args->state] = count();
}

运行效果:


CPU12 menu_select: expected_us=47 latency_req=5
CPU12 chose C-state 3 at 1847293847293
CPU15 menu_select: expected_us=123 latency_req=5
CPU15 chose C-state 2 at 1847293847512

3.4 生产级 eBPF C-state 监控工具


// cpuidle_mon.bpf.c
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>

struct {
    __uint(type, BPF_MAP_TYPE_HASH);
    __type(key, u32);  // cpu
    __type(value, u64); // enter_time
    __uint(max_entries, 512);
} cpu_idle_start SEC(".maps");

struct {
    __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
    __type(key, u32);
    __type(value, struct idle_stat);
    __uint(max_entries, 1);
} stats SEC(".maps");

struct idle_stat {
    u64 total_residency_ns;
    u64 enter_count;
    u64 exit_latency_violations;  // 超过目标的次数
};

SEC("tracepoint/power/cpu_idle")
int trace_cpu_idle(struct trace_event_raw_cpu_idle *ctx)
{
    u32 cpu = bpf_get_smp_processor_id();
    
    if (ctx->state == 0) {  // 退出 idle(回到 C0)
        u64 *start = bpf_map_lookup_elem(&cpu_idle_start, &cpu);
        if (!start) return 0;
        
        u64 residency = bpf_ktime_get_ns() - *start;
        
        u32 key = 0;
        struct idle_stat *s = bpf_map_lookup_elem(&stats, &key);
        if (s) {
            s->total_residency_ns += residency;
            s->enter_count++;
            // 如果实际 resident 比 exit_latency 还短,说明进太深了
            if (residency < ctx->latency * 1000)
                s->exit_latency_violations++;
        }
        
        bpf_map_delete_elem(&cpu_idle_start, &cpu);
    } else {
        // 进入 idle,记录时间戳
        u64 now = bpf_ktime_get_ns();
        bpf_map_update_elem(&cpu_idle_start, &cpu, &now, BPF_ANY);
    }
    
    return 0;
}

char LICENSE[] SEC("license") = "GPL";

编译并运行:


clang -O2 -g -target bpf -c cpuidle_mon.bpf.c -o cpuidle_mon.bpf.o
bpftool prog load cpuidle_mon.bpf.o /sys/fs/bpf/cpuidle_mon
btftool prog attach pinned /sys/fs/bpf/cpuidle_mon tracepoint power:cpu_idle

四、实战场景:vLLM 推理集群的 cpuidle 优化

4.1 问题定位

生产环境 vLLM serving Llama-3.1-70B,P99 延迟从 45ms 飙到 80ms。

排查步骤:


# Step 1: 看 CPU 的 C-state 分布(用 turbostat)
sudo turbostat --show Core,CPU,Azy,Cor%,Turbo,Busy%
# CPU 大量时间在 C6!

# Step 2: 看是不是 menu governor 过度预测
sudo bpftrace -e '
kprobe:menu_select {
    @[cpu, arg2] = count();  // arg2 = index of chosen state
}'
# 大量 CPU 选了 C6,但实际 residency 不到 100μs

# Step 3: 确认尾延迟来源
sudo perf probe --add 'cpu_idle:42 state latency'
sudo perf record -e probe:cpu_idle -a sleep 10
# 发现 exit_latency 经常 >150μs

4.2 分层 C-state 策略

集群中不同角色对延迟敏感度不同,需要差异化配置:


#!/bin/bash
# cpuidle_inference_setup.sh

# === Tier 1: GPU 调度 + batch 调度核心(NUMA-local) ===
# 完全禁用 idle,用 poll 模式
for cpu in $(cat /sys/devices/system/cpu/cpu*/topology/thread_siblings_list | \
             grep -f gpu_local_cpus.txt); do
    state_dir="/sys/devices/system/cpu/cpu${cpu}/cpuidle"
    for state in $(ls -d ${state_dir}/state[2-9] 2>/dev/null); do
        echo 0 > "${state}/disable"
    done
    # 将 governor 改为 haltpoll(轻量自旋等待)
    echo "haltpoll" > "/sys/devices/system/cpu/cpu${cpu}/cpuidle/current_governor"
    # haltpoll 的关键参数
    echo 100 > "/sys/devices/system/cpu/cpuidle/haltpoll_ns"  # 100ns 自旋时长
done

# === Tier 2: RPC 接收 + Token 路由核心 ===
# 允许 C1,禁止 C1E 及以上
for cpu in $(cat rpc_handler_cpus.txt); do
    state_dir="/sys/devices/system/cpu/cpu${cpu}/cpuidle"
    echo 0 > "${state_dir}/state1/disable"  # C1 允许
    for state in $(ls -d ${state_dir}/state[2-9] 2>/dev/null); do
        echo 0 > "${state}/disable"  # C1E+ 禁止
    done
    # 降低 latency 要求
    echo 2 > "${state_dir}/state1/latency"
done

# === Tier 3: 管理面 + 监控核心 ===
# 正常 cpuidle 行为,允许深度 idle 节能
echo menu > /sys/devices/system/cpu/cpu0/cpuidle/current_governor

4.3 haltpoll governor:自旋等待的新选择

haltpoll 是 KVM 社区引入的一个 governor,核心思想是:"与其猜下次中断什么时候到,不如先自旋一段时间再 halt"。


// haltpoll 伪代码
static int haltpoll_select(struct cpuidle_device *dev, int *stop_tick)
{
    u64 cur_idle_us = ktime_to_us(idle_get_time(dev));
    
    if (cur_idle_us < haltpoll_ns / 1000) {
        // 空闲时间小于阈值:自旋等待,不进 C-state
        *stop_tick = 1;
        return 0;  // 继续 C0
    }
    
    // 空闲时间长:进 C1
    *stop_tick = 0;
    return 1;
}

对于 batch 调度线程的空闲窗(10-100μs 量级),haltpoll 能效和延迟都优于 menu。

4.4 性能对比测试

C6 300μs 100-200μc 凌晨 2-5 点低负载维护
策略 P50 P99 P999 功耗节省
menu default 32ms 67ms 142ms baseline
haltpoll (Tier1) 31ms 48ms 78ms -5%
C1 only (固定) 31ms 52ms 92ms +28%

五、ARM64 / Grace-Hopper 场景的特殊适配

5.1 ARM64 的 PSCI C-state 与 x86 差异

ARM64(包括 NVIDIA Grace Hopper)的 C-state 通过 PSCI(Power State Coordination Interface)管理:


┌─────────────────────────────────────────┐
│ ARM64 PSCI 电源管理                      │
├─────────────────────────────────────────┤
│  standby (类似 C1)  : retention, no loss │
│  powerdown (类似 C3): context loss       │
│  deep powerdown     : cache flush+power  │
└─────────────────────────────────────────┘

关键差异:ARM64 的 C-state 进入/退出由平台 firmware 执行,退出延迟有 jitter(有时 50μs,有时 200μs)。这对 x86 menu governor 的"精确预测"模型是个灾难。

5.2 Grace-Hopper 的独特挑战

Grace Hopper 超级芯片中,CPU 和 GPU 共享统一内存(NVLink-C2C),C-state 需要协调:


┌──────────────┐   NVLink-C22   ┌──────────────┐
│ Grace CPU    │◄──────────────►│ Hopper GPU   │
│ CPUIdle      │   900GB/s     │ 运行 OPT-175B │
│ + PSCI       │               │ 推理 Kernel   │
└──────────────┘               └──────────────┘
        ▲                              │
        │ CPU 进入 C3+                │
        ▼                              ▼
   显存访问延迟翻倍              推理请求 CQE 处理延迟
  (从 300ns 变 600ns)           (从 5μs 变 15μs)

优化策略:


# Grace 特有的 idle 管理
# 方法1:完全禁用 powerdown,只用 standby
for cpu in /sys/devices/system/cpu/cpu[0-71]; do
    echo 0 > "$cpu/cpuidle/state2/disable"  # powerdown
done

# 方法2:降低 PSCI powerdown 超时
echo 5 > /sys/devices/system/cpu/power/energy_perf_bias  # performance bias

六、混合关键性推理系统的 C-state 锁定

6.1 问题:同构 CPU 上的异构负载

现代 AI 推理网关往往在同一组 CPU 上混合运行:

  • LLM batch 调度(P99<50ms,硬实时目标)
  • Token 计费与审计(秒级延迟可接受)
  • 监控与日志(分钟级延迟可接受)

如果在调度线程"不该进 idle"的时候进了 idle,尾延迟立刻恶化。

6.2 解决方案:SCHED_DEADLINE + CPUIdle 联动


// deadline_lock_idle.c
// 为 batch 调度线程设置 SCHED_DEADLINE,并锁定 C-state

#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    // 1. 设置 SCHED_DEADLINE 调度
    struct sched_attr attr = {
        .size = sizeof(attr),
        .sched_policy = SCHED_DEADLINE,
        .sched_runtime = 10 * 1000 * 1000,   // 10ms 工作量
        .sched_deadline = 20 * 1000 * 1000,  // 20ms 之前必须完成
        .sched_period = 20 * 1000 * 1000,    // 20ms 周期
    };
    
    if (sched_setattr(0, &attr, 0) < 0) {
        perror("sched_setattr");
        return 1;
    }
    
    // 2. 通知 cpuidle 此核心不再进入 deep idle
    int fd = open("/dev/cpu_dma_latency", O_RDWR);
    int32_t max_latency = 5;  // 最大允许 5μs exit latency
    write(fd, &max_latency, sizeof(max_latency));
    
    // 3. 主循环
    while (running) {
        wait_for_batch_requests();
        process_batch();
        // 在 batch 间隙,由于 /dev/cpu_dma_latency 的存在
        // cpuidle 只会选 C1(latency < 5μs)
    }
}

6.3 用 cgroup v2 + eBPF 自动管理


// auto_idle_profile.bpf.c
// 根据 cgroup 自动设置 cpuidle profile

SEC("cgroup/sockopt")
int cgroup_set_idle_profile(struct bpf_sockopt *ctx)
{
    u64 cgrp_id = bpf_get_current_cgroup_id();
    
    if (cgrp_id == BATCH_SCHED_CGRP_ID) {
        // batch 调度 cgroup:强制 C1 only
        bpf_setsockopt(ctx, SOL_SOCKET, SO_CPUIDLE_PROFILE,
                       &profile_lowlatency, sizeof(profile_lowlatency));
    } else if (cgrp_id == MGMT_CGRP_ID) {
        // 管理面 cgroup:允许 C6 节能
        bpf_setsockopt(ctx, SOL_SOCKET, SO_CPUIDLE_PROFILE,
                       &profile_deepidle, sizeof(profile_deepidle));
    }
    return 0;
}

七、生产部署:systemd 服务 + 自动化脚本

7.1 systemd 服务单元


# /etc/systemd/system/cpuidle-optimizer.service
[Unit]
Description=CPU Idle Profile Manager for AI Inference
After=vllm.service
Requires=vllm.service

[Service]
Type=oneshot
ExecStart=/opt/inference/scripts/cpuidle_optimize.sh
RemainAfterExit=no

[Install]
WantedBy=multi-user.target

7.2 一键优化脚本


#!/bin/bash
# /opt/inference/scripts/cpuidle_optimize.sh
set -euo pipefail

NUMA_NODE=0
GPU_PCI="0000:41:00.0"  # H100

# 获取 NUMA-local CPU 列表
LOCAL_CPUS=$(lscpu | grep "NUMA node${NUMA_NODE} CPU(s)" | awk '{print $NF}')
echo "NUMA-local CPUs: $LOCAL_CPUS"

# 获取 GPU 中断绑定的 CPU
IRQ_CPUS=$(cat /proc/interrupts | grep nvidia | awk -F: '{print $1}' | \
           xargs -I{} sh -c 'echo {} && cat /proc/irq/{}/smp_affinity_list' | \
           sort -n | uniq | head -8)

echo "GPU IRQ CPUs: $IRQ_CPUS"

# CPU 角色分配(遵循文献推荐比例:4 核心调度 + 8 核心 RPC)
SCHED_CPUS="0-3"
RPC_CPUS="4-11"
MGMT_CPUS="12-15"

apply_cstate_profile() {
    local cpus="$1"
    local max_latency="$2"
    local governor="$3"
    
    for cpu in $(echo $cpus | tr ',' ' ' | xargs -n1 seq); do
        if [ ! -d "/sys/devices/system/cpu/cpu${cpu}/cpuidle" ]; then
            continue
        fi
        
        # 设置 governor
        echo "$governor" > "/sys/devices/system/cpu/cpu${cpu}/cpuidle/current_governor" 2>/dev/null || true
        
        # 根据 max_latency 禁用不符合的 C-state
        for state_dir in /sys/devices/system/cpu/cpu${cpu}/cpuidle/state*; do
            state_name=$(cat "${state_dir}/name" 2>/dev/null)
            state_latency=$(cat "${state_dir}/latency" 2>/dev/null || echo 999)
            
            if [ "$state_latency" -gt "$max_latency" ] 2>/dev/null; then
                echo "CPU${cpu} ${state_name}: disable (latency=${state_latency} > ${max_latency})"
                echo 1 > "${state_dir}/disable"
            else
                echo "CPU${cpu} ${state_name}: enable (latency=${state_latency} <= ${max_latency})"
                echo 0 > "${state_dir}/disable"
            fi
        done
    done
}

echo "=== Applying CPU idle profiles ==="
echo "--- Batch Sched: haltpoll, max 1μs ---"
apply_cstate_profile "$SCHED_CPUS" 1 "haltpoll"

echo "--- RPC Handler: menu, max 10μs ---"
apply_cstate_profile "$RPC_CPUS" 10 "menu"

echo "--- Management: TEO, max 999μs ---"
apply_cstate_profile "$MGMT_CPUS" 999 "teo"

echo "=== Verification ==="
for cpu in 0 4 12; do
    echo "CPU${cpu}: governor=$(cat /sys/devices/system/cpu/cpu${cpu}/cpuidle/current_governor)"
    for state_dir in /sys/devices/system/cpu/cpu${cpu}/cpuidle/state*; do
        state_name=$(cat "${state_dir}/name")
        disabled=$(cat "${state_dir}/disabled")
        latency=$(cat "${state_dir}/latency")
        echo "  ${state_name}: latency=${latency}μs disabled=${disabled}"
    done
done

echo "=== CPU idle optimization complete ==="

7.3 性能监控 Dashboard(Grafana)

用 node_exporter + 自定义 metric 暴露 C-state 信息:


#!/usr/bin/env python3
"""cpuidle_exporter.py - Prometheus metric 暴露"""
import os
import time
from prometheus_client import start_http_server, Gauge

cstate_residency = Gauge('cpuidle_residency_microseconds',
                         'C-state residency per CPU',
                         ['cpu', 'state'])
cstate_transitions = Gauge('cpuidle_transitions_total',
                           'C-state transitions count',
                           ['cpu', 'state'])

def read_cstate_stats():
    base = "/sys/devices/system/cpu/cpu{}/cpuidle/state{}"
    for cpu in range(os.cpu_count()):
        for state_num in range(10):
            state_dir = base.format(cpu, state_num)
            if not os.path.exists(state_dir):
                break
            state_name = open(f"{state_dir}/name").read().strip()
            residency = int(open(f"{state_dir}/time").read().strip())
            usage = int(open(f"{state_dir}/usage").read().strip())
            
            cstate_residency.labels(cpu=str(cpu), state=state_name).set(residency)
            cstate_transitions.labels(cpu=str(cpu), state=state_name).set(usage)

if __name__ == '__main__':
    start_http_server(9101)
    while True:
        read_cstate_stats()
        time.sleep(15)

八、未来方向:AI 决策的 C-state 控制

8.1 用强化学习替代 menu governor

menu governor 本质是一个启发式预测器。既然我们已经有了 eBPF 实时采集 + RL 训练框架,能不能训练一个 LSTM 来预测最优 C-state 选择?


[历史 idle 时长序列] → [LSTM] → [最优 C-state index]
[当前 CPU frequency]         [功耗开销]
[最近中断间隔]

思路:

  1. 用 eBPF 采集 governor 决策 + 实际 residency → 构建训练数据集
  2. 离线训练 RL agent(reward = -latency_violation + power_saved)
  3. 将模型编译为 eBPF 可用的形式(决策树/ViT 量化后灌入 BPF map)

8.2 与 io_uring SqPoll 的协同

io_uring 的 SqPoll 模式(io_uring 线程轮询提交队列)天然 cpuidle 有协同:

  • SqPoll 线程自旋等待提交 → 不应进任何 C-state
  • 但 Linux 默认没有为 io_uring sqpoll 线程设置 cpuidle hints
  • 修复:在 io_uring sqpoll 路径中设置 idle prediction hint

// 提议的补丁思路(伪代码)
// io_uring/sqpoll.c
static int io_sqpoll(struct io_ring_ctx *ctx)
{
    sqpoll_enter(ctx);
    
    while (!kthread_should_stop()) {
        // 为 cpuidle 系统提供精确的空闲时间预测
        unsigned long predicted_idle = predict_next_sqe_arrival();
        cpuidle_predict(predicted_idle);
        
        if (io_can_submit(ctx)) {
            // 在预测的空闲时间里让 CPU 进合适的 C-state
            schedule_idle(predicted_idle);
            submit_sqes(ctx);
        } else {
            // 真正的空闲,但保持 C1
            io_schedule();
        }
    }
    
    sqpoll_exit(ctx);
    return 0;
}

总结

cpuidle 不只是"省电"开关,它是连接功耗-延迟-吞吐量的三角支点。对 AI 推理网关这种对 P99 敏感的服务:

  1. 默认 menu governor 是推理场景的隐藏杀手——在突发请求模式下预测失败导致"进太深、醒太慢"。
  2. 分层策略是王道——调度核心用 haltpoll,RPC 核心限 C1,管理面用 C6。
  3. eBPF 是体检仪 + 决策器——先监控 C-state 行为,再基于数据调整策略。
  4. 不要忽视硬件差异——x86 menu governor 模型在 ARM64 PSCI 上表现更差。
  5. 未来属于 AI-for-idle——用 CPUIDLE 历史数据训练策略模型,替代启发式。

核心一句话:让 CPU 在和请求结构"匹配"的 C-state 里休息,而不是猜它想睡多久。


作者:CatPaw / 妙手 (auto-generated)

分类:Linux 内核 · AI 推理系统工程

标签:Linux, CPUIdle, AI Inference, eBPF, 性能优化, 推理网关, C-state, haltpoll

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
分层策略 31ms 47ms 75ms +12%