论文分享:Unlocking Energy

Motivation

锁有以下特点:

  • 现有的并行系统的多线程同步大部分用锁来实现的。
  • 锁由于抽象的比较好,所以算法的实现并不会影响整体系统的正确性。
  • 有些锁的策略会比其他策略消耗更多的功耗。

而本文发现在改善锁的功耗的同时,往往会改善这个锁的吞吐率。

Intro

如何节省功耗:

Harware Techniques

  • clock gating:Deterministic Clock-Gating for Low-Power

    Clock gating is a popular technique used in many synchronous circuits for reducing dynamic power dissipation. Clock gating saves power by adding more logic to a circuit to prune the clock tree. Pruning the clock disables portions of the circuitry so that the flip-flops in them do not have to switch states. Switching states consumes power. When not being switched, the switching power consumption goes to zero, and only leakage currents are incurred.

    时钟门控(英语:Clock gating)是一种在同步时序逻辑电路的一种时间脉冲信号技术,可以降低芯片功耗。时钟门控通过在电路中增加额外的逻辑单元、优化时钟树结构来节省电能。

  • power gating:A Circuit Technique to Reduce Leakage in Deep-Submicron Cache Memories

    Power gating is a technique used in integrated circuit design to reduce power consumption, by shutting off the current to blocks of the circuit that are not in use. In addition to reducing stand-by or leakage power, power gating has the benefit of enabling Iddq testing.

  • voltage and frequency scaling

Software Techniques

  • approximation

  • consolidation

  • energy-efficient data structures

  • fast active-to-idle switching

  • power-aware schedulers

  • energy-oriented compilers

初期观察

本文观察了使用mutex锁与使用spinlock的功耗差别。

  • mutex在等待的时候会直接睡眠。
  • spinlock则是一直循环等待。

最终整个系统的功耗情况也不同。

论文分享:Unlocking Energy_第1张图片

可以看到看到mutex的功耗低,但能效低。spinlock在相同的情况有2倍的吞吐率。

所以选择一个适合的锁并不是那么简单的事情。

POLY Pareto Optimality in locks for energy efficiency

  • 忙等确定会导致一定的能源损耗,降低能效。

    这是由于一下原因导致的:

    • 在忙等里面,没有能源友好的暂停。在x86架构上pause指令往往会增加能源损耗…
    • 再一个monitor/mwait指令只有在内核态才能执行,而从用户态切换到内核态又有很大的overhead需要考虑。
    • 传统的DVFS策略,比较粗粒度,不容易使用。(反应比较慢,或许需要很久才能调整,而lock的变化又比较快)
  • 睡眠实际上可以节省很大一部分的能源损耗。

    在Xeon机器上,max power consumption为206w,而如果是idle状态只有55w的能源损耗。所以如果在sleep状态的时候可以节省比较多的能源损耗。

  • 但是睡眠往往又会降低能效。

    主要问题在于将睡眠的线程唤醒需要7000个cycles,这一个overhead非常大。

    传统的mutex锁很容易导致刚刚切换到睡眠状态的锁,又立刻将其唤醒,导致非常大的overhead。

    本文主要贡献的锁,就是在这一点上做文章,设计了一个MUTEXEE。(具体思路?)

  • 所以对于那些需要等待很久的锁,就将其切换到sleep状态。

    在竞争程度比较高的时候,可以选择一部分锁进入睡眠等待,一部分锁active等待。但是对于谁需要等待很久,这就是一个unfair的问题了。进入sleep可以降低当前锁的竞争程度,在功耗与吞吐率上均有好处。

Trade off

所以现在主要的trade off是吞吐率和锁等待延迟的trade off。

  • 睡眠vs忙等
  • 忙等中使用DVFS/monitor/mwait or not
  • low vs high fairness

Background

  • Mutex的实现就是先spin等待一段时间,然后再调用futex call去睡眠
  • 忙等类型的锁包括一系列的如:spinlock,mcs,clh,ticket,tas。
  • TPP是评价能耗的一个重要评判标准,Throughput Per Power
  • 而对于能耗来说,EPOEnergy Per Operation 也是一个量化标准。
  • TPP = 1/EPO

Target Platform

Estimating Max Power Consumption

