c++ 计算两个uint8_t变量之差的最快方法?

baubqpgj  于 2023-10-20  发布在  其他
关注(0)|答案(3)|浏览(197)

我必须计算两个uint8_t变量之间的差异,这是一个对效率非常敏感的代码区域。我必须找到最快的方法来执行这个计算。这是一个在Ubuntu上运行的C++程序。
我目前使用以下宏:

#define UINT8_T_DIFF(a, b) (static_cast<uint8_t>(((a > b) ? (a - b) : (b - a))))

这个宏产生了我需要的答案,但是我想知道是否有什么方法可以让这个计算更快?
请注意,我在宏中有static_cast,因为如果没有它,我会得到一个编译器消息:

conversion to 'uint8_t {aka unsigned char}' from 'int' may alter its value [-Werror=conversion]
bbuxkriu

bbuxkriu1#

一般来说,当您以最明显地传达意图的方式编写源代码时,编译器通常会生成最优化的程序集。这就是你想要做的:

uint8_t diff(uint8_t a, uint8_t b) {
    return abs(a - b);
}

你可以看到一些编译器如何在Godbolt上编译它。特别是GCC有一个有趣的序列,它不使用任何分支或CMOV指令:

movzx   eax, dil
movzx   esi, sil
sub     eax, esi
cdq
xor     eax, edx
sub     eax, edx
ret

它使用的技巧是,我们可以通过对寄存器进行符号扩展,将上半部分与下半部分进行异或,然后从下半部分中减去上半部分,来获取寄存器的绝对值。同时,Clang使用CMOV指令。我不知道哪一个在实践中更好。您可能需要根据您所针对的特定体系结构对它们进行基准测试。
由于这是一个常见的操作,我怀疑是否有任何汇编程序可以比这两种方法编写得更快。

aemubtdh

aemubtdh2#

如果你能负担得起时间-空间的权衡,它只需要64 K来保存一个结果的查找表。

const uint8_t abs_diff[256][256] = 
    {{0, 1, 2, 3, ..., 255},
     {1, 0, 1, 2, ..., 254},
     {2, 1, 0, 1, ..., 253},
     ...
     {255, 254, 253, ..., 0}};

#define UINT8_T_DIFF(a, b) (abs_diff[a][b])

也许缓存未命中将使这不值得。但是如果你在一个内部循环中使用这个宏,那么在这段时间内,它可能会把大部分内容保存在缓存中。

13z8s7eq

13z8s7eq3#

您可以在没有分支的情况下执行此操作,如下所示:

(uint8_t)((a > b) * (a - b) + (a <= b) * (b - a))

将每个值乘以相应的比较结果,结果会在您不希望的情况下减少为0。

相关问题