问题 是否可以通过消除> =比较的需要,对无符号整数进行类型标记,从而使边界检查更快?


假设我的程序中有一个非常性能关键的循环,我需要检查一个点是否在一个矩形内,但我知道在编译时下限总是为0,如下所示: (x >= 0 && y >= 0 && x < width && y < height)

我可以通过类型将x和y类型化为无符号整数来消除前两个比较(例如,类似于 reinterpret_cast<>() 或者a union 在C ++中),因为符号位会保证任何负数都会变成一个 unsigned int 大到足以使边界检查失败?如果是这样,你将如何用C ++或其他语言实现它?这样做可以获得任何性能提升吗?


4172
2018-01-19 01:57


起源

可能是以下副本: stackoverflow.com/questions/2711522/... - Jeremy Friesner
使用 static_cast 转换整数类型。您还可以尝试比较程序集以查看编译器是否自动优化它。 - Neil Kirk
@JeremyFriesner我会说不 - 这个 问题似乎非常清楚 那 回答。 - Drew Dormann
是。 - Jerry Coffin


答案:


是的,当您测试有符号整数并且下限为零时,它是完全有效的优化。实际上,这是一种常见的优化,您的编译器几乎肯定会自动执行它;通过自己动手来模糊代码很可能是一个毫无意义的过早优化。

我刚刚在GCC 4.9上对此进行了测试,并通过检查生成的汇编代码确认它自动执行此优化 -O1 以上。我希望所有现代编译器也能这样做。


12
2018-01-19 02:11



好吧,如果放在适当命名的内联函数中,它不必混淆代码。 - Ben Voigt
没错,编译器非常聪明,可以发现这个优化机会并为您完成。 - Ross Smith
因此,编译器检测到您对一个整数执行大于零的测试,并在同一个整数上执行另一个小于测试(针对正值!),然后将其切换到无符号比较模式以节省少于1个时钟周期? - BWG
@Stuntddude这是一个全新的问题。对于其他人。 - Drew Dormann
如果编译器可以证明,这种优化只能自动实现 width 是非负面的吗? - zch


也许...

虽然在“纸上”这似乎只允许你进行两次比较而不是四次(这很好) - 你无法保证这将如何表现。如今,大多数CPU可以同时执行多个并行操作 - 您可以轻松地并行计算四个比较。

你的问题取决于编译器,CPU以及检查前后的代码 - 所以我的答案是“也许”。

避免将x,y转换为与当前大小不同的类型 - 即从int8_t转换为uint8_t很好,int8_t到uint32_t 威力 招致罚款。

根据您的意愿重写:

if ( ( static_cast<uint8_t>(x) < width ) &&
     ( static_cast<uint8_t>(y) < length ) )

测试性能增量非常困难,您需要使用RDTSC指令将代码用一些程序集包装,以捕获前后的时间。您可能还需要使用CPUID指令来刷新管道。

总之,对我来说你的优化 似乎 合理,但如果有的话,可能不会产生太大的影响。它会工作。


3
2018-01-19 02:10