42

在典型的手持/便携式嵌入式系统设备中,电池寿命是硬件、软件和设备可以支持的功能设计中的一个主要问题。从软件编程的角度来看,人们知道 MIPS、内存(数据和程序)优化代码。我知道 H/W 深度睡眠模式、待机模式,它们用于以较低的周期为硬件提供时钟,或者将时钟完全转到一些未使用的 circutis 以节省电力,但我正在从这个角度寻找一些想法:

在我的代码正在运行并且需要继续执行的情况下,鉴于此,我如何才能有效地编写代码“电源”以消耗最少的功率?

是否有任何特殊的编程结构、数据结构、控制结构,我应该查看它们以实现给定功能的最低功耗。

在代码结构设计时或在低级设计期间是否应牢记任何软件高级设计注意事项以使代码尽可能节能(最低功耗)?

4

17 回答 17

22
  • 就像1800 INFORMATION说的那样,避免轮询;订阅事件并等待它们发生
  • 仅在必要时更新窗口内容 - 让系统决定何时重绘它
  • 更新窗口内容时,确保您的代码尽可能少地重新创建无效区域
  • 使用快速代码,CPU 可以更快地返回深度睡眠模式,并且此类代码更有可能保留在 L1 缓存中
  • 一次对小数据进行操作,因此数据也保留在缓存中
  • 确保您的应用程序在后台时不会执行任何不必要的操作
  • 让您的软件不仅节能,而且具有电源意识 - 在使用电池时减少更新图形、禁用动画、减少硬盘抖动

并阅读其他一些指南。;)

最近,英特尔软件博客上开始出现一系列名为“为电源优化软件应用程序”的帖子。可能对 x86 开发人员有一些用处。

于 2008-09-15T05:42:28.320 回答
9

Zeroith,使用完全静态的机器,可以在空闲时停止。您无法击败零赫兹。

首先,切换到无滴答操作系统调度程序。每毫秒左右醒来都会浪费电力。如果不能,请考虑减慢调度程序中断。

其次,确保您的空闲线程是省电的,等待下一个中断指令。您可以在大多数小型设备拥有的那种监管不足的“用户空间”中执行此操作。

第三,如果您必须轮询或执行用户信心活动,例如更新 UI,请睡觉,执行此操作,然后重新睡觉。

不要相信那些你没有检查过“sleep and spin”类型代码的 GUI 框架。尤其是您可能很想用于#2 的事件计时器。

在读取时阻塞线程,而不是使用 select()/epoll()/WaitForMultipleObjects() 进行轮询。给线程调度器(和你的大脑)带来压力,但这些设备通常都可以。这最终会稍微改变您的高级设计;它变得更整洁!一个轮询你可能做的所有事情的主循环最终会在 CPU 上变得缓慢和浪费,但确实保证了性能。(保证慢)

缓存结果,懒惰地创造东西。用户希望设备运行缓慢,所以不要让他们失望。少跑步更好。尽可能少地逃跑。当您不再需要单独的线程时,它们可以被杀死。

尝试获得比您需要的更多的内存,然后您可以插入多个哈希表并节省搜索。如果内存是 DRAM,这是一个直接的权衡。

查看一个比您认为可能需要的实时系统。以后可以节省时间(原文如此)。他们也能更好地处理线程。

于 2008-09-15T05:37:13.370 回答
5

在我使用智能手机的工作中,我发现保持电池寿命的最佳方法是确保禁用程序在该特定点运行所需的一切。

例如,仅在需要时打开蓝牙,类似手机功能,在不需要时调低屏幕亮度,调低音量等。

这些函数使用的功能通常会远远超过您的代码使用的功能。

于 2008-09-15T07:23:54.393 回答
5

不要投票。使用事件和其他操作系统原语来等待可通知的事件。轮询可确保 CPU 保持活动状态并延长电池寿命。

于 2008-09-15T05:17:39.983 回答
3

避免轮询是一个很好的建议。

微处理器的功耗大致与其时钟频率和电源电压的平方成正比。如果您有可能通过软件调整这些,则可以节省一些电量。此外,关闭不需要的处理器部分(例如浮点单元)可能会有所帮助,但这在很大程度上取决于您的平台。在任何情况下,您都需要一种方法来测量处理器的实际功耗,以便找出哪些有效,哪些无效。就像速度优化一样,功率优化也需要仔细分析。

于 2009-04-21T19:37:35.293 回答
1

查看您的编译器生成的内容,特别是对于热门代码区域。

于 2008-09-15T10:02:31.813 回答
1

如果你有低优先级的间歇性操作,不要使用特定的定时器唤醒来处理它们,而是在处理其他事件时处理。

