在手臂霓虹灯中有效地组合面具

Posted

技术标签:

【中文标题】在手臂霓虹灯中有效地组合面具【英文标题】:Efficiently combine masks in arm neon 【发布时间】:2018-04-21 04:57:13 【问题描述】:

作为我计算的一部分,我最终将 2 个掩码存储在 2 个 uint32x4_t 变量中。这些来自VCEQ。为了进一步处理,我想将它们组合成一个 q-reg 或 d-reg。手臂霓虹灯的首选方法是什么?

Simple solution:

uint16x8_t combineMasks(uint32x4_t mask_lo, uint32x4_t mask_hi)

    uint16x4_t lo = vmovn_u32(mask_lo);
    uint16x4_t hi = vmovn_u32(mask_hi);
    return vcombine_u16(lo, hi);

有没有更好的方法呢?在我的情况下,我稍后将 vand 结果掩码与 find position of a min/max element 的一些值。

【问题讨论】:

【参考方案1】:
// aarch32
vuzp.16     mask_lo, mask_hi        // you can use either one.

// aarch64
uzp1        result.8h, mask_lo.8h, mask_hi.8h

另一个关于intrinsux 无用的示例:如果您的目标包含aarch32vuzp1 将无法编译。换句话说,如果你想要获得最大的性能,无论如何你都必须在intrinsux 中编写这两个版本。

intrinsux 有什么意义?与简单粗暴的汇编编码相比,实在是太让人头疼了。

【讨论】:

vuzp.16 mask_lo, mask_hi 不会产生与 combineMasks 相同的结果,对吧? @Pavel 只返回低或高,结果和你的一样。 关于 asm/intrinsics:我在 10 年前做了一些 neon asm,甚至无法理解如何使用内在函数,特别是当时它们非常糟糕。不过,现在比以前好多了。我只是在尝试不同的东西来试验算法,而处理纯 asm 对我来说是没有意义的。对于最终结果,我肯定会考虑这样做,但此时我不需要这样做,尤其是内在函数对我来说效果很好。 您当前的测试结果非常具有欺骗性。您的例程并不那么复杂,它们只处理小块数据。平坦的开销将使装配版本的性能提升看起来越来越小。 12,960,000 个 4x4 复数浮点矩阵乘法在用汇编语言编写时几乎快两倍,给你一个想法。 我发布了主要处理最终/尾部结果的精简代码版本,我正在尝试使用它来查看是否可以改进以及在多大程度上可以改进。

以上是关于在手臂霓虹灯中有效地组合面具的主要内容,如果未能解决你的问题,请参考以下文章

手臂霓虹灯转置 4x4 uint32

如何在具有霓虹内在函数的多核处理器中有效地使用所有霓虹灯单元

在单臂霓虹灯寄存器中有效地将 8 位数字扩展到 12 位

如何在霓虹灯中进行交叉乘法?

Proteus仿真Arduino UNO +WS2812玩转霓虹灯

如何编程霓虹灯寄存器索引