C 中的有符号与无符号运算
非常简单的问题:
我有一个程序对整数和长整型进行大量的数学计算。为了适应额外的位,我将 long long 设为无符号,因为我只处理正数,现在可以获得更多值。
奇怪的是,这给了我 15% 的性能提升,我证实这是因为简单地将所有 long long 都变成了无符号。
这可能吗?无符号数的数学运算真的更快吗?我记得读到过,没有区别,编译器会自动选择最快的方法,无论是有符号还是无符号。这 15% 的提升真的是因为使变量无符号吗?还是可能是我的代码中受到其他影响?
而且,如果确实是由于使变量无符号,我是否应该致力于使所有内容(甚至整数)都无符号,因为我从不需要负数,并且如果我可以保存它,每一秒都很重要。
Very simple question:
I have a program doing lots and lots of mathematical computations over ints and long longs. To fit in an extra bit, I made the long longs unsigned, since I only dealt with positive numbers, and could now get a few more values.
Oddly enough, this gave me a 15% performance boost, which I confirmed to be in simply making all the long long's unsigned.
Is this possible? Are mathematical operations really faster with unsigned numbers? I remember reading that there would be no difference, and the compiler automatically picks out the fastest way to go whether signed or unsigned. Is this 15% boost really from making the vars unsigned, or could it be something else affected in my code?
And, if it really is from making the vars unsigned, should I aim to make everything (even ints) unsigned, as I never need negative numbers, and every second is important if I can save it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在某些操作中,有符号整数更快,在其他操作中,无符号更快:
在 C 中,可以假设有符号整数操作不换行。例如,编译器将利用这种循环优化。可以类似地优化比较。 (如果您不希望出现这种情况,这也可能会导致微妙的错误)。
另一方面,无符号整数则没有这种假设。然而,对于某些操作来说,不必处理符号是一个很大的优势,例如:除法。无符号除以 2 的常数幂是一个简单的移位,但是(取决于您的舍入规则)负数有条件减 1。
就我个人而言,我习惯只使用无符号整数,除非我确实有一个需要签名的值。与其说是为了性能,不如说是为了正确性。
您可能会看到效果被 long long 放大,(我猜)在您的情况下是 64 位。 CPU 通常没有单独的指令来处理这些类型(在 32 位模式下),因此有符号操作的稍微增加的复杂性将更加明显。
In some operations, signed integers are faster, in others, unsigned are faster:
In C, signed integer operations can be assumed not to wrap. The compiler will take advantage of this in loop optimization, for example. Comparisons can be optimized away similarly. (This can also lead to subtle bugs if you don't expect this).
On the other hand, unsigned integers do not have this assumption. However, not having to deal with a sign is a big advantage for some operations, for example: division. Unsigned division by a constant power of two is a simple shift, but (depending on your rounding rules) there's a conditional off-by-1 for negative numbers.
Personally, I make a habit of only using unsigned integers unless I really, really do have a value which needs to be signed. It's not so much for performance as correctness.
You may see the effect magnified with long long, which (I'm guessing) is 64 bits in your case. The CPU usually doesn't have single instructions do deal with these types (in 32 bit mode), so the slight added complexity for signed operations will be more noticeable.
在 32 位处理器上,模拟 64 位整数运算;使用
unsigned
而不是signed
意味着仿真库不必做额外的工作来传播进位位等。On a 32-bit processor, 64-bit integer operations are emulated; using
unsigned
instead ofsigned
means the emulation library doesn't have to do extra work to propagate carry bits etc.在三种情况下,编译器会关心变量是有符号还是无符号:
在某些机器上,将有符号变量转换为更长的类型需要额外的代码;在其他机器上,转换可以作为“加载”或“移动”指令的一部分来执行。
某些机器(主要是小型嵌入式微控制器)需要比无符号与无符号比较更多的指令来执行有符号与有符号比较,但大多数机器都具有可用的有符号和无符号比较指令的完整数组。
当无符号类型发生溢出时,编译器可能必须添加代码以确保定义的行为实际发生。有符号类型不需要这样的代码,因为在没有这样的代码的情况下可能发生的任何事情都是标准允许的。
There are three cases where a compiler cares whether a variable is signed or unsigned:
On some machines, conversion of signed variables to longer types requires extra code; on other machines, a conversion may be performed as part of a 'load' or 'move' instruction.
Some machines (mainly small embedded microcontrollers) require more instructions to perform a signed-versus-signed comparison than unsigned-versus-unsigned, but most machines have a full array of both signed and unsigned compare instructions available.
When overflows occur with unsigned types, the compiler may have to add code to ensure that the defined behavior actually occurs. No such code is required for signed types, because anything that might happen in the absence of such code would be permitted by the standard.
编译器不会选择它是未签名还是已签名。但是,是的,从理论上讲,
unsigned with unsigned
比signed withsigned
更快。如果你真的想放慢速度,你可以选择signed with unsigned
。更糟糕的是:浮点数为整数
。当然,这取决于处理器。
The compiler doesn't pick if it's going to be unsigned or signed. But, yes, in theory,
unsigned with unsigned
is faster thansigned with signed
. If you really want to slow things down, you'll go withsigned with unsigned
. And even worse:floats with integers
.It depends on the processor, of course.