AIGC标识 DPDK场景下GRUB与cpuset的分工

结论

DPDK 低时延 / 零丢包场景下,GRUB 启动参数和 cpuset 都要配置,但不是配两遍同样的隔离,而是分工不同、缺一不可:

  • GRUB(内核启动参数)负责"把内核噪声搬走":让调度器、tick、RCU、中断别落在 DPDK 专用核上;
  • cpuset / EAL(运行期)负责"把 DPDK 线程钉上去":保证 PMD 线程真的落在这批核上,且别的进程不来抢。

只配 GRUB 不配绑核:DPDK 线程不一定落在预期核上;只绑核不配 GRUB:核上依然有 tick / RCU / 中断抖动,低时延指标出不来。两边核号集合必须一致。

分析基于的版本

  • Linux 内核:cgroup v2(5.x 起 cpuset.cpus.partition 支持隔离分区;isolcpus=domain 走 HK_TYPE_DOMAIN_BOOT);
  • DPDK:20.x ~ 25.x(EAL -l / --lcores / --lcores=<lcore>@<cpu> 绑核方式一致);
  • 参考文档:Linux 内核官方 admin-guide/cpu-isolation.rst、core-api/housekeeping.rst、Intel DPDK 官方性能报告。

一、GRUB 和 cpuset 本身会冲突吗

不会在系统层冲突(不会启动失败、内核崩溃),但两者都是 CPU 隔离机制,叠加使用确实存在机制不一致。

GRUB 与 cpuset 冲突机制

关键机制:isolcpus=domain 由内核的 HK_TYPE_DOMAIN_BOOT 管理,它"忽略由 cpuset 执行的隔离";而 cpuset 隔离分区修改的是 HK_TYPE_DOMAIN。两套 housekeeping cpumask 各自维护、互不同步,叠加时就可能配置打架。

三个具体冲突点:

  1. 隔离可被绕过:isolcpus 只是把核移出调度器默认池,这些核仍留在 root cpuset 的 cpuset.cpus 中,cpuset / taskset 仍可显式把任务放上去;硬件中断也照样会落在"隔离"核上。
  2. 两套掩码互不同步:HK_TYPE_DOMAIN_BOOT(isolcpus)与 HK_TYPE_DOMAIN(cpuset 分区)各管各的,housekeeping 任务可能被排到"已隔离"的核上。
  3. 已记录的真实故障:Red Hat 已知问题(RHEL 6/7)——内核更新后 cpuset 不再在 isolcpus 的 CPU 上做负载均衡,任务分配行为异常。

另外有个硬约束:系统必须至少保留 1 个在线 housekeeping CPU(通常 CPU0),不能把全部核隔离。

二、DPDK 场景:两边各干什么

DPDK 场景 GRUB 与 cpuset 分工

2.1 GRUB 侧(必配,且不止 isolcpus)

Intel DPDK 官方性能报告的标准内核行就是 isolcpus + nohz_full + rcu_nocbs 一组同时给,并注明 nohz_full / rcu_nocbs 对零丢包很关键。

参数 作用
isolcpus=<DPDK核> 把核移出调度器默认负载均衡
nohz_full=<DPDK核> 关闭周期 tick(要求核上只有一个任务)
rcu_nocbs=<DPDK核> RCU 回调外移到 housekeeping 核
irqaffinity=<管理核> 中断默认绑到 housekeeping 核
可选 nosmt、iommu=pt、intel_pstate=disable、processor.max_cstate=、numa_balancing=disable、巨页

示例(DPDK 专用核 2-7,管理核 0-1):

GRUB_CMDLINE_LINUX="isolcpus=nohz,domain,managed_irq,2-7 nohz_full=2-7 rcu_nocbs=2-7 irqaffinity=0-1 intel_iommu=on iommu=pt default_hugepagesz=1G hugepagesz=1G hugepages=16"

新式写法(内核官方推荐):调度器域隔离交给 cgroup v2 cpuset partition(运行时可调),GRUB 只写 nohz_full、irqaffinity、isolcpus=managed_irq,<核>,避免与 cpuset partition 在同一批核上叠用。

2.2 cpuset 侧(需要,但角色是"把 DPDK 送上去")

isolcpus 只是让调度器"默认不往这些核放任务",但还要保证 DPDK 线程确实落在这些核上。三种等价绑核方式,选一种即可,不要全叠:

  1. DPDK EAL -l <核列表> / --lcores:启动时用 pthread_setaffinity_np 把 lcore 钉到指定核——裸机最简,这种情况甚至不需要单独 cpuset;
  2. systemd AllowedCPUs= / K8s CPU pinning / cgroup cpuset.cpus:服务化、容器化管理时推荐,整个进程树都被约束;
  3. taskset -cp:一次性临时绑核,调试用。

三、避坑点

  1. 核号必须一致:GRUB 里 isolcpus / nohz_full / rcu_nocbs 的核 = cpuset / EAL 给 DPDK 的核,错配是最常见的"配了没效果"。
  2. 不要对同一批核同时用 isolcpus=domain 和 cgroup v2 cpuset.cpus.partition=isolated——这就是 HK_TYPE_DOMAIN_BOOT 忽略 cpuset 隔离的坑。
  3. 一核一个 PMD 线程:nohz_full 只在核上跑单个任务时生效;核上多个活任务会自动恢复 tick,nohz 白配。main / 管理线程放 housekeeping 核。
  4. 至少保留一个 housekeeping 核(通常 CPU0):中断、RCU 回调、未绑定 workqueue / kthread、内务统计都跑在这里。
  5. 确认 irqbalance 不再把中断迁回 DPDK 核;irqaffinity= 只是默认值,网卡中断仍需检查。

四、验证方法

# 查看内核隔离的核
cat /sys/devices/system/cpu/isolated

# 查看某 cgroup 的实际可用核
cat /sys/fs/cgroup/<path>/cpuset.cpus.effective

# 查看中断亲和性
cat /proc/irq/*/smp_affinity

# 查看 DPDK 进程绑核情况
taskset -cp <dpdk-pid>

# 抖动 / 噪声实测
rtla osnoise

一句话总结

GRUB 写 isolcpus=<核> nohz_full=<核> rcu_nocbs=<核> irqaffinity=<管理核>,应用侧用 EAL -l 或 systemd AllowedCPUs= 钉住同一批核——前者搬走内核噪声,后者钉住数据面线程,这就是 DPDK 官方性能报告里"零丢包"配置的完整形态。

posted on 2026-09-20 08:41  王景迁  阅读(16)  评论(0)    收藏  举报

导航