gpt4 book ai didi

c++ - 如何对进程的 'manager' 和 'worker' 线程进行优先级排序(或设置调度策略)?

转载 作者:IT王子 更新时间:2023-10-29 01:08:31 25 4
gpt4 key购买 nike

我正在运行一个进程(在基于 Linux 3.x 的操作系统上),其中:

  • 一些线程是“管理器”线程(为简单起见,假设他们决定哪些工作线程应该做什么,但不做任何 I/O,并且他们需要的 CPU 时间总量更短/更短比工作线程')
  • 更多线程是“工作线程”:它们在计算方面承担繁重的工作,我对它们随时被抢占没有任何问题。

有可能存在超额订阅(即工作线程数超过 HT 英特尔处理器内核的两倍)。现在,我看到的是“管理器”线程没有足够频繁地获得处理器时间。他们并没有完全“饿死”,我只是想给他们一个助力。所以,我很自然地考虑设置不同的线程优先级(我在 Linux 上)——但后来我注意到线程调度程序的不同选择及其效果。在这一点上我感到困惑,或者更确切地说 - 我不清楚:

  • 我应该为经理选择哪种调度策略,为 worker 选择哪种?
  • 我应该将线程优先级设置为什么(如果有的话)?
  • 我的线程是否需要偶尔使用 yield()?

注意事项:

  • 我有意不谈论语言或线程池机制。我想在更一般的背景下问这个问题。
  • 请不要对 CPU 核心做出假设。它们可能有很多,也可能只有一个,也许我需要每个核心上的 worker (或 worker 和经理)。
  • 工作线程可能会也可能不会进行 I/O。不过,欢迎回答他们不执行任何 I/O 的情况。
  • 除了运行我的应用程序外,我并不真的需要系统响应迅速。我的意思是,我宁愿能够在那里使用 SSH 并在没有明显延迟的情况下让我的输入回显给我,但那里没有真正的限制。

最佳答案

UPD 12.02.2015:我进行了一些实验。

理论

将“管理器”线程调度程序更改为 RT(提供 SCHED_DEADLINE/SCHED_FIFO 策略的实时调度程序)有一个明显的解决方案。在这种情况下,“管理器”线程将始终比系统中的大多数线程具有更高的优先级,因此它们几乎总是在需要时获得 CPU。

但是,还有另一种解决方案可以让您继续使用 CFS 调度程序。您对“工作”线程目的的描述类似于批处理调度(在古代计算机很大的时候,用户必须将他的工作放入队列并等待数小时才能完成)。 Linux CFS 通过 SCHED_BATCH 策略支持批处理作业,通过 SCHED_NORMAL 策略支持对话作业。

内核代码中也有有用的注释(kernel/sched/fair.c):

/*
* Batch and idle tasks do not preempt non-idle tasks (their preemption
* is driven by the tick):
*/
if (unlikely(p->policy != SCHED_NORMAL) || !sched_feat(WAKEUP_PREEMPTION))
return;

因此,当“经理”线程或其他事件唤醒“ worker ”时,只有当系统中有空闲 CPU 或“经理”将耗尽其时间片时,后者才会获得 CPU(调整它会改变任务的权重)。

如果不更改调度程序策略,您的问题似乎无法解决。如果“worker”线程非常忙而“manager”很少醒来,他们会得到相同的vruntime。 bonus,所以“worker”总是会抢占“manager”线程(但是你可以增加它们的权重,所以它们会更快地耗尽它们的 bonus)。

实验

我有一台配备 2 个 Intel Xeon E5-2420 CPU 的服务器,它为我们提供了 24 个硬件线程。为了模拟两个线程池,我使用了自己的 TSLoad工作负载生成器(并在运行实验时修复了几个错误 :))。

有两个线程池:tp_manager有 4 个线程和 tp_worker有 30 个线程,都在运行 busy_wait工作负载(仅 for(i = 0; i < N; ++i); )但循环次数不同。 tp_workerbenchmark 工作模式,因此它将运行尽可能多的请求并占用 100% 的 CPU。

这里是示例配置:https://gist.github.com/myaut/ad946e89cb56b0d4acde

3.12(带有调试配置的 Vanilla )

EXP  |              MANAGER              |     WORKER
| sched wait service | sched service
| policy time time | policy time
33 | NORMAL 0.045 2.620 | WAS NOT RUNNING
34 | NORMAL 0.131 4.007 | NORMAL 125.192
35 | NORMAL 0.123 4.007 | BATCH 125.143
36 | NORMAL 0.026 4.007 | BATCH (nice=10) 125.296
37 | NORMAL 0.025 3.978 | BATCH (nice=19) 125.223
38 | FIFO (prio=9) -0.022 3.991 | NORMAL 125.187
39 | core:0:0 0.037 2.929 | !core:0:0 136.719

3.2(股票 Debian)

EXP  |              MANAGER              |     WORKER
| sched wait service | sched service
| policy time time | policy time
46 | NORMAL 0.032 2.589 | WAS NOT RUNNING
45 | NORMAL 0.081 4.001 | NORMAL 125.140
47 | NORMAL 0.048 3.998 | BATCH 125.205
50 | NORMAL 0.023 3.994 | BATCH (nice=10) 125.202
48 | NORMAL 0.033 3.996 | BATCH (nice=19) 125.223
42 | FIFO (prio=9) -0.008 4.016 | NORMAL 125.110
39 | core:0:0 0.035 2.930 | !core:0:0 135.990

一些注意事项:

  • 所有时间都以毫秒为单位
  • 最后一个实验是设置关联性(@PhilippClaßen 建议):管理器线程绑定(bind)到核心 #0,而工作线程绑定(bind)到除核心 #0 之外的所有核心。
  • 管理器线程的服务时间增加了两倍,这可以通过内核并发来解释(处理器具有超线程!)
  • 使用 SCHED_BATCH + nice(TSLoad 不能直接设置权重,但 nice 可以间接设置)稍微减少等待时间。
  • SCHED_FIFO 实验中的负等待时间是可以的:TSLoad 保留 30us,以便它可以做准备工作/调度程序有时间进行上下文切换等。看起来 SCHED_FIFO 非常快。
  • 保留单核并没有那么糟糕,因为它消除了核内并发,服务时间显着减少

关于c++ - 如何对进程的 'manager' 和 'worker' 线程进行优先级排序(或设置调度策略)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28008127/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com