Android应用的源码级能耗计算

也是从此前的网站搬运过来的,原文发布在2014年8月25日。

这是一篇南卡罗来纳大学发表在ISCA’13会议上的论文。计算机架构设计学术界开始认真对待ARM+Android的移动智能应用环境了,这也算是一步非常大的进展(过去主要收录的都是高性能桌面/服务器处理器设计的paper)。
这篇文章想要解决一个问题:嵌入式应用对功耗敏感,但是当前的技术无法提供足够细粒度的功耗数据,因此需要提出一种基于硬件的功耗测试方法,并结合程序分析以及统计建模,最终实现快速而精确的功耗信息获取。
点评:从立意以及研究对象上看这篇文章是偏向工程实践的,也就是说文章提出的工具主要针对实际的开发人员和芯片设计/研究人员。从其评测方法学上,对于性能建模也有借鉴意义,所以值得我们认真读一读。需要重点注意的是:文章中对Android多线程运行时环境的分析。

引言

移动应用的复杂度越来越高,其功耗开销也日益增长,但却少有针对功耗的评估方法。目前开发人员只能依赖经验完成对其apk的功耗预估,没有客观的指导。当然,现在也有一些通过监控应用的运行时行为特征,跟踪关键OS参数从而提供开发人员功耗估计数据的工具,但这些工具的分析粒度一般都是component或者method级的。而如果利用CPU time评估应用功耗开销,又会遇到DVFS以及多种硬件模块协同工作的不可知因素。如果用CA模型去分析,速度又太慢;用基于程序分析的评估方法有需要细致的细粒度软件profiling环境支持。这篇文章提出的工具可以提供源码级的功耗分析,在实现工具的过程中存在许多现实的障碍,比如功耗采样精度、线程切换和GC的影响等。所以需要结合基于硬件的测量、程序分析以及统计模型等3类技术。评估架构的基本设想是:

  • 首先,在测量功耗的同时,用path profiling获得应用执行的代码段,从而得到对应代码段的执行功耗;
  • 然后,利用统计信息辨识出高能耗事件(线程切换等),并通过鲁棒性较高的回归分析获得每行源码能耗;
  • 最后,提供一个可视化能耗数据后端给开发人员,使其可以清晰的看到每行代码对应的能耗值。

在上述框架的基础上,还需要引入经验模型,以获得框架增加的执行延时以及准确度。目前框架的整体误差率在10%以内。其中,统计模型与测量数据的match程度也到达了0.93(R2)。特别是,该框架能够精确的探测到高能耗事件的影响,比如GC。速度也比较快,3分钟以内就搞定。

背景与动机

主要讨论能耗测量与计算源码每行能耗消耗值的挑战,分为三类:硬件、运行时系统以及软件。这部分用开源的Google Authenticator项目做例子。该例子就是客户端向时间同步服务器发起同步请求的整个过程。

硬件限制

主要问题在于速度的不匹配上,CPU执行速度太快(GHz级别),而功耗采样速度太慢(kHz级别)。甚至有可能出现采样间隔内,子程序已经执行完成的情况。

运行时限制

Android系统的运行时包括支持应用运行的OS和Dalvik虚拟机。运行时存在如下几种可能影响apk能好的行为:线程切换、GC以及tail能耗。问题在于上述事件的持续时间、运行频率以及时序信息都不为apk所知。而如果直接profiling整个运行时,开销又太大。所以,需要找个办法,在apk层就能统计上述信息。
线程切换对源码级能耗计算的影响主要有如下几条:

  • 首先,任何针对某段时间的能耗测量都有可能包含某些与当前被测应用无关的线程,比如OS操作。因此这段时间的功耗采样数据都可能包含了非被测应用的指令。
  • 其次,线程切换自身的能耗开销也非常大,比如新线程的启动

Android系统还会在apk执行过程中周期性的进行GC操作。通常情况下,应用本身是不会管理GC的,GC一般是由OS负责的,因此可能在任意时刻、任意method执行时被触发。虽然Dalvik虚拟机可以log下GC发生的时间点,但其精度太差,只能做到ms级别。而GC的能耗开销又非常大,因此很容易导致框架精确性的问题。也就是说,有可能出现这样一种情况:明明只是一个简单的方法调用,却由于出现了GC操作,而导致巨大的能耗开销。
对于tail能耗而言,某些硬件很可能被OS按照一定的预期在原本应该idle的情况下激活。一般存在2种不同的呈现形式:

  • 某API访问了某硬件模块并返回。此时,即使后续一段时间没有新的API访问该硬件模块,系统也会保持其为激活模式,从而消耗能耗,比如对网络/无线通信模块的使用。
  • 2次对相同硬件模块的顺序访问间隔小于tail的时间。

