可以使用sched_setaffinity将线程固定到cpu,从而提高性能(在某些情况下)

从linux手册页:



此外,如果我希望获得更实时的响应,则可以将该线程的调度程序策略更改为SCHED_FIFO,并将优先级提高到某个较高的值(最高sched_get_priority_max),这意味着有问题的线程应始终抢占其他线程准备就绪时,线程在其cpu上运行。

但是,在这一点上,运行在刚刚被实时线程抢占的cpu上的线程可能已经淘汰了许多实时线程的1级缓存条目。

我的问题如下:

  • 是否可以防止调度程序将任何线程调度到给定的cpu上? (例如:要么完全从调度程序中隐藏cpu,要么以其他方式隐藏)
  • 是否有一些绝对必须能够在该CPU上运行的线程? (例如:内核线程/中断线程)
  • 如果我需要在该CPU上运行内核线程,那么要使用什么合理的最大优先级值,这样我才不会饿死内核线程?
  • 最佳答案

    答案是使用cpusetspython cpuset utility使配置它们变得容易。

    基本概念

    3个cpusets

  • root:存在于所有配置中,并包含所有cpus(非屏蔽)
  • system:包含用于系统任务的cpus-需要运行但不是“重要”(未屏蔽)的
  • user:包含用于“重要”任务的cpus-我们要在“实时”模式下运行的(屏蔽)
  • shield命令管理这3个cpuset。

    在安装过程中,它将所有可移动任务移动到非屏蔽cpuset(system)中,在拆卸期间,将所有可移动任务移动到root cpuset中。
    设置完成后,该子命令使您可以将任务移动到shield(user)cpuset中,此外,还可以将特殊任务(内核线程)从root移至system(因此也移出user cpuset)。

    命令:

    首先,我们创建一个盾牌。自然,防护罩的布局将取决于机器/任务。例如,假设我们有一台4核非NUMA机器:我们想将 3核专用于屏蔽,而将 1核专用于无关紧要的任务;因为它不是NUMA,所以我们不需要指定任何内存节点参数,并且让内核线程在root cpuset中运行(即:跨所有cpus)
    $ cset shield --cpu 1-3
    

    可以将某些内核线程(那些未绑定(bind)到特定CPU的线程)移到system cpuset中。 (通常,移动已绑定(bind)到特定CPU的内核线程不是一个好主意)
    $ cset shield --kthread on
    

    现在,让我们列出屏蔽(user)或非屏蔽(system)cpusets中正在运行的内容:( verbt的-v,它将列出进程名称)(添加第二个-v以显示80个以上字符)
    $ cset shield --shield -v
    $ cset shield --unshield -v -v
    

    如果我们要停止盾牌(拆解)
    $ cset shield --reset
    

    现在让我们在屏蔽中执行一个过程('--'之后的命令传递给要执行的命令,而不是cset)
    $ cset shield --exec mycommand -- -arg1 -arg2
    

    如果我们已经有一个正在运行的进程想要移入屏蔽中(请注意,我们可以通过传递逗号分隔的列表或范围来移动多个进程(即使存在间隙,该范围内的任何进程也会移动))
    $ cset shield --shield --pid 1234
    $ cset shield --shield --pid 1234,1236
    $ cset shield --shield --pid 1234,1237,1238-1240
    

    高级概念
    cset set/proc-这些使您可以更好地控制cpuset

    设置

    创建,调整,重命名,移动和销毁cpuset

    指令

    使用cpus 1-3创建一个cpuset,使用NUMA节点1并将其命名为“my_cpuset1”
    $ cset set --cpu=1-3 --mem=1 --set=my_cpuset1
    

    将“my_cpuset1”更改为仅使用CPU 1和CPU 3
    $ cset set --cpu=1,3 --mem=1 --set=my_cpuset1
    

    销毁一个cpuset
    $ cset set --destroy --set=my_cpuset1
    

    重命名现有的cpuset
    $ cset set --set=my_cpuset1 --newname=your_cpuset1
    

    创建一个分层的cpuset
    $ cset set --cpu=3 --mem=1 --set=my_cpuset1/my_subset1
    

    列出现有的CPU集(级别1的深度)
    $ cset set --list
    

    列出现有的cpuset及其子级
    $ cset set --list --set=my_cpuset1
    

    列出所有现有的CPU
    $ cset set --list --recurse
    

    过程

    管理线程和流程

    指令

    列出在cpuset中运行的任务
    $ cset proc --list --set=my_cpuset1 --verbose
    

    在cpuset中执行任务
    $ cset proc --set=my_cpuset1 --exec myApp -- --arg1 --arg2
    

    移动任务
    $ cset proc --toset=my_cpuset1 --move --pid 1234
    $ cset proc --toset=my_cpuset1 --move --pid 1234,1236
    $ cset proc --toset=my_cpuset1 --move --pid 1238-1340
    

    移动任务及其所有同级
    $ cset proc --move --toset=my_cpuset1 --pid 1234 --threads
    

    将所有任务从一个CPU移动到另一个
    $ cset proc --move --fromset=my_cpuset1 --toset=system
    

    将未固定的内核线程移入cpuset
    $ cset proc --kthread --fromset=root --toset=system
    

    强制将内核线程(包括固定到特定cpu的那些线程)移入cpuset(注意:这可能会对系统造成可怕的后果-确保您知道自己在做什么)
    $ cset proc --kthread --fromset=root --toset=system --force
    

    层次结构示例

    我们可以使用分层cpusets创建优先分组
  • 用1个cpu(0)创建system cpuset
  • 用1个cpu(1)
  • 创建一个prio_low cpuset
  • 用2个cpus(1-2)创建prio_met cpuset
  • 使用3 cpus(1-3)
  • 创建prio_high cpuset
  • 用所有4个cpus(0-3)创建一个prio_all cpuset(请注意与root相同;这是与根分开的一种好习惯)

  • 为此,您需要创建prio_all,然后在prio_all下创建子集prio_high,等等。
    $ cset set --cpu=0 --set=system
    $ cset set --cpu=0-3 --set=prio_all
    $ cset set --cpu=1-3 --set=/prio_all/prio_high
    $ cset set --cpu=1-2 --set=/prio_all/prio_high/prio_med
    $ cset set --cpu=1 --set=/prio_all/prio_high/prio_med/prio_low
    

    关于linux - 如何屏蔽Linux调度程序中的CPU(防止将线程调度到该CPU上)?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11111852/

    10-10 00:47