MWAIT与HALT在效率方面的比较



我对MONITOR-MWAIT与HLT指令提出了疑问。两者都会停止处理器,并在各种外部触发器(中断等)上唤醒。

在我的实验中,当考虑时,HLT和MWAIT的功能几乎相同

  • 如果您是而不是操作系统调度程序,一个包含上述指令的简单循环,将很快被中断,并且由于MWAIT需要重新检查MONITOR和MWAIT之间的条件,有什么区别?(我想问的是,为什么不首先使用HLT,并节省分配跟踪区域的痛苦(如果不仔细配置,可以避免mon/mwait机制并将其变成NOP),因为如果你不是操作系统调度程序,你就不可能不迅速醒来,只需检查HLT循环中的值

(当然,MWAIT可能是更高的分辨率,我还没有测量分辨率,但它似乎被(我假设)中断等唤醒了)。。所以我看不出有多大的优势。

谢谢,任何以这种方式思考的想法都将不胜感激

性能;最重要的是CPU从"等待"状态出来所需的时间,无论何时发生它正在等待的事情(HLT的IRQ,或者MWAIT的IRQ或内存写入)。这会影响延迟,例如,在中断处理程序启动或任务切换实际发生之前需要多长时间。不同的CPU从等待状态出来所花费的时间不同,同一CPU上的HLT和MWAIT也可能略有不同。

功耗也是如此——不同CPU之间等待时消耗的功率可能会有很大差异(尤其是当你开始考虑超线程之类的事情时);并且在同一CPU上HLT与MWAIT的功耗也可能略有不同。

就使用而言,它们适用于不同的情况。HLT用于等待IRQ,而MWAIT用于等待发生内存写入。当然,如果你正在等待内存写入,那么你需要决定IRQ是否应该中断你的等待(例如,如果你只想等待内存写入的话,你可以先执行CLI,然后执行MWAIT)。

然而,对于多任务系统,它们大多只用于相同的事情——在CPU空闲的调度器中。在MONITOR/MWAIT引入之前,调度器会在等待工作时使用HLT(以稍微降低功耗)。这意味着,如果另一个CPU解锁了一个任务,它就不能直接将该任务放入调度器的队列,并且必须向HLTed CPU发送一个(相对昂贵的)"处理器间中断",以使其脱离HLT状态(否则,当有工作可以/应该做时,CPU将什么都不做)。使用MWAIT,这种"处理器间中断"(可能)是不必要的——您可以将MONITOR设置为监视对调度程序队列的写入,这样将任务放入队列的行为就足以导致等待的CPU停止等待。

也有一些研究将MONITOR/MWAIT用于自旋锁和同步(例如,等待争用锁释放)。这项研究的最终结果是,CPU从"等待"状态出来所需的时间太长,像这样使用MONITOR/MWAIT会导致太多的性能损失(除非存在设计缺陷,例如,在应该使用互斥锁的情况下使用旋转锁)。

我想不出任何其他原因(除了调度器和锁定/同步)来使用HLT或MWAIT。

HLT指令实现单个线程可用的最浅空闲功率状态(C-state),而MWAIT指令允许您请求所有可用的空闲功率状态以及子状态。

在硬件级别,执行HLT相当于执行状态提示为0的MWAIT。这使处理器处于C1状态,这是核心的时钟门控。如果您想进入更深的C状态以对核心进行电源门控并可能对包进行电源门控,则必须使用MWAIT。

对于各种电源状态,在省电和退出延迟之间总是有一个折衷方案。C状态越深,节电越多,但退出C状态所需的时间越长。您还应该注意,现代x86处理器将根据中断频率限制电源状态的深度(即,如果您每1 us接收一次中断事件,硬件将不会尝试进入具有2 us退出延迟的C状态)。

除了硬件禁止进入C状态外,一些C状态只能通过线程之间的协调进入。例如,在具有超线程的Intel x86处理器上,内核中的两个线程都必须请求功率门控C状态,以便在内核级别进行功率门控,同样,包中的所有内核都必须请求包级别的功率门控C态,以便在包级别进行功率选通。硬件通常遵守最浅的请求,因此如果1个线程请求C1,另一个线程请求C3,则处理器进入C1。

如果您不控制操作系统,那么这实际上是一个没有意义的问题(因为MWAIT仅在CPL0上可用)。如果您"拥有"操作系统,那么使用MWAIT而不是HLT几乎总是有意义的,因为在许多情况下,它可以节省更高的功率,并提供与HLT相同的空闲功率状态。

MONITOR/MWAIT应该可用于"旋转锁和同步(例如等待争用锁释放)">

然而,MONITOR/MWAIT(a)由于一个令人惊讶的愚蠢和恼人的原因,不得不被限制为仅由环0内核代码使用,而不是由用户代码使用,并且(b)被加载了微代码以进入低功耗睡眠状态。

一些公司已经更好地执行了类似或等效的指令,例如MIPS的LL/PAUSE大致相当于MONITOR/MWAIT。

最新更新