为什么无符号类型在arm cpu中效率更高?
我正在阅读手臂手册并提出这个建议,但没有提到原因。
为什么无符号类型更快?
I'm reading an arm manual and come to this suggestion, but the reason is not mentioned.
Why unsigned types are faster?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在 ARMv4 之前,ARM 没有对加载半字和有符号字节的本机支持。要加载带符号的字节,您必须
LDRB
然后对值进行符号扩展(LSL
向上,然后ASR
向下)。这很痛苦,所以char
默认情况下是unsigned
。在 ARMv4 中添加了指令来处理半字和有符号值。这些新指令必须被压缩到可用的指令空间中。可用空间的限制意味着它们无法像原始指令一样灵活,原始指令能够在加载值时进行各种地址计算。
因此,例如,您可能会发现
LDRSB
无法将从内存中获取的数据与地址计算结合起来,而LDRB
可以。这可能会耗费周期。有时我们可以修改短
重代码以对ints
进行操作来避免这种情况。我的网站上有更多信息:http://www.davespace.co。 uk/arm/efficient-c-for-arm/memaccess.html
Prior to ARMv4, ARM had no native support for loading halfwords and signed bytes. To load a signed byte you had to
LDRB
then sign extend the value (LSL
it up thenASR
it back down). This is painful sochar
isunsigned
by default.In ARMv4 instructions were added to handle halfwords and signed values. These new instructions had to be squeezed into the available instruction space. Limits on the space available meant that they could not be made as flexible as the original instructions, which are able to do various address computations when loading the value.
So you may find that
LDRSB
, for example, is unable to combine a fetch from memory with an address computation whereasLDRB
could. This can cost cycles. Sometimes we can reworkshort
-heavy code to operate on pairs ofints
to avoid this.There's more info on my site here: http://www.davespace.co.uk/arm/efficient-c-for-arm/memaccess.html
我认为这只是ARM CPU的指令集针对无符号进行了优化。对于无符号类型,某些操作可以使用一条指令完成,但如果是有符号类型,则需要多条指令。这就是为什么我认为如果在大多数(所有?)C 和 C++ 编译器中为 ARM 进行编译,它默认为 unsigned char 而不是更常见的signed char。
I think it's just that the instruction set for ARM CPUs is optimized for unsigned. Some operations can be done with one instruction for unsigned types but will need multiple instructions if it's signed. That's why I think if compiling for ARM in most (all?) C and C++ compilers it defaults to unsigned char rather than the more usual signed char.
我能想到的无符号类型的唯一优点是除法和取模实现可能会稍微快一些,并且您可以进行诸如
if (unsigned_value < limit)
而不是if (signed_value > ;= 0 && 签名值 < 限制)
。我怀疑你的手册可能已经过时了。今天使用的任何 ARM 都将具有 v4 或更高版本的指令集,并且我非常确定没有任何指令会根据符号而更快或更慢。
在较旧的 ARM 上,我相信有符号乘法可能会更慢;我认为提前终止只查找最高位中的所有零,而不是所有零,因此涉及负数的乘法总是花费最长时间。尽管这取决于值,而不取决于类型是有符号还是无符号。至少在 ARMv4 及更高版本上,提前终止适用于负值。
另外,我认为非常早期的 ARM 无法加载单个字节,只能加载一个字。因此,您需要两条指令来加载无符号字节,需要三条指令来加载有符号字节:
与
(目前)
ldrb r0, [r1]
或ldrsb r0, [r1]
进行单字节加载。在现代处理器上,使用无符号类型不太可能对性能产生可测量的影响。使用最有意义的类型,然后在确定任何性能瓶颈后详细查看代码。
The only advantages of unsigned types I can think of are that division and modulo implementations may be slightly faster, and you can do tests like
if (unsigned_value < limit)
rather thanif (signed_value >= 0 && signed_value < limit)
.I suspect your manual may be out of date. Any ARM in use today will have v4 or later of the instruction set, and I'm pretty sure that no instructions are faster or slower depending on signedness.
On older ARMs, I believe that signed multiplication could be slower; I think that early termination only looked for all zeros in the top bits, not all ones, so multiplications involving negative numbers would always take the maximum time. Although this depended on the value, not on whether the type was signed or unsigned. On at least ARMv4 and later, early termination works for negative values.
Also, I think very early ARMs couldn't load a single byte, only a word. So you'd need two instructions to load an unsigned byte, and three to load a signed one:
versus
versus (these days)
ldrb r0, [r1]
orldrsb r0, [r1]
to do a single-byte load.On a modern processor, it's very unlikely that using unsigned types will have a measurable impact on performance. Use whichever type makes most sense, then look at the code in detail once you've identified any performance bottlenecks.