我应该在计算它们的位运算之前将我的整数截断为短路吗?

Ell*_*sky 5 c optimization performance x86 bit-manipulation

假设我有一个按位表达式f: int -> int,它只依赖于输入的两个最低字节.在一般情况下,这将是任何更快的计算(uint32)f'((uint16)x),在那里f': short -> short?或者转换涉及开销?假设f编译器过于复杂,无法自行解决这个问题.

Dai*_*Dai 8

较短的整数不会更快.一般来说,最快的类型与本机CPU字大小相同(因此在x86上使用32位整数,在AMD64/x64上使用64位整数).此外,对于某些操作,无符号整数比有符号整数更快(无符号与有符号整数的性能).

非字大小的整数比字大小的整数慢,因为处理器硬件在加载值时必须提供额外的填充,然后在存储时截断它; 也可能存在对齐问题(主要是当ISA允许非对齐值存储时 - 尽管字大小的整数也可以是非对齐的).

C的最新版本带有已知快速类型的typdef,其名称表示它们可以容纳的最大大小值,例如,int_fast8_t用于执行八位位组操作的最快类型(即使它在编译时甚至可能是128位类型) .

在您的问题中,您写道您只对16位值("输入的两个最低字节")执行操作,这意味着您将要使用uint_fast16_t.您将需要uint(for unsigned)因为任何整数的低16位(甚至signed整数等int)表示无符号值.

这些"快速整数"类型在stdint.h您的编译器附带的中定义,它可以直接包含在内#include <stdint.h>或通过间接包含#include <inttypes.h>.stdint.h还将包括limits.h.

更多信息可以在Wikibook on C上看到:

https://en.wikibooks.org/wiki/C_Programming/stdint.h

stdint.h是C99标准库第7.18节中引入的C标准库中的头文件,允许程序员通过提供一组typedef指定精确宽度整数类型的s 来编写更多可移植代码,并为每个类型定义最小和最大允许值.类型,使用宏

https://en.wikibooks.org/wiki/C_Programming/inttypes.h

Fast & fixed integer types | signed         | unsigned
---------------------------+----------------+---------------
 8 bit                     | int_fast8_t    | uint_fast8_t
16 bit                     | int_fast16_t   | uint_fast16_t
32 bit                     | int_fast32_t   | uint_fast32_t
64 bit                     | int_fast64_t   | uint_fast64_t
Run Code Online (Sandbox Code Playgroud)

C++

如您所见,这些定义仅由C99(不是C90,也不是C++ 03)强制要求,但C++ 11确实通过合并stdint.has <cstdint>(ie #include <cstdint>)来提高C90兼容性.

Microsoft Visual Studio的C++编译器和工具链(从Visual Studio 2017开始)不是一个符合C99编译器(这是设计),但是因为Visual C++ 2012及更高版本是一个符合标准的C++ 11编译器, 您可以<cstdint> 按预期使用 -只有Visual Studio 2010及更早版本(2008年,2005年等)缺少标题.

我注意到,如果你想编译C99代码,微软赞同使用Visual Studio工具链:https://blogs.msdn.microsoft.com/vcblog/2015/12/04/clang-with-microsoft-codegen-在-VS-2015-更新-1 /

Java的:

如果您正在使用Java,则严格定义大多数原始类型的大小(与C和C++相反,它们只需要能够存储某个最小范围内的值,因为它对C编译器有效使用128 -bit native integer for ushort):https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html - 我不相信有任何方法可以在纯Java中实现"快速"原生整数运算.

C#/ .NET:

在C#/.NET的故事类似于Java(如System.Byte,Int16等)严格定义,在C#中short,intlong关键字总是别名为Int16,Int32并且Int64不像C,其中他们的定义是供应商定义.

.NET确实具有平台大小的System.IntPtr类型,但除了加法和减法之外,你不能对它执行按位或算术运算(并且首先使用类型的开销将消除使用此类型的任何性能增益 - 尽管我注意IntPtr也不一定是字大小的:sizeof(void*)不必相等sizeof(uint_fast32_t)(因为指针必须足够大以存储每个可能的有效地址,但原生字大小可能更小,例如具有32位字的CPU大小,但使用64位地址总线,在这种情况下,sizeof(void*) == 8但是sizeof(uint_fast32_t) == 4- 反过来可能:64位字机只有32位地址总线(sizeof(void*) == 4, sizeof(uint_fast32_t) == 8).

Python,JavaScript,Ruby,PHP

这些是GitHub上的其他4种顶级语言 - 它们都共享一个弱类型设计,所以不要直接暴露任何"fast int"功能或打字系统(JavaScript甚至不能让你区分它floatint它的Number类型) ...但如果你想要表现,你就不会使用这些语言:)

进一步阅读:

在实践中:

在针对x86和x64的典型桌面软件开发中,您可以将许多事情视为理所当然,但在更具异国情调的环境中,事情往往会有所不同:考虑MIPS/NEC VR3400(类似于Nintendo 64中使用的VR3400i),它具有本机能力64位操作(即它具有本机64位字大小),但32位操作实际上比64位操作更快,并且它支持32位和40位地址空间 - 这意味着它已stdint.h存在于时间(这是1995年,早于C99)"最小","快速"和指针整数类型的定义与x86非常不同.


R..*_*R.. 5

根据经验,int除了存储大量数据(只需要较小的范围)之外,永远不要使用小于类型,而较大的类型会浪费大量内存或影响缓存一致性等.

在大多数cpu体系结构(包括x86)中,窄类型最多不会比32位或更大类型更快,最差更慢.