赞
踩
目录
四、Extending an existing simulation
官网教程:gem5: ARM Power Modelling
通过使用gem5中已记录的各种统计数据,可以在gem5模拟中对能量和功率使用(energy and power usage)进行建模和监控。这是通过使用MathExprPowerModel实现的,它是一种通过数学方程来建模功率使用的方法。本教程详细介绍了功耗建模所需的各个组件,并解释了如何将它们添加到现有的ARM模拟中。
本章借鉴了位于configs/example/arm目录中的fs_power.py配置脚本,并提供了扩展此脚本或其他脚本的说明。
请注意,只有在使用更详细的“timing” CPU时才能应用功耗模型。
关于功耗建模如何集成到gem5中以及它们与模拟器的其他部分如何交互的概述,可以在Sascha Bischoff在2017年ARM Research Summit上的演示中找到。
完整的fs_power.py配置脚本:
- import argparse
- import os
-
- import m5
- from m5.objects import MathExprPowerModel, PowerModel
-
- import fs_bigLITTLE as bL
-
-
- class CpuPowerOn(MathExprPowerModel):
- def __init__(self, cpu_path, **kwargs):
- super(CpuPowerOn, self).__init__(**kwargs)
- # 2A per IPC, 3pA per cache miss
- # and then convert to Watt
- self.dyn = (
- "voltage * (2 * {}.ipc + 3 * 0.000000001 * "
- "{}.dcache.overallMisses / simSeconds)".format(cpu_path, cpu_path)
- )
- self.st = "4 * temp"
-
-
- class CpuPowerOff(MathExprPowerModel):
- dyn = "0"
- st = "0"
-
-
- class CpuPowerModel(PowerModel):
- def __init__(self, cpu_path, **kwargs):
- super(CpuPowerModel, self).__init__(**kwargs)
- self.pm = [
- CpuPowerOn(cpu_path), # ON
- CpuPowerOff(), # CLK_GATED
- CpuPowerOff(), # SRAM_RETENTION
- CpuPowerOff(), # OFF
- ]
-
-
- class L2PowerOn(MathExprPowerModel):
- def __init__(self, l2_path, **kwargs):
- super(L2PowerOn, self).__init__(**kwargs)
- # Example to report l2 Cache overallAccesses
- # The estimated power is converted to Watt and will vary based
- # on the size of the cache
- self.dyn = f"{l2_path}.overallAccesses * 0.000018000"
- self.st = "(voltage * 3)/10"
-
-
- class L2PowerOff(MathExprPowerModel):
- dyn = "0"
- st = "0"
-
-
- class L2PowerModel(PowerModel):
- def __init__(self, l2_path, **kwargs):
- super(L2PowerModel, self).__init__(**kwargs)
- # Choose a power model for every power state
- self.pm = [
- L2PowerOn(l2_path), # ON
- L2PowerOff(), # CLK_GATED
- L2PowerOff(), # SRAM_RETENTION
- L2PowerOff(), # OFF
- ]
-
-
- def main():
- parser = argparse.ArgumentParser(
- description="Generic ARM big.LITTLE configuration with "
- "example power models"
- )
- bL.addOptions(parser)
- options = parser.parse_args()
-
- if options.cpu_type != "timing":
- m5.fatal("The power example script requires 'timing' CPUs.")
-
- root = bL.build(options)
-
- # Wire up some example power models to the CPUs
- for cpu in root.system.descendants():
- if not isinstance(cpu, m5.objects.BaseCPU):
- continue
-
- cpu.power_state.default_state = "ON"
- cpu.power_model = CpuPowerModel(cpu.path())
-
- # Example power model for the L2 Cache of the bigCluster
- for l2 in root.system.bigCluster.l2.descendants():
- if not isinstance(l2, m5.objects.Cache):
- continue
-
- l2.power_state.default_state = "ON"
- l2.power_model = L2PowerModel(l2.path())
-
- bL.instantiate(options)
-
- print("*" * 70)
- print(
- "WARNING: The power numbers generated by this script are "
- "examples. They are not representative of any particular "
- "implementation or process."
- )
- print("*" * 70)
-
- # Dumping stats periodically
- m5.stats.periodicStatDump(m5.ticks.fromSeconds(0.1e-3))
- bL.run()
-
-
- if __name__ == "__m5_main__":
- main()
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
功耗模型由两个函数组成,用于描述如何计算不同功耗状态下的功耗消耗。这些功耗状态包括以下几种(来自src/sim/PowerState.py):
每个状态(除了UNDEFINED)都分配了一个功耗模型,使用PowerModel类的pm字段。它是一个包含4个功耗模型的列表,分别对应以下顺序的状态:
需要注意的是,虽然有4个不同的条目,但这些条目不一定是不同的功耗模型。提供的fs_power.py文件在ON状态使用一个功耗模型,然后在其余状态使用相同的功耗模型。
gem5模拟器对功耗使用模拟了两种类型:
一个功耗模型必须包含用于模拟这两种功耗的方程(这个方程可以非常简单,比如,如果不需要或者与该功耗模型无关的静态功耗,可以将其设为st = "0")。
在fs_power.py中提供的功耗模型是继承自MathExprPowerModel类的。MathExprPowerModel是指定为包含用于计算系统功耗的数学表达式的字符串。它们通常包含了一些统计数据和自动变量,比如温度,例如:
- class CpuPowerOn(MathExprPowerModel):
- def __init__(self, cpu_path, **kwargs):
- super(CpuPowerOn, self).__init__(**kwargs)
- # 2A per IPC, 3pA per cache miss
- # and then convert to Watt
- self.dyn = "voltage * (2 * {}.ipc + 3 * 0.000000001 * " \
- "{}.dcache.overall_misses / sim_seconds)".format(cpu_path,
- cpu_path)
- self.st = "4 * temp"
上述的功耗模型来源于提供的fs_power.py文件。
可以看到自动变量(电压和温度【voltage
and temp
】)不需要路径,而组件特定的统计信息(CPU的每周期指令ipc)需要路径。在文件的主函数中,可以看到CPU对象有一个path()函数,返回组件在系统中的“路径”,例如system.bigCluster.cpus0。path函数由SimObject提供,因此可以被系统中任何扩展了SimObject的对象使用,例如稍后几行中的L2缓存对象也使用了它。
(注意将dcache.overall_misses除以sim_seconds以转换为瓦特。这是一个功耗模型,即能量随时间的变化。在使用这些术语时要小心,因为它们通常可以互换使用,但在功耗和能量模拟/建模方面,它们具有非常具体的含义。)
提供的fs_power.py脚本通过导入现有的fs_bigLITTLE.py脚本并修改其值来进行扩展。作为其中的一部分,使用了几个循环来迭代SimObjects的后代,以应用功耗模型。因此,为了扩展现有的仿真以支持功耗模型,可以定义一个辅助函数来帮助完成这个任务。
- def _apply_pm(simobj, power_model, so_class=None):
- for desc in simobj.descendants():
- if so_class is not None and not isinstance(desc, so_class):
- continue
-
- desc.power_state.default_state = "ON"
- desc.power_model = power_model(desc.path())
上述函数接受一个SimObject、一个Power Model和一个可选的类,SimObject的子孙必须实例化该类才能应用PM。如果没有指定类,则PM将应用于所有子孙。
无论是否决定使用辅助函数,现在需要定义一些Power Models。可以按照fs_power.py文件中的模式进行操作:
示例实现:
- class CpuPowerOn(MathExprPowerModel):
- def __init__(self, cpu_path, **kwargs):
- super(CpuPowerOn, self).__init__(**kwargs)
- self.dyn = "voltage * 2 * {}.ipc".format(cpu_path)
- self.st = "4 * temp"
-
-
- class CpuPowerClkGated(MathExprPowerModel):
- def __init__(self, cpu_path, **kwargs):
- super(CpuPowerOn, self).__init__(**kwargs)
- self.dyn = "voltage / sim_seconds"
- self.st = "4 * temp"
-
-
- class CpuPowerOff(MathExprPowerModel):
- dyn = "0"
- st = "0"
-
-
- class CpuPowerModel(PowerModel):
- def __init__(self, cpu_path, **kwargs):
- super(CpuPowerModel, self).__init__(**kwargs)
- self.pm = [
- CpuPowerOn(cpu_path), # ON
- CpuPowerClkGated(cpu_path), # CLK_GATED
- CpuPowerOff(), # SRAM_RETENTION
- CpuPowerOff(), # OFF
- ]
-
- [...]
-
- def addOptions(parser):
- [...]
- parser.add_argument("--power-models", action="store_true",
- help="Add power models to the simulated system. "
- "Requires using the 'timing' CPU."
- return parser
-
-
- def build(options):
- root = Root(full_system=True)
- [...]
- if options.power_models:
- if options.cpu_type != "timing":
- m5.fatal("The power models require the 'timing' CPUs.")
-
- _apply_pm(root.system.bigCluster.cpus, CpuPowerModel
- so_class=m5.objects.BaseCpu)
- _apply_pm(root.system.littleCluster.cpus, CpuPowerModel)
-
- return root
-
- [...]
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
默认情况下,gem5每模拟一秒钟就将模拟统计信息转储到stats.txt文件中。可以通过m5.stats.periodicStatDump函数进行控制,该函数接受以模拟时钟周期为单位的统计信息转储频率,而不是以秒为单位。同时,m5.ticks提供了一个fromSeconds函数,以便于使用。
下面是一个示例,展示了统计信息转储频率如何影响结果的分辨率,取自Sascha Bischoff的演示幻灯片第16页:
统计信息转储的频率直接影响基于stats.txt文件生成的图表的分辨率。然而,它也会影响输出文件的大小。每模拟一秒转储统计信息与每模拟一毫秒转储统计信息相比,会增加文件大小几百倍。因此,有意控制统计信息转储频率是合理的。
使用提供的fs_power.py脚本,可以按以下方式进行设置:
- [...]
-
- def addOptions(parser):
- [...]
- parser.add_argument("--stat-freq", type=float, default=1.0,
- help="Frequency (in seconds) to dump stats to the "
- "'stats.txt' file. Supports scientific notation, "
- "e.g. '1.0E-3' for milliseconds.")
- return parser
-
- [...]
-
- def main():
- [...]
- m5.stats.periodicStatDump(m5.ticks.fromSeconds(options.stat_freq))
- bL.run()
-
- [...]
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
可以使用以下方式指定统计信息转储频率:
--stat-freq <val>
在调用模拟时进行设置。
使用提供的fs_power.py时,gem5崩溃,并显示以下错误消息:致命错误:统计信息''(160)未通过regStats()函数正确初始化
使用提供的fs_power.py时,gem5崩溃,并显示以下错误消息:致命错误:无法评估功耗表达式:[...]
这是因为gem5的统计框架最近进行了重构。获取最新版本的gem5源代码并重新构建应该可以解决这个问题。如果不希望这样做,可以使用以下两组补丁:
可以通过按照各自链接中的下载说明来检出和应用这些补丁。
前阵子放假断更了一段时间(在家除了学习都是有意思的事情),现在逐步开始捡起学习状态。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。