使用逻辑来避免愚蠢的场景,即您的应用可能会进入睡眠状态 10 毫秒,然后必须再次唤醒以等待下一个事件。对于提到的那种平台,两个事件是否同时处理并不重要。拥有自己的计时器和回调机制可能适合这种决策。权衡是代码复杂性和维护与可能的节能。

于 2008-09-15T10:29:07.413 回答
1

考虑尽可能少地使用网络接口。您可能希望收集信息并将其发送出去,而不是不断发送。

于 2008-09-15T05:29:12.687 回答
1

相当及时,今天在 Hackaday 上关于测量各种命令的功耗的文章: Hackaday: the-effect-of-code-on-power-consumption

除此之外:
- 中断是你的朋友
- 轮询 / wait() 不是你的朋友
- 尽可能少做
- 使你的代码尽可能小/高效
- 关闭尽可能多的模块、引脚、外围设备微型
- 尽可能慢地运行
- 如果微型有引脚驱动强度、压摆率等设置。检查并配置它们,默认值通常是全功率/最大速度。
- 回到上面的文章,回去测量功率,看看你是否可以通过改变东西来放弃它。

于 2012-06-14T15:31:07.913 回答
1

简而言之,尽可能少做。

于 2008-09-30T13:19:55.500 回答
1

好吧,如果您的代码可以完全在处理器缓存中执行,那么您将有更少的总线活动并节省电力。只要您的程序足够小以将代码+数据完全放入缓存中,您就可以“免费”获得这种好处。OTOH,如果您的程序太大,并且您可以将程序划分为或多或少独立于另一个的模块,则可以通过将其划分为单独的程序来节省一些电力。(我想也可以制作一个工具链,将相关的代码和数据包分散到缓存大小的块中......)

我想,从理论上讲,您可以通过减少指针取消引用的数量以及重构您的跳转以便首先进行最有可能的跳转来节省一些不必要的工作——但这​​对于程序员来说是不现实的。

Transmeta 的想法是让机器在运行中进行一些指令优化以节省电力......但这似乎没有足够的帮助......看看他们从哪里得到的。

于 2008-10-21T22:59:21.080 回答
1

将未使用的内存或闪存设置为 0xFF 而不是 0x00。对于 flash 和 eeprom 来说当然是这样,对于 s 或 d ram 不确定。对于舞会,存在反转,因此 0 存储为 1 并消耗更多能量,1 存储为零并消耗更少。这就是你在擦除一个块后读取 0xFFs 的原因。

于 2009-05-18T01:54:22.317 回答
0

不要投票,睡觉

尽可能避免使用芯片的耗电区域。例如,乘数很耗电,如果你可以移位和加法,你可以节省一些焦耳(只要你不做太多移位和加法,实际上乘数就是赢了!)

如果你真的很认真,我会得到一个功耗感知调试器,它可以将功耗与你的源代码相关联。 像这样

于 2012-06-15T12:47:27.433 回答
0

在 Linux 上,安装 powertop 以查看哪个软件唤醒 CPU 的频率。并遵循 powertop 站点链接的各种提示,其中一些可能也适用于非 Linux。

http://www.lesswatts.org/projects/powertop/

于 2009-12-10T20:41:24.900 回答
0

同样重要的事情是降低数学运算的精度,选择可用的最小数据集,如果您的开发环境可用,则打包数据和聚合操作。

knuth 书籍可以为您提供节省内存或 CPU 所需的特定算法的所有变体,或者降低精度以最小化舍入误差

此外,花一些时间检查所有嵌入式设备 api - 例如,大多数 symbian 手机可以通过专门的硬件进行音频编码

于 2008-09-30T13:39:19.790 回答
0

选择快速且具有小基本块和最少内存访问的高效算法。

了解处理器的缓存大小和功能单元。

不要访问内存。如果它们将您的工作代码或数据集扩展到可用缓存之外,请不要使用对象或垃圾收集或任何其他高级构造。如果您知道缓存大小和关联性,请在低功耗模式下布置您需要的整个工作数据集并将其全部放入 dcache(忘记一些将数据分散在单独对象或数据中的“正确”编码实践)结构,如果这会导致缓存垃圾)。与所有子程序相同。如有必要,将您的工作代码集全部放在一个模块中,以便在 icache 中将其全部条带化。如果处理器具有多级高速缓存,请尽量适应最低级别的指令或数据高速缓存。大学教师'

等等

于 2010-08-29T08:50:41.133 回答
0

尽快完成工作,然后进入空闲状态等待中断(或事件)发生。尝试用尽可能少的外部内存流量使代码用尽缓存。

于 2009-09-23T08:03:30.707 回答