【问题标题】:Leading zeros calculation with intrinsic function具有内在函数的前导零计算
【发布时间】:2023-03-21 12:48:01
【问题描述】:

我正在尝试优化一些在嵌入式系统中工作的代码(FLAC 解码、Windows CE、ARM 926 MCU)。

default implementation 使用宏和查找表:

/* counts the # of zero MSBs in a word */
#define COUNT_ZERO_MSBS(word) ( \
 (word) <= 0xffff ? \
  ( (word) <= 0xff? byte_to_unary_table[word] + 24 : \
              byte_to_unary_table[(word) >> 8] + 16 ) : \
  ( (word) <= 0xffffff? byte_to_unary_table[word >> 16] + 8 : \
              byte_to_unary_table[(word) >> 24] ) \
)

static const unsigned char byte_to_unary_table[] = {
    8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

但是大多数 CPU 已经有专用指令,x86 上的 bsr 和 ARM 上的 clz (http://www.devmaster.net/articles/fixed-point-optimizations/),应该更有效。

在 Windows CE 上,我们有内部函数 _CountLeadingZeros,它应该只调用该值。但是它比宏慢 4 倍(以 1000 万次迭代测量)。

一个(应该)依赖于专用 ASM 指令的内部函数怎么可能慢 4 倍?

【问题讨论】:

    标签: arm bit-manipulation windows-ce intrinsics leading-zero


    【解决方案1】:

    检查拆卸。您确定编译器插入了指令吗?在备注部分有这样的文字:

    这个功能可以通过 调用运行时函数。

    我怀疑这就是你的情况。

    请注意,CLZ 指令仅在 ARMv5 及更高版本中可用。如果你想要 ARMv5 代码,你需要告诉编译器:

    /QRarch5 ARM5 Architecture
    /QRarch5T ARM5T Architecture
    

    (微软错误地使用“ARM5”而不是“ARMv5”)

    【讨论】:

    • 我会检查生成的代码。如果它真的是一个函数调用(而不是一个真正的内在函数),那么调用开销就可以解释为什么它这么慢。
    猜你喜欢
    • 2014-02-16
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 2020-10-28
    • 2019-07-21
    • 1970-01-01
    • 2019-08-12
    相关资源
    最近更新 更多