在CUDA C 最佳实践指南中有一小节关于使用有符号和无符号整数。
在 C 语言标准中,无符号整数溢出语义是明确定义的,而有符号整数溢出会导致未定义的结果。因此,编译器使用有符号算术可以比使用无符号算术更积极地优化。这对于循环计数器特别值得注意:由于循环计数器的值通常为正数,因此将计数器声明为无符号可能很诱人。然而,为了更好的性能,它们应该被声明为有符号的。
例如,考虑以下代码:
对于 (i = 0; i < n; i++) { out[i] = in[offset + stride*i]; }在这里,子表达式
stride*i
可能会溢出一个 32 位整数,因此如果 i 被声明为无符号,溢出语义会阻止编译器使用一些原本可能已经应用的优化,例如强度降低。相反,如果 i 被声明为有符号,其中溢出语义未定义,编译器就有更多的余地来使用这些优化。
尤其是前两句话让我感到困惑。如果无符号值的语义定义良好并且有符号值可以产生未定义的结果,那么编译器如何为后者生成更好的代码?