searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

线程独享CPU的方法介绍

2023-06-26 08:41:46
64
0

线程独享CPU的方法介绍

问题陈述

有些时候我们为了获取更高的性能,不仅需要一个线程在指定的cpu上跑,还需要这个线程独享这个cpu,即其他的线程不要在这个cpu上跑。我们可以利用cgroup机制,将一组线程和一组cpu核建立双向绑定关系,即这组线程只能跑在这组cpu核上,同时这组cpu核上也只允许跑这组线程。每个线程再通过调用sched_setaffinity或类似的库函数达到独享cpu的目的。

cgroup背景

一个cgroup组包含一组具有同样的限制或者属性的进程/线程。比如一个cgroup组有4个线程,只有他们被允许访问cpu核48-51。子系统(subsystem)或者资源控制器(resource controller)是控制cgroup进程/线程的限制或者属性的内核组件。这些组件包括cpu, cpuacct, cpuset, memory, devices, net_cls, blkio, perf_event, net_prio, hugetlb, pids, rdma等。其中cpuset是允许cgroup进程/线程访问一组cpu核或者numa节点的组件。cpuset是通过sysfs来配置的,其根目录是/sys/fs/cgroup/cpuset,表示默认的cgroup组,所有的进程/线程默认都分到这个cgroup组,所有的cpu核也默认分到这个组。根目录下可以建立子目录表示子cgroup组,子目录下可以再建目录表示更低一级的组。不管是哪一级的cgroup组,其目录下都会有如下几个文件可供配置:

  • cpus - cgroup进程/线程允许访问的cpu。
  • mems - cgroup进程/线程允许访问的numa nodes。
  • procs – cgroup进程IDs。
  • tasks – cgroup的线程IDs。

创建cgroup

本节说明如何通过以下脚本来创建一个cgroup组,将允许的cpu核分配到这个cgroup组,下节则说明如何让线程加入到这个cgroup组。

  1. 在根目录下创建两个目录代表两个cgroup组,将我们希望独占的cpu核分配到isolated组,将其他的cpu核分配到housekeeping组。新建线程默认会加入housekeeping组,希望独占cpu的线程则通过下节描述的方法加入到isolated组。
  2. 假设我们有96个cpu核,2个numa node。我们将48-51这4个核分配到isolated组,将其他核分配到housekeeping组。因为isolated组的核都属于numa 0,我们可以只允许isolated组访问numa 0。
  3. 因为我们希望新建的进程/线程加入到housekeeping组,而只有指定的线程才能加入isolated组,所以我们关闭isolated组的sched_load_balance。isolated的上级组的sched_load_balance也需要关闭。一旦打开,子cgroup只能继承,不能更改。
  4. 将默认组里的进程都迁移到housekeeping组。这里要注意的是,有些内核线程必须绑在固定的核上(如下图),因此无法迁移,不过这些线程正常情况下不会对性能造成太大的影响。               

配置后的目录结构如下:

指定线程加入cgroup

可以通过将线程ID写入cgroup组下的tasks文件来将该线程加入到一个cgroup组,以下是线程将自己加入到isolated组并绑核的代码片段:

备选方案

cgroup的优点是配置灵活,可以动态生效。如果线程的数目和绑定的核的关系比较固定,可以不依赖cgroup,直接通过修改内核启动的参数,重启生效。

  1. 在/etc/default/grub启动命令中增加isolcpus参数

GRUB_CMDLINE_LINUX=" crashkernel=512M isolcpus=48,49,50,51“

  1. 更新cfg 文件:

grub2-mkconfig -o /etc/grub2-efi.cfg

  1. 重启生效。
0条评论
0 / 1000
huaxiang
4文章数
1粉丝数
huaxiang
4 文章 | 1 粉丝