【问题标题】:How to experimentally determine the scheduling quantum of a process/thread?如何通过实验确定进程/线程的调度量?
【发布时间】:2016-09-27 02:47:12
【问题描述】:

只是为了阻止任何 cmet 产生“你为什么需要知道这个??”:这只是一个我很好奇的谜题,而不是出于任何实际原因我需要做的事情。

给定一个典型的 POSIX 系统[1],您将如何设计一个实验来确定 CPU 密集型进程的调度量[2]?

[1]:但不能让您通过系统调用或 /proc 接口查询此信息

[2]:“调度时间量”定义为进程在其调度时间结束且操作系统允许其他进程运行之前在 CPU 上运行而不会阻塞或让步的时间量。

【问题讨论】:

  • 请注意,更高优先级的进程通常会在它想要的时候立即运行(否则就没有更高的优先级了)。也许在您的最后一段中,您的意思是“......在其预定时间结束并且操作系统允许另一个相同优先级的进程运行之前。”
  • @JeremyFriesner 我认为在典型的系统中,进程在它们的时间片到期之前不会被抢占。我弄错了吗?它是如何在 Linux 或 FreeBSD 中工作的?无论如何,我已经编辑了这个问题。
  • 通常一个进程将继续运行,直到 (a) 它的时间片过期(另一个具有相同优先级的进程准备好运行),或者 (b) 另一个具有更高优先级的进程准备好运行跑步。 (另一种方法,即准备运行的高优先级进程因为较低的进程正在运行而没有运行,这被称为优先级反转,这是调度程序设计人员试图避免的事情)
  • @JeremyFriesner 在一个 1 核系统上,如果一个高优先级的 CPU 绑定线程永远旋转,除非调度程序发现它需要降低优先级,否则没有其他线程可以运行?这似乎是错误的,但我不是专家。
  • 在具有静态优先级的系统中,这正是可能发生的事情。这很常见,例如在实时系统中,如果高优先级线程从不放弃 CPU,那么您可能必须重新启动计算机才能重新获得对它的控制权。当然,有一个错误的程序使您的计算机无法控制并不是一个非常理想的行为,这就是为什么一些非实时操作系统(尤其是 Unix/Linux)如果它未能自愿放弃 CPU(例如通过阻塞)很长时间。 (见:informit.com/articles/article.aspx?p=101760

标签: multithreading scheduling experimental-design


【解决方案1】:

我认为您可以通过对以下系统的足够运行次数进行统计分析得到答案:

  • 每个处理器运行一个线程以清除终止标志,然后运行一个循环进行固定次数的迭代或直到设置终止标志,以先到者为准。这些线程记录它们是由于运行所有迭代而终止,还是由于设置了终止标志。

  • 同时,运行一个设置终止标志的附加线程。

在循环中进行各种迭代次数。

如果循环在线程时间片内完成,它将完成所有迭代。如果它没有在线程时间片内完成,终止线程将有机会中断其中一个循环线程。

现在,终止线程有时会首先被调度,并且可能还有其他线程正在运行,这会使行为复杂化,因此您可能需要在多处理器系统上运行很多次并统计分析结果。您还需要考虑线程启动时间和内存访问时间等因素,因为通过循环检查标志的每次迭代可能都会存在内存屏障。

但是,如果在足够多的不同循环迭代限制下进行足够多的重复,这应该会为您提供在一个时间片内可以迭代循环的次数。然后你可以在一个空载的系统上运行大量的迭代,得到每次迭代所花费的时间长度,然后计算每个时间片的挂钟时间。

【讨论】:

  • 在多处理器系统上,线程 2 /always/ 不会立即在可用处理器上运行吗?
  • @BrennanVincent 好点——如果没有其他线程在运行,是的。我已经调整了答案以适应这一点。显然测试设计可以进一步改进,但我认为我提供的基本想法是合理的。
【解决方案2】:

我不确定它有多准确,但这可能会奏效:

  1. 确保您的计算机处于空闲状态(或尽可能空闲)
  2. 产生 2N 个线程(其中 N 是计算机中的内核数)。所有这些线程都应设置为以彼此相同的优先级运行。
  3. 每个线程都应该运行一个无限循环,其中除了使用高分辨率计时器重复检索当前单调递增的挂钟时间(例如调用 std::chrono::steady_clock::now() 或类似)。
  4. 在循环的每次迭代中,每个线程都应检查“突然间隙”的结果时间值,即时钟时间从 (t) 跳到 (t+n 毫秒的位置,其中 n 大于通常的增量价值)。这些间隙很可能表明某个时间段线程从 CPU 中退出,以便另一个线程可以运行。
  5. 在某个时间点,计算所有这些间隙大小的平均值,这就是您对调度程序量子大小的估计。

请注意,这假设您的时钟分辨率大于调度程序的量程大小;如果不是(例如,如果您尝试使用分辨率为 10mS 的时钟来测量 5mS 的量子长度),那么测量量子长度将是困难的 AFAICT。

【讨论】:

  • 这可能很接近,但我认为它可能会在 std::chrono::steady_clock::now() 需要系统调用的系统中被丢弃(因此上下文切换和调度将发生在每个通过循环的时间,而不仅仅是在时间片到期之后)
  • 系统调用不会导致切换到另一个任务。那将是一个极其昂贵的系统设计。
  • 它可能需要从用户模式到内核模式(并返回)的上下文切换......stackoverflow.com/questions/9238326/…
  • @usr 它经常这样做——尤其是如果调用不能立即完成(想想read 等)
  • 时钟调用不会阻塞系统调用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-30
  • 1970-01-01
  • 2012-04-23
  • 1970-01-01
  • 2012-01-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多