【问题标题】:Raspberry Pi 2 NEON inline assembly instruction not workingRaspberry Pi 2 NEON 内联汇编指令不起作用
【发布时间】:2016-08-25 20:17:26
【问题描述】:

我试图让我的旧代码运行得更快,因为我发现 RPi 2 处理器支持 NEON 指令。所以我写了这段代码:

__asm__ __volatile__(
  "vld1.8 {%%d2, %%d3}, [%1];"
  "vld1.8 {%%d4, %%d5}, [%2];"
  "vaba.u8 %%q0, %%q1, %%q2;"
  "vst1.64 %%d0, [%0];"
  : "=r" (address_sad_intermediary)
  : "r" (address_big_pic), "r" (address_small_pic)
  :
);

然后在 C 中,主要的 sad 变量与 sad_intermediary 相加。

主要目标是计算绝对差的总和,因此我将 big_pic 中的 16 B 加载到 q1 寄存器中,将 small_pic 中的 16 B 加载到 q2 寄存器中,将 SAD 计算到 q0 中,然后将 q0 中的较低 8 B 加载到中介变量。问题是,由此产生的悲伤是零。

我使用 GCC 4.9.2-std=c99 -pthread -O3 -lm -Wall -march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard 选项。

您是否发现代码有任何问题?谢谢。

【问题讨论】:

    标签: gcc assembly arm raspberry-pi2 neon


    【解决方案1】:

    您永远不会将任何内容加载到 q0 中,因此 vaba 将绝对差异添加到未初始化的寄存器中。看起来你也没有声明你正在修改哪些寄存器。

    但我不知道这是否是您的问题的原因,因为我对内联汇编不太方便。不过,您可能不应该将内联汇编用于这样的事情。如果您使用intrinsics,那么编译器有更大的优化代码的能力。像这样的:

    #include <arm_neon.h>
    
    ...
    uint8x8_t s = vld1_u8(address_sad_intermediary);
    s = vaba_u8(s, vld1_u8(address_big_pic), vld1_u8(address_small_pic));
    vst1_u8(address_sad_intermediary, s);
    

    (请注意,此代码仅适用于八个字节,因为您的代码中只保存了八个字节)

    【讨论】:

    • 但是为什么我没有向 q0 加载任何内容?在这个document, p58 中,你可以看到,结果被保存到第一个寄存器中,在我的例子中是 q0。我不想使用内在函数,因为我读到它们的性能并不理想。
    • 内联汇编的性能可能会更差。内在性能在历史上一直很糟糕,但 gcc-6.1 现在可用,而且现代 Clang 都做得很合理。只要代码简单,它们就不会搞砸,它们会处理管道调度,而无需您考虑。
    • vaba 从 q0 读取并添加到 q1 和 q2 的绝对差异。 q0中必须要有东西才能执行操作,否则会得到一个无意义的结果。
    • 我尝试了内在函数,在查看了生成的 ASM 代码之后,看起来还不错,我就这样做了。主要问题是,我没有意识到 vaba 生成向量变量不是标量。
    猜你喜欢
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 2016-02-07
    • 2012-08-03
    • 2015-10-19
    • 2014-06-19
    • 2020-12-23
    • 1970-01-01
    相关资源
    最近更新 更多