【问题标题】:ARM Cortex A8 Benchmarks: can someone help me make sense of these numbers?ARM Cortex A8 基准测试:有人可以帮我理解这些数字吗?
【发布时间】:2011-11-08 17:04:52
【问题描述】:

我正致力于在 Android 上编写几个实时 DSP 算法,因此我决定直接在 Assembly 中对 ARM 进行编程,以尽可能优化所有内容并最大限度地简化数学运算。起初我得到的速度基准并没有多大意义,所以我开始阅读有关管道危险、双重问题能力等的内容。我仍然对我得到的一些数字感到困惑,所以我把它们贴在这里,希望有人能解释我为什么得到我得到的东西。特别是,我感兴趣的是为什么 NEON 需要不同的时间来对不同的数据类型运行计算,即使它声称在一个周期内执行每个操作。我的发现如下。

我正在使用一个非常简单的循环进行基准测试,并运行了 2,000,000 次迭代。这是我的功能:

hzrd_test:

    @use received argument an number of iterations in a loop
    mov r3 , r0

    @come up with some simple values
    mov r0, #1
    mov r1, #2

    @Initialize some NEON registers (Q0-Q11)
    vmov.32 d0, r0, r1
    vmov.32 d1, r0, r1
    vmov.32 d2, r0, r1

    ...

    vmov.32 d21, r0, r1
    vmov.32 d22, r0, r1
    vmov.32 d23, r0, r1

hzrd_loop:

    @do some math
    vadd.s32 q0, q0, q1
    vadd.s32 q1, q0, q1
    vadd.s32 q2, q0, q1
    vadd.s32 q3, q0, q1
    vadd.s32 q4, q0, q1
    vadd.s32 q5, q0, q1
    vadd.s32 q6, q0, q1
    vadd.s32 q7, q0, q1
    vadd.s32 q8, q0, q1
    vadd.s32 q9, q0,s q1
    vadd.s32 q10, q0, q1
    vadd.s32 q11, q0, q1

    @decrement loop counter, branch to loop again or return
    subs r3, r3, #1
    bne hzrd_loop

    @return
    mov r0, r3
    mov pc, lr

请注意指定为向量加法 (vadd) 和有符号 32 位整数 (s32) 的计算操作和数据类型。此操作在一定时间内完成(见下表)。根据this ARM Cortex-A8 document 和后续页面,NEON 中的几乎所有基本算术运算都应该在一个周期内完成,但这是我得到的:

vmul.f32 ~62ms vmul.u32 ~125ms vmul.s32 ~125ms vadd.f32 ~63ms vadd.u32 ~29ms vadd.s32 ~30ms

我通过简单地替换上述循环中所有内容的操作和数据类型来完成它们。 vadd.u32vadd.f32 快两倍,vmul.f32vmul.u32 快两倍有什么原因吗?

干杯! = )

【问题讨论】:

    标签: assembly arm benchmarking neon cortex-a8


    【解决方案1】:

    哇,你的结果非常准确:

    • 32 位整数 Q 乘法需要 4 个周期,而浮点数需要 2 个。
    • 32 位整数 Q 加法需要 1 个周期,而浮点型需要 2 个。

    不错的实验。

    也许你已经知道了,但在为 NEON 编码时要小心:

    • 不要在 NEON 工作繁重时使用 ARM 访问内存
    • 不要将 VFP 指令与 NEON 指令混用。 (共享的除外)
    • 不要访问 S 寄存器。
    • 不要从 NEON 寄存器转移到 ARM 的

    以上所有这些都会导致严重的打嗝。

    祝你好运!

    PS:我宁愿针对 A9 进行优化(周期时间略有不同),因为几乎所有新设备都带有 A9。 ARM 的 A9 时序图更具可读性。 :-)

    【讨论】:

    • 嗯,从您计算周期的方式来看,我的数据肯定是有道理的,但是您如何计算它们?我显然没有正确阅读文档,或者我们正在阅读不同的文档。
    • 我们实际上正在阅读相同的内容。你不必数。它就在“周期”下的图表中。 ARM 试图向我们展示太多,并成功地让我们感到困惑。查看 VMUL(integer, normal),从“Qd,Qm,Qn”开始,您会看到 1 到 4。这意味着它需要 4 个周期,在其中您可以看到执行周期的那个阶段发生了什么。 (预计 src 操作数在管道的哪个阶段,以及将 dst 操作数放入哪个阶段)
    • 我会这样说:4,Qd(5,3),Qn(4,2),Qm(3,1)。但它是 ARM。
    • 谢谢! = ) 我确实被文件弄糊涂了。
    【解决方案2】:

    我猜(因为我手头没有文档链接)您遇到了管道问题。我知道现在称为 VFPU 的 FPU - err 的管道长度与 CPU 用于执行循环的整数数学部分的管道长度不同。我看到第二个算术运算取决于第一个算术运算,这将停止任一管道并可能暴露您所看到的差异。

    另外,我相信乘法不是整数的 1 个周期指令,而是 2-5 个周期,具体取决于第二个值的 msb - 由于数字大小较小,这里的 2 个周期可以解释这种差异。为了验证这一点,从一个更大的乘数开始,看看它是否会随着更大的大小而变慢。

    我还会验证您的代码是否都适合 1 个缓存页面,以消除这种可能性。

    我还想看看上面关于双重执行的部分,因为当事情是交叉依赖时,那里也会发生各种管道停顿。

    【讨论】:

    • 我不能 100% 确定我是否正确阅读了 Cortex-A8 TRM (PDF) 的第 16.6 节,但我认为您对某些需要超过 1 个周期的说明是正确的。
    • Michael,指令缓存的一页有多大?到目前为止,我从未关注过这一点。很高兴知道。
    • 老实说,我不确定。它因实现而异 - 您必须查找特定设备的内容。不错的答案顺便说一句-您的答案解释了巨大的差异,而我的答案可能解释了较小的差异。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多