对于上述两种情况,该能耗评估框架都必须能够准确的便是tail能耗的开销,并将其归结到访问硬件模块的那行源码上。

软件级挑战

源码级能耗计算必须获得关于apk执行的准确信息。但获得此类信息的过程通常都是昂贵且侵入式的(即使在basic block级别,开销也非常巨大)。此外,还需要获得API调用的准确信息。在执行过程中,应用会不断地调用各类库函数、API以访问硬件模块。此类调用的能耗开销相对较大,而某些API调用就可能不涉及硬件模块,因此能耗开销非常小。因此,有必要分清楚不同类型的API调用。

方案

从顶层看,该方法有两个步骤:运行时测量以及离线分析。其中运行时测量阶段的输入为“基于分析的应用(application under analysis,AUA)”以及一组测试人员系统获得能能耗测量use case。App Instrumenter使用一种高效的路径profiling技术,将probes引导插入到AUA,后者将负责获得时间戳信息以及路径转换信息(path traversal information)。这样,测试人员就可以在功耗测量平台上执行注入的AUA了。最终可以使得在功耗测量平台采样功耗数据的同时,能够记录路径信息。上述路径信息以及功耗采样数据可以作为离线分析阶段的输入。路径调整器(Path Adjuster)负责静态的分析路径,并将高功耗事件插入到功耗采样数据中。此后,分析器(Analyzer)则执行回归分析以计算每条源码的功耗开销,如下图所示。如果分析器发现缺少回归过程所需的数据点,则整个流程将回到运行时册里那个阶段,开发人员就可以重新执行应用,以捕获足够多的采样点数据。最终,注释器(Annotator)负责使用计算值,在源码显示位置创建图形化的功耗数据层。

7E22496C-C0CC-4D06-BEE6-8302748F8712-1024x352.jpg

运行时测量阶段

在运行时测量阶段,需要为AUA和功耗测量获得执行路径。因此,App注入器将插入probes到AUA中以记录相关信息。此后,完成注入的AUA开始执行,同时功耗测量平台则会捕获功耗采样数据。

AUA的注入过程

这一步主要是获得那条代码路径是当前执行的,同时还需要统计执行的频率、时间轴以及API调用情况。这篇论文引用了Ball和Larus的工作。具体来说,首先在AUA中为每个method创建CFG,并给每个CFG付一个标签。然后计算CFG的maximal spanning tree,并利用其引导minimal placement of instrumentation。本文扩展了B&L的方案以处理内嵌method调用,并发以及异常。probe的数据结构是:<thread_id, path_id, enter_time, exit_time>。
此外,App注入器还负责在特定API调用前后插入时间戳,其数据结构是:<method_id, enter_time, exit_time>。

注入AUA的执行

功耗测试平台是基于LEAP节点的,LEAP是一款基于ATOM N550处理器的硬件平台,运行Android 3.2系统。LEAP的所有部件(WiFi、GPS、存储器以及CPU)都是由ADC连接的,并以10kHZ的频率对电流进行采样。同时,LEAP还提供Android应用以触发同步信号的能力。这样,我们就可以消除时钟skew,从而将路径时间戳与采样数据同步了。

离线分析阶段

本阶段需要完成对采样数据和注入后得到的trace数据的分析,并将其映射到源码上。主要分为3个阶段:

  • 首先,路径调整器静态的检查CFG上每条路径,并根据特定API调用、tail能耗以及interleaving的线程,调整对应的能耗测量值;
  • 其次,分析器采用回归技术计算每行源码的能耗开销,并辨识出GC、线程切换出现点的路径;
  • 最后,注释器负责在源码上创建图形化表达形式。

路径能耗采样调整

计算每行源码的能耗值

能耗数据的可视化

评估

目标应用

实现

RQ1: 开销分析

RQ2: 测量精度

Advertisements

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s