高时钟中断速率和睡眠状态如何影响英特尔双核移动平台。
作者:Karthik Krishnan
Win32* 接口可以提供各种 API,用于以所需频率定期执行应用程序代码。它们以系统时钟的定期计时器滴答声为依据。系统时钟内置于 Microsoft Windows* 操作系统的“硬件抽象层”(HAL)。诸如多媒体播放等各种应用程序具有用于磁盘 I/O、解码、音频视频输出和 UI 的各种线程。通常它们使用基于计时器的中断来定期执行特定时间线前或特定时间线上的代码段(例如每 90 毫秒播放音频等)。下面是此情景下最常用的 API:
还有其他 API,例如 WaitableTimers()、QueuedTimers() 等;但所有这些 API 都使用系统时钟触发基于计时器的代码执行。
通常操作系统每 10-15.6 毫秒接收一次基于定期计时器的中断。我们不妨看一个示例,其中,应用程序使用 timeSetEvent() API 每隔 32 毫秒播放一段音频,操作系统每 15 毫秒接收一次中断。计时器每次滴答时,操作系统都将检查截止时间,在前两次计时器滴答过程中检查时(也就是 30 毫秒后),尚未到达应用程序播放截止时间。在第三次计时器滴答时(45 毫秒后),操作系统才发现已过播放截止时间,然后启动播放。此时的问题是,播放时间比应用程序计划时间延迟了 13 毫秒。这表明,计时器中断的时间粒度对定时启动的定期调用有一定影响。
Microsoft Windows Multimedia SDK 提供 timeBeginPeriod()API 来更改默认中断频率,在 Windows XP 上,最低可为 1 毫秒。下面的代码为一个示例:
修改中断速率的解决方法
void SetResolution(int delta) { TIMECAPS tc; UINT wTimerRes; if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) == TIMERR_NOERROR) { wTimerRes = min(max(tc.wPeriodMin, (UINT)delta), tc.wPeriodMax); timeBeginPeriod(wTimerRes); } }
增大中断速率的粒度可以更加精确地提高定期调用的时间线。例如,前面的示例中,由于每毫秒都触发中断,因此播放将在正确时间进行。但是,增加中断速 率粒度会大大增加功耗。而且并非所有多媒体内容都需要如此高的中断频率。以下将分析在当前和未来英特尔架构上,如此高的中断频率对睡眠状态和 CPU 功耗的影响。分析中包括若干多媒体应用程序实验,实验表明,对于特定媒体内容,使用默认中断速率仍可保持用户体验和整体性能。如欲了解有关中断速率的详细 讨论,请参考 http://www.microsoft.com/whdc/system/CEC/mm-timer.mspx * 。
诸如英特尔® 奔腾® M 处理器等英特尔移动架构中包括增强型 Intel SpeedStep® 技术,该技术能够根据系统需求优化能耗和性能。该项技术的运行方式是:提供 CPU 多点操作模式(称作P状态, P0 表示 CPU 最高频率 ),根据需求增加或降低处理器频率。如果具有可忽略的系统需求且 CPU 正在空闲时,它将提供多个处理器睡眠状态(称作C 状态,C 状态越高,例如 C4,则表明睡眠状态越深 ),这大大降低了整体功耗。
通过为中断提供服务的中断处理程序,每个中断都将 CPU 从深层睡眠状态中拉回至 C0。这将影响对功耗优化至关重要的睡眠状态保持。在多个 C 状态之间转换也将产生关联的能耗成本。如果中断速率很高,由于睡眠状态保持降低以及 C 状态转换关联的成本,将对因深层睡眠状态带来的节能产生负面影响。而英特尔® 平台提供平台特定的 C3 级状态,要求长期保持该状态(若干毫秒)以充分清偿转换成本。过大的中断速率会潜在抵消平台提供的深层睡眠状态的优势。
英特尔® 酷睿™ 双核(以前称作 Yonah)处理器上的 C 状态保持和 CPU 功率影响
作者采用简单的时钟滴答代码分析在运行 Microsoft WinXP*-SP2 的英特尔® 酷睿™ 双核 B0 处理器 (2.0GHz)、1GB 533 上,高中断速率对 C 状态保持以及平均 CPU 功率的影响。此白皮书中包含的所有功率数据均采用 CPU 的 NetDAQ* 配置估测。下面的代码(称作 MyTicker)将接受命令行参数,相应地设置中断速率,然后永远保持空闲:
MyTicker 代码 .
int _tmain(int argc, _TCHAR* argv[]) { if (argc != 2) return 1; int tick = (int)argv[argc]; TIMECAPS tc; UINT wTimerRes; HANDLE hThread; if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) { return -1; //error } wTimerRes = min(max(tc.wPeriodMin, tick), tc.wPeriodMax); timeBeginPeriod(wTimerRes); Sleep(INFINITE); return 0; //not reached! }
下面的图表针对 CPU 使用率、每秒中断数、C3/C4 状态保持及平均 CPU 能耗等方面对以 1 毫秒时间间隔触发中断的“MyTicker 1 毫秒”和设置默认中断时间间隔的空闲系统之间进行比较。紫色线表示具有默认中断(~15.6 毫秒)的“空闲”系统,蓝色线表示采用 1 毫秒中断频率的空闲系统。
图 1: 每秒中断数(MyTicker 1 毫秒对比“空闲”)
正如所预期的那样,每秒中断数从 ~100 增加到此处的 ~1000。
图 2: 睡眠状态保持(MyTicker 1 毫秒对比“空闲”)
此处 %C3 状态保持反映两种情景下的睡眠状态保持 (C3/C4)。随着每秒中断数从 ~100 增加到 ~1000,C3 状态保持从 ~97% 降低到 ~81%。睡眠状态保持的降低表示平均 CPU 能耗的增加。
图 3: CPU 平均能耗(MyTicker 1 毫秒对比“空闲”)
从上面可以清晰看出,中断增加时,CPU 平均能耗大大增加(~0.5W 至 ~1.05W)。预期未来平台上的能耗损失将远远高于此处,需要应用程序对中断速率非常敏感。
下面的部分使用一些实际多媒体应用程序按照上述步骤进行了分析。分析重点如下:
由于我们必须研究各种不同的应用程序,但又没有这些应用程序的源代码,所以我们设计实现了侦听和修改计时器 API 的侦听方法。该方法的工作方式类似 Microsoft Detours* 库。在高级别上,它将修改应用程序的二进制映像,从而为计时器 API 创建闸控函数。下面将显示使用 timeSetEvent() API 的方法:
图 4: API 侦听方法
第一步,将包含侦听功能的代码(MyIntercept 函数、Trampoline 函数)推入调用进程 (Iexplore.exe) 的地址空间。函数中需要侦听的前几个指令将被覆盖,并无条件跳转至 MyIntercept 函数。Trampoline 函数包含这些被覆盖的指令,然后无条件跳转至 timeSetEvent()。鉴于所有现有计时器调用都将通过 MyIntercept() 进行传递,我们可以通过修改 MyIntercept() 中的堆栈值来修改内置中断速率。
多媒体应用程序中的中断值
我们选择了一列常用多媒体应用程序来研究所使用的中断频率。下表表明,多数多媒体应用程序采用高中断速率(1 毫秒)。
应用 | TimerAPI | 中断频率 (毫秒) |
中断值 (毫秒) |
多媒体插件 1* | SetTimer() | 1 | 10-30 |
多媒体插件 2* | SetTimer() | 1 | 15-30 |
多媒体插件 3* | SetTimer() | 5 | 10 |
多媒体插件 4* | SetTimer() | 1 | 10 |
多媒体插件 5* | timeSetEvent() | 1 | 16 |
下表显示了采用高中断速率和低中断速率(1 毫秒对比 10 毫秒)的多媒体应用程序的最终结果。在所测试的英特尔® 酷睿™ 双核处理器上,每项的内容并不会大量耗用 CPU 功率。这为各种活动保留了大量扩展空间,同时也反映了使用播放功能并不会消耗大量资源。该表中包括 C0/C3 状态保持以及 CPU 平均功耗。%C3Res 包括所有 C3 状态保持以及深层睡眠状态。
每秒帧数和音频/视频同步可用来衡量用户体验。对这些因素的任何影响都将反映用户体验下降。通过我们已测试的内容,我们发现,当中断速率降低至 10 毫秒时,用户体验并未发生明显变化。
应用 | %C0 | %C3Res | 每秒中断次数 | 平均功率 | 内容 |
多媒体插件 1*: 1 毫秒 |
~25% | ~75% | ~1087 | 1.24 瓦 | 在线广告 |
多媒体插件 1*: 10 毫秒 |
~10% | ~90% | ~71 | 1.10 瓦 | |
多媒体插件 2*: 1 毫秒 |
~36% | ~64% | ~1110 | 1.84 瓦 | 640x248,电影花絮 |
多媒体插件 2*: 10 毫秒 |
~20% | ~80% | ~80 | 1.32 瓦 | |
多媒体插件 3*: 1 毫秒 |
~57% | ~43% | ~1035 | 2.788 瓦 | 1280x720,高清电影 |
多媒体插件 3*: 10 毫秒 |
~47% | ~53% | ~65 | 2.45 瓦 |
随着中断频率从 1 毫秒降低到 10 毫秒,C3 状态保持明显上升,C0 状态保持明显下降。其结果是节约了大量的 CPU 能耗,最大节约 0.5W,这取决于内容和应用程序。在未来的架构中,预期节能将大大增长。
持久中断
使用某些多媒体应用程序时发现的另外一个问题包括播放完成后也无法关闭的粘着中断。下面显示一个示例情景。
图 5. 持久中断的示例
不关闭中断将使 CPU 仍保持活动状态,即使空闲时也会降低深层睡眠保持。