ARM组装:绝对值功能:两行或三行更快?

Ken*_*n W 6 optimization performance assembly arm cortex-m3

在我的嵌入式系统类中,我们被要求将给定的C函数AbsVal重新编码到ARM Assembly中.我们被告知,我们能做的最好的是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;
}
Run Code Online (Sandbox Code Playgroud)

TA /教授的3线解决方案

ASR R1, R0, #31         ; R1 <- (x >= 0) ? 0 : -1
ADD R0, R0, R1          ; R0 <- R0 + R1
EOR R0, R0, R1          ; R0 <- R0 ^ R1
Run Code Online (Sandbox Code Playgroud)

我的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
Run Code Online (Sandbox Code Playgroud)

有几个地方我可以看到潜在的性能差异:

  1. 增加一个额外的算术右移调用
  2. 删除一个内存提取

那么,哪一个实际上更快?它取决于处理器或内存访问速度吗?

Nil*_*nck 5

这是另一个两个指令版本:

    cmp     r0, #0
    rsblt   r0, r0, #0
Run Code Online (Sandbox Code Playgroud)

哪个转换为简单的代码:

  if (r0 < 0)
  {
    r0 = 0-r0;
  }
Run Code Online (Sandbox Code Playgroud)

该代码应该非常快,即使在像Cortex-A8和A9这样的现代ARM-CPU内核上也是如此.


Dav*_*mas 5

访问 ARM.com 并获取Cortex-M3 数据表。第 3-4 页的 3.3.1 节包含指令时序。幸运的是,它们在 Cortex-M3 上非常简单。

从这些时间安排中我们可以看出,在完美的“无等待状态”系统中,您教授的示例需要 3 个周期:

ASR R1, R0, #31         ; 1 cycle
ADD R0, R0, R1          ; 1 cycle
EOR R0, R0, R1          ; 1 cycle
                        ; total: 3 cycles
Run Code Online (Sandbox Code Playgroud)

你的版本需要两个周期:

ADD R1, R0, R0, ASR #31 ; 1 cycle
EOR R0, R1, R0, ASR #31 ; 1 cycle
                        ; total: 2 cycles
Run Code Online (Sandbox Code Playgroud)

所以从理论上讲,你的速度更快。

您提到“删除一次内存获取”,但这是真的吗?各自的例程有多大?由于我们处理的是 Thumb-2,所以我们混合使用了 16 位和 32 位指令。让我们看看它们是如何组装的:

他们的版本(根据 UAL 语法进行调整):

    .syntax unified
    .text
    .thumb
abs:
    asrs r1, r0, #31
    adds r0, r0, r1
    eors r0, r0, r1
Run Code Online (Sandbox Code Playgroud)

组装到:

00000000        17c1    asrs    r1, r0, #31
00000002        1840    adds    r0, r0, r1
00000004        4048    eors    r0, r1
Run Code Online (Sandbox Code Playgroud)

即 3x2 = 6 字节。

您的版本(再次根据 UAL 语法进行调整):

    .syntax unified
    .text
    .thumb
abs:
    add.w r1, r0, r0, asr #31
    eor.w r0, r1, r0, asr #31
Run Code Online (Sandbox Code Playgroud)

组装到:

00000000    eb0071e0    add.w   r1, r0, r0, asr #31
00000004    ea8170e0    eor.w   r0, r1, r0, asr #31
Run Code Online (Sandbox Code Playgroud)

即 2x4 = 8 字节。

因此,您实际上增加了代码的大小,而不是删除内存获取。

但这会影响性能吗?我的建议是进行基准测试