论文分享:Unlocking Energy_第2张图片

  • Idele Power Consumption 均为上图为0个HT是的性能。两种策略均为55.5Watt。

  • 当 activating 一个 socket 里面的第一个core的时候会比开这个socket剩下的core消耗的能源更多,这是因为新开一个socket也需要同时将uncore的一些components开起来。

    新开一个sock分别在min和max中对应增加6.4与13.6。而开这个sock剩下的只需要2.3与5.6 Watss。

  • Memory的消耗功耗的变化范围没有Cores和Package变化大。

所以,总的来说,优化一个软件的能耗的机会在于

  • 用更少的核心,比如将thread放入sleep状态
  • 或者减少一个核心的运行频率来减少软件的功耗

Busy waiting

Busy waiting 到底会消耗多少Power

论文分享:Unlocking Energy_第3张图片

上图左边整体累计功耗。右边为CPI,为每一条指令平均需要的CPU周期数。

测试内容为等待一个永远也不会释放的锁。

  • sleeping的功耗可以非常低,这是由于等待中的线程会进入sleeping状态,不会消耗过多的CPU资源。
  • 但是一个比较有趣的现象是:本地的spinning会比全局的spinning消耗大约3%的能源
  • 这个可以从CPI图中得到解释:全局的spinning会在一个共享地址上进行原子操作,所以每条指令所需要的CPU周期数很多,很长一段时间后才会执行一次存储。而本地的spinning每个cycle都会执行一次L1 load,消耗的能源多一些(???差别会有很大吗)

所以,总的来说,sleeping会比spinning节省很多的能耗。

Reducing Busy waiting 能耗

作者做了以下尝试:

针对local spinning 降低其功耗

对于local spinning这种CPI过低的,需要想方设法增高其CPI。而其CPI过低主要是乱序执行后,会导致每个cycle都会有一次memory load。(其实从理论上,还要确保增高CPI后,多的那些cycle不能又做一些高功耗的事情,不过应该增高所用的方法,都不会有很好的功耗)

论文分享:Unlocking Energy_第4张图片

Pause可以将CPI提高到4.6,但是其不仅不能降低功耗,还会增加功耗。(真的吗???Pause的实现方法??)

而真正增高其CPI同时降低其功耗,需要从避免过多的预测执行下手。可以使用memory barrier来达到这个效果。

左图中灰色的线可以节省最多达7%的功耗。(还是和sleeping 差别有点大啊)

所以本文后面的pause都用memory barrier来替代。

DVFS相关探索

针对如何触发VF变化:需要在/sys/devices写一个context file,需要去看下文章 The TURBO Diaries: Application-controlled Frequency Scaling Explained

VF的特点:

  • VF-switch所需要的时间比较多,在Xeon中需要5300个Cycle(反应比较慢,粒度比较大,不灵活),所以在等待结束开始运行CS区域的时候,没法即时切回最高的VF。
  • 同一个物理核心上的频率都是相同的,没法针对一个hyper-threads进行单独调整(也可以总结为不灵活)。

论文分享:Unlocking Energy_第5张图片

当到30个线程的时候,才更多可能一个物理核心上的线程都在空等,此时才会降低功耗。在线程少的时候并不明显。

Monitor/mwait

MONITOR defines an address range used to monitor write-back stores. MWAIT is used to indicate that the software thread is waiting for a write-back store to the address range defined by the MONITOR instruction.

Intel manual

由于Monitor/mwait只能在kernel态使用,作者写了一个新的virtual device使得用户程序可以使用mwait等待一片内存区域。但是由于有用户态和内核态的切换,所以会有额外的开销。

(其实与sleeping相比,mwait更加高效吗?效率上提升有多少?单纯对比sleeping有多少优势?)

而使用Monitor/mwait主要有以下两个缺点:

  1. 由于Monitor/mwait只能在内核态使用,故使用文件操作有700个多余的周期(这个倒是可以暂时讨论时回避,如果该机制很好的话,能否以后在用户态提供类似的工具?),而最好的情况下(只唤醒一个线程)从睡眠中利用mwait来唤醒要1600个cycles。(相比较传统的sleeping要花费7000个cycles,而传统的local spinning只需要280个cycles)
  2. 当线程数量超过HT的数量时,由于mwait会阻塞硬件context,会导致livelock的问题。

Conclution

在Busy waiting中作文章效果都不是特别理想

现有的节省能耗的方法只有sleeping比较有效。

Futex sleep

Sleeping 代价

目前sleeping是使用futex system call 实现的。

论文分享:Unlocking Energy_第6张图片

横轴为从睡眠到唤醒之间的间隔,纵轴为从唤醒到线程开始运行的整体时间。可以从图中发现,wake up call调用会有2k左右的latency,而被叫醒的线程大概还要另外的4k左右的cycles才能真正跑起来。

  1. 当sleep到wake up的间隔时间比较少时,wake up的系统调用所消耗时间比较多。这是因为要sleep call共用一个kernel lock。
  2. 当间隔很多时,sleep的线程会进入更进一步的idle模式,因此唤醒时间就会非常长了。

另外,所有的futex call都使用的同一个kernel lock,所以当需要futex sleep的线程多的时候,还会在kernel中产生contention,导致效率进一步降低。

所以在效率上,futex sleep的效率十分不尽人意。

能否减少sleeping的代价

当临界区的时间小于futex-sleep的延迟时,整体性能并不会有改善。(刚睡眠就被唤醒,sleep miss)

尝试通过降低公平性来提高futex sleep的performance

通过只让少数(2个)线程忙等,其他去睡眠,来提高效率。同时为了一定的公平性,在忙等一个时间T后,忙等的需要找一个线程来替换自己。T越大,公平性越差。

论文分享:Unlocking Energy_第7张图片

上图的ss-X代表着spin & sleep 在不同的busy-waiting和futex的比例X下的结果

这个结果就很有趣了。当X增大时,wake up的频率变低,此时busy waiting竞争的线程数也非常的少。(这个比例为什么会到1000这么大?????)最终吞吐率变高同时能耗也非常低,唯有此时的公平性不好。

MUTEXEE

mutex遇到的问题:

  1. 可能CS区域的时间比sleep的系统调用时间短
  2. 在用户空间释放了锁之后,有可能唤醒的线程还没醒来,就有新的线程又获取了锁。公平性得不到保证。

Basic idea

论文分享:Unlocking Energy_第8张图片

MUTEXEE针对

  1. 更长的等待时间,且用mfence降低功耗
  2. 在解锁时先等待一段时间,确认短时间没有人busy waiting竞争锁后再去futex wake up。

MUTEXEE还设置了不同模式应对不同场景,主要区别是在睡眠之前等多久和释放锁之后等多久。而场景是通过唤醒的比例来定的。

论文分享:Unlocking Energy_第9张图片

测试的结果和猜测的一致,在临界区的较短时,MUTEXEE在效率以及功耗上要大幅好于MUTEX。

而对于公平性测试:

论文分享:Unlocking Energy_第10张图片

95%的还是可以的,但是99%就会有很多由于睡眠太久导致不公平。

为了避免少数等待太久,可以设置timeout,timeout会大幅影响性能。

Evaluate

论文分享:Unlocking Energy_第11张图片

evaluate的是不带TO的MUTEXEE。可以看到在性能和能效上都有不错的表现与可扩展性。但是在thread比较多时,MUTEXEE拥有远超MUTEX的Tail latency(因为没有TO)。mcs lock在40个核的时候出现性能与功耗下坠,这是由于硬件线程数量限制。(所以说MUTEXEE设置的机制可以使其在线程数量大于HT时仍然保持一定的性能?????好像是这样的,如果竞争多的话,很多的都被放去睡眠了,不过从功能上来说,MUTEX也可以达到这个效果吧……

文章的结论

在microbenchmark可以总结如下结论:

  1. 锁的吞吐率和功耗是相关的,可以同时增加。
  2. 在高竞争程度时,可以改善的空间比较大,但是性能上还是有一定的妥协。
  3. 在低竞争程度,能源功耗很大程度取决于吞吐率,因为本来就没多少能够通过睡眠来降低功耗的空间。

在现实世界测试集可以总结如下结论:

  1. 在数某些测试集中,sleep会导致吞吐率降低
  2. 有些系统中,MUTEX只是同步中的一小部分,最终对整体系统的影响不是太大。
  3. 当线程数量比核多时,睡眠是非常必要的。MUTEXEE在显著提吞吐率的同时降低了功耗。

你可能感兴趣的:(多核同步,阅读笔记,算法)