【发布时间】:2013-05-06 03:42:10
【问题描述】:
在我的嵌入式系统课程中,我们被要求将给定的 C 函数 AbsVal 重新编码为 ARM 程序集。 有人告诉我们,我们能做的最好的就是 3 行。我决心找到一个 2 线解决方案并最终做到了,但 我现在的问题是我实际上是降低了性能还是提高了性能。
C 代码:
unsigned long absval(signed long x){
unsigned long int signext;
signext = (x >= 0) ? 0 : -1; //This can be done with an ASR instruction
return (x + signet) ^ signext;
}
TA/教授的三线解决方案
ASR R1, R0, #31 ; R1 <- (x >= 0) ? 0 : -1
ADD R0, R0, R1 ; R0 <- R0 + R1
EOR R0, R0, R1 ; R0 <- R0 ^ R1
我的 2 线解决方案
ADD R1, R0, R0, ASR #31 ; R1 <- x + (x >= 0) ? 0 : -1
EOR R0, R1, R0, ASR #31 ; R0 <- R1 ^ (x >= 0) ? 0 : -1
有几个地方我可以看到潜在的性能差异:
- 增加了一个额外的算术右移调用
- 删除一个内存提取
那么,哪一个实际上更快?是否取决于处理器或内存访问速度?
【问题讨论】:
-
为什么不对其进行基准测试。这是了解性能差异的最可靠方法。
-
我完全会这样做,但我只是被介绍给这些概念。我可以请求教授帮助我进行基准测试,但更重要的是了解 为什么 它会更快或更慢是我的目标。不确定基准测试是否显示获取/执行阶段时间或寄存器/ALU 访问
-
这取决于实现。 A8 之前的内核可能会更快地运行您的代码,移位通常是免费的,除非您的移位值在寄存器中。 A8 和更新的内核有多个管道,可能允许一些并行执行,这可以使两者都在循环中,你可以试试pulsar.webshaker.net/ccc/result.php?lng=us。
-
@KenW 越来越多(至少对于 x86 等 CISC 芯片而言),基准测试是能够理解性能的唯一明智的方法。 (性能配置文件本质上是不确定的)。也就是说,我对 ARM 知之甚少;祝你好运。
-
反向条件减法是 IMO 的做法。由于 ARM 状态寄存器只是可选地更新,因此可以更早地计算符号位作为副作用。实际上 rsbne 可以被认为是计算 abs 的单指令方法。一个可以使用例如
movs r0, variable同时从内存中加载值并测试符号。
标签: performance optimization assembly arm cortex-m3