Android 面试奇怪问题

2018-05-21 16:06:24 +08:00
 GLee9507
今天面试一家做车载的公司,被问到一个奇怪的问题。---如何优化、降低 CPU 使用率?
唉,没回答上来,我觉得 CPU 使用率是无法人为干预的,大家怎么看?
13199 次点击
所在节点    Android
58 条回复
iwtbauh
2018-05-22 14:50:54 +08:00
@enenaaa “进入 idle 后是等待中断, 不是正常运行状态。” 惊了,CPU 使用状态还有正常不正常的区别。同样是代码,你凭什么说 idle 里的代码就不是正常使用 CPU,非 idle 里的代码就是正常使用?莫非你以为编译后的内核中 idle 里的汇编机器指令和其他地方的汇编机器指令有区别?还是 CPU 能自己分辨出来代码是 idle ?等待中断不假,其实是内核用一个死循环等待中断的啊,和其他死循环编译出来的机器指令一样,对于 CPU 而言,它就是当“普通代码”一样执行 idle 里的代码而已。都是对 CPU 的“正常使用”

另外上文的却有容易混淆的地方,占用率指的是总占用率,我表达的意思是 CPU 在指定频率下(不管多低)都是 100%使用的。
enenaaa
2018-05-22 15:22:31 +08:00
@iwtbauh #41
idle 函数内执行 hlt 指令,cpu 进入暂停状态,等待下一次硬件中断。 这有啥奇怪的。难道你以为 cpu 会一直满负荷运转,主动检查各种中断嘛。
iwtbauh
2018-05-22 16:42:40 +08:00
@enenaaa 拜托,hlt 是 x86 汇编指令。对于 ARM 而言,据我所知并没有等价指令存在。(其实是否在 x86 上使用我感觉也是存疑的,毕竟这个指令很早就有了,wikipedia 上说 8086 就有了,如果确实可行没道理早期时代的 Linux 内核不用它用死循环,现在不清楚),Android 设备几乎没有用 x86 CPU 的吧

操作系统确实会去执行死循环,Linux 4.6 版本(现在 Android 似乎还在大批使用 3.x 内核?懒得找旧内核源码了),https://github.com/torvalds/linux/blob/v4.6/kernel/sched/idle.c,在 202 行执行 cpu_idle_loop 函数,这个函数就是一个死循环。

另外我什么时候说过“主动检查各种中断”了,,中断要是主动去检测还是中断么,当然是中断产生时 cpu_idle_loop 被打断,CPU 去执行中断处理函数了,如果需要调度自然会调度。

另外也不是满负荷运转,原因就是上面说的,基本上绝大部分设备上 CPU 频率可以调整。只是在当前频率下 CPU 并没有停止,还是一直在执行一个又一个指令。
tempdban
2018-05-22 18:19:32 +08:00
楼上不要吵,主动检查中断,可对可不对。
enenaaa
2018-05-22 18:22:56 +08:00
@iwtbauh arm 有 wfi, wfe 指令。
WFI suspends execution until one of the following events occurs:

an exception

an interrupt becomes pending, which would preempt if PRIMASK was clear

a Debug Entry request, regardless of whether debug is enabled.
iyaozhen
2018-05-22 18:36:08 +08:00
😂 难道楼主之前都不关心 CPU 使用率吗?我们都有 CPU、内存、电量、流量各种测试
tianzx
2018-05-22 18:56:46 +08:00
mark
saberpowermo
2018-05-22 19:00:12 +08:00
面 android 问这种问题, 居然在 v2 都不算奇怪问题了
mark 下 向楼上的大佬们学习了。
mashiro233
2018-05-22 19:45:35 +08:00
@iwtbauh
@enenaaa

首先 x86 我不熟,如果 HLT 的作用是将 cpu 进入低功耗模式等待中断将其恢复到正常模式的话。那么 ARM 对应的有 WFI(Wait For Interrupt)指令将 cpu 进入一个低功耗模式,直到一个中断发生。在多核的情况下还有个 WFE。

既然都贴出内核代码了,那我们不妨分析一下。首先看死循环,死循环再往下看(227 行)是不是有个 local_irq_disable()关闭中断,再之后,检查是进入 poll 轮寻(这里会重新开启中断)还是真正的 idle 模式,这里会调用
cpuidle_idle_call(),在这里(128 行),会检查是否需要让出 idle,如果需要则让出,不需则检查当前 cpu 是否支持 idle,如果支持则调用 default_idle_call(),这里就是会调用 arch_cpu_idle(),也就是 x86 的 HLT 指令,ARM 的 WFI 指令的地方。所以很显然,内核使用了大循环没有错,但是大循环绝对不是 iwtbauh 想象的那样工作,简单点就是。

```
while(1){

}

```
sampeng
2018-05-22 19:47:18 +08:00
很空泛的问题,随便答答,只要答到面试官 G 点就行了。。
mashiro233
2018-05-22 19:47:35 +08:00
手抖按到快捷键了发出来了…………
```
while(1){
是否需要调度?需要,让出: 不需要,idle 或者 poll。
}

```
mashiro233
2018-05-22 20:22:18 +08:00
@iwtbauh

针对你 39 楼的回复 `CPU 通电以后就会一直转` 这个也观点我认为也是错误的。

我们来看 Cortex-A72 的手册 2.4.1 Dynamic power management。
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0488f/Chunk1121736769.html

这里谈到了 WFI 和 WFE 的实现,其中都提到了。
ARMv8-A architecture that puts the core in a low-power state by disabling the clocks in the core while keeping the core powered up. This reduces the power drawn to the static leakage when the core is in WFI low-power state.

注意这个 disabling the clocks,进入 idle 之后时钟是被关闭的 cpu 本身不执行指令,但是能够被外部中断或者其他什么方式唤醒(比如 WFE 可以被其他核的 SEV 指令唤醒)。
mashiro233
2018-05-22 20:28:12 +08:00
说错了,是 Cortex-A57 ……
iwtbauh
2018-05-22 21:39:32 +08:00
@enenaaa
@mashiro233

的却是我的错,抱歉了。

另外,WFI 与 HLT 相近但并不完全一样。

顾名思义
HLT ( halt )是“保证” CPU 进入休眠模式
WFI ( wait for int )是等待中断,让 CPU 进入睡眠模式是平台的“实现细节”,而不是标准和保证,对于有的 arm 平台,这个指令相当于一直执行 NOP
mashiro233
2018-05-22 22:04:19 +08:00
@iwtbauh
感谢,学习了,x86 那块没确实没怎么系统研究过。😂
wizardforcel
2018-05-23 01:15:21 +08:00
降低某个程序的占用率还是能做到的,sleep 了解一下。
GLee9507
2018-05-23 08:28:14 +08:00
@wizardforcel Android 应用 sleep 的意义何在 -。-
fancyhan
2018-05-23 21:37:06 +08:00
这种开放问题,往往低水平的面试官只认同他自己知道的那些方面。我想未必是你的问题

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/456552

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX