我应该更喜欢在 C++ 代码中使用小类型的 int(int8 和 int16)吗?
我在嵌入式 Linux 的 C++/Qt 项目中工作,在该项目中,我们不断对抗"处理器的限制,特别是在更新用户界面中的图形时.由于这些限制(特别是我们前段时间情况更糟的情况),我总是尽可能地优化代码,并且优化成本最低.我正在做的其中一项优化是始终针对我正在处理的情况使用正确的整数值:qint8、qint16 和 qint32,具体取决于我需要的值有多大.
I'm working in a C++/Qt project for Embedded Linux where we are constantly "duelling" against the limitations of our processor specially when it comes to updating the graphs in the user interface. Thanks to those limitations (and specially our situation some time ago when things were even worse), I try to optimize the code always when I can and if the costs of optimization are minimum. One of such optimizations I was doing is to always use the correct integer value for the situation I'm handling: qint8, qint16 and qint32 depending on how big is the value I need.
但前段时间我在某处读到,与其尽可能尝试使用最小大小的整数,我应该总是更喜欢使用与处理器容量相关的整数值,也就是说,如果我的处理器是 32-面向位,那么即使不需要这么大的整数,我也应该始终使用 qint32.一开始我不明白为什么,但是 这个问题的答案建议这是因为处理器的性能在它必须使用其默认整数大小"时会更高.
But some time ago I read somewhere that instead of trying to use the minimal size of integer when possible, I should always prefer to use the integer value related to the capacity of my processor, that is, if my processor is 32-bit oriented, then I should prefer to use qint32 always even when such a big integer wasn't required. In a first moment I couldn't understand why, but the answer to this question suggest that is because the performance of the processor is greater when it has to work with its "default size of integer".
嗯,我不相信.首先,没有提供实际参考来证实这样的论点:我只是不明白为什么从 32 位内存空间写入和读取会比使用 32 位整数更慢(并且给出的解释不太容易理解, 顺便提一句).其次,当我需要将数据从一侧传输到另一侧时,例如在使用 Qt 的信号和插槽机制时,我的应用程序中有一些时刻.由于我将数据从一个点传输到另一个点,较小的数据不应该总是比较大的数据有所改进吗?我的意思是发送两个字符(不是通过引用)的信号不应该比发送两个 32 位整数更快地完成工作?
Well I'm not convinced. First of all no actual reference was provided confirming such a thesis: I just can't understand why writing and reading from a 32-bit memory space would be slower then doing it with 32 bit integer (and the explanation given wasn't much comprehensible, btw). Second there are some moments on my app when I need to transfer data from one side to the other such as when using Qt's signals and slots mechanism. Since I'm transferring data from one point to the other shouldn't smaller data always give an improvement over bigger data? I mean a signal sending two chars (not by reference) isn't supposed to do the work quicker then sending two 32 bit integers?
事实上,虽然处理器解释"建议使用您的处理器的特性,但其他情况则相反.例如,在处理数据库时,this 和 this 线程都表明存在优势(即使只是在一些情况下)使用较小版本的整数.
In fact, while the "processor explanation" suggests using the characteristics of your processor, other cases suggests the opposite. For example, when dealing with databases, this and this threads both suggests that there is an advantage (even if just in some cases) in using smaller versions of integer.
那么,毕竟,当上下文允许或不允许时,我应该更喜欢使用小类型的 int 吗?或者是否有一个案例列表,其中一种方法或另一种方法更有可能产生更好或最差的结果?(例如,我应该在使用数据库时使用 int8 和 int16,但在所有其他情况下我的处理器的默认类型)
So, after all, should I prefer to use small types of int when the context allows or not? Or is there a list of cases when one approach or the other is more likely to give better or worst results? (e.g. I should use int8 and int16 when using databases but the default type of my processor in all other situations)
最后一个问题:Qt 通常具有基于 int 的功能实现.在这种情况下,强制转换操作不会消除使用次要整数可能带来的任何改进吗?
And as a last question: Qt normally have int-based implemenations of its functions. In such cases, doesn't the cast operation annihilates any possible improvement that one could have by using minor integers?
推荐答案
这个问题实在是太笼统了,没有指定具体的CPU.因为一些 32 位 CPU 有大量用于处理较小类型的指令,有些则没有.一些 32 位 CPU 可以流畅地处理未对齐的访问,一些会因此产生较慢的代码,还有一些会在遇到它时停止并着火.
This question is really too broad without specifying a specific CPU. Because some 32 bit CPUs have plenty of instructions for handling smaller types, some don't. Some 32 bit CPUs handle misaligned access smoothly, some produce slower code because of it, and some halt and catch fire when they encounter it.
话虽如此,首先每个 C 和 C++ 程序中都存在标准整数提升的情况,它会将您使用的所有小整数类型隐式转换为 int
.
That being said, first of all there is the case of standard integer promotion present in every C and C++ program, which will implicitly convert all small integer types you use into int
.
编译器可以自由地使用标准中指定的整数提升,或者优化它,以产生最有效的代码,只要结果与非优化代码相同.
The compiler is free to use integer promotion as specified in the standard, or to optimize it away, whichever leads to the most effective code, as long as the results are the same as for non-optimized code.
如果程序员不了解各种隐式类型提升规则的工作原理,隐式提升可能会创建更有效的代码,但它也可能会产生带有意外类型和符号更改的微妙、灾难性的错误.可悲的是,很多想成为 C 和 C++ 程序员的人都不是.使用较小的整数类型时,您需要成为一个更有能力/清醒的程序员,而不是到处使用 32 位大小的变量.
Implicit promotion may create more effective code but it may also create subtle, disastrous bugs with unexpected type and signedness changes, if the programmer is not aware of how the various implicit type promotion rules work. Sadly, plenty of would-be C and C++ programmers are not. When using smaller integer types, you need to be a much more competent/awake programmer than if you just use 32 bit sized variables all over the place.
因此,如果您正在阅读本文但从未听说过整数提升规则或通常的算术转换/平衡,那么我会强烈建议您立即停止任何手动优化整数大小的尝试并继续阅读 改为使用那些隐式提升规则.
So if you are reading this but have never heard of the integer promotion rules or the usual arithmetic conversions/balancing, then I would strongly suggest that you immediately stop any attempt of manually optimizing integer sizes and go read up on those implicit promotion rules instead.
如果您了解所有隐式提升规则,则可以使用较小的整数类型进行手动优化.但是使用那些给编译器最大灵活性的.它们是:
If you are aware of all implicit promotion rules, then you can do manual optimization by using smaller integer types. But use the ones which gives the compiler most flexibility. Those are:
#include <stdint.h>
int_fast8_t
int_fast16_t
uint_fast8_t
uint_fast16_t
当使用这些类型时,编译器可以自由地将它们更改为更大的类型,如果这样会产生更快的代码.
When these types are used, the compiler is free to change them for a larger type if that would yield faster code.
上述变量仅依赖于整数提升/表达式优化之间的区别在于,对于快速类型,编译器不仅可以决定哪种类型最适合给定计算的 CPU 寄存器,还可以决定内存消耗和对齐方式变量已分配.
The difference between the above variables just relying on integer promotion/expression optimization, is that with the fast types the compiler can not only decide which type suits the CPU registers best for a given calculation, but also decide memory consumption and alignment when the variables are allocated.
相关文章