为什么快速整数类型比其他整数类型快?

ISO/IEC9899:2018(C18)在7.20.1.3下说明:

7.20.1.3 Fastest minimum-width integer types

1下列每一种类型都指定一个通常快于 268)的整数类型,以便在至少具有指定宽度的所有整数类型之间进行操作。

Typedef 名称 int_fastN_t指定宽度至少为 N 的最快有符号整数类型。Typedef 名称 uint_fastN_t指定宽度至少为 N 的最快无符号整数类型。

3 The following types are required:

int_fast8_t, int_fast16_t, int_fast32_t, int_fast64_t, uint_fast8_t, uint_fast16_t, uint_fast32_t, uint_fast64_t

此表单的所有其他类型都是可选的。


268) 不能保证指定类型在所有情况下都是最快的; 如果实现没有明确的理由选择一种类型而不是另一种,它只会选择一些满足有符号性和宽度要求的整数类型。


但是没有说明为什么这些“快速”整数类型更快。

  • 为什么这些快速整数类型比其他整数类型快?

我用 C + + 标记了这个问题,因为快速整数类型在 cstdint的头文件中的 C + + 17中也是可用的。不幸的是,在 ISO/IEC 14882:2017(C + + 17)中没有关于他们的解释的部分; 我已经在问题的正文中实现了该部分。


信息: 在 C 语言中,它们在 stdint.h的头文件中声明。

9412 次浏览

想象一下,一个 CPU 只执行64位的算术运算。现在想象一下如何在这样的 CPU 上实现一个无符号的8位附加值。为了得到正确的结果,需要进行多次操作。在这样的 CPU 上,64位操作比其他整数宽度的操作更快。在这种情况下,所有 Xint_fastY_t可能都是64位类型的别名。

如果 CPU 支持对窄整数类型的快速操作,因此较宽的类型不会比较窄的类型快,那么 Xint_fastY_t不会(不应该)是一个比表示所有 Y 位所必需的较宽类型的别名。

Out of curiosity, I checked the sizes on a particular implementation (GNU, Linux) on some architectures. These are not same across all implementations on same architecture:

┌────╥───────────────────────────────────────────────────────────┐
│ Y  ║   sizeof(Xint_fastY_t) * CHAR_BIT                         │
│    ╟────────┬─────┬───────┬─────┬────────┬──────┬────────┬─────┤
│    ║ x86-64 │ x86 │ ARM64 │ ARM │ MIPS64 │ MIPS │ MSP430 │ AVR │
╞════╬════════╪═════╪═══════╪═════╪════════╪══════╪════════╪═════╡
│ 8  ║ 8      │ 8   │ 8     │ 32  │ 8      │ 8    │ 16     │ 8   │
│ 16 ║ 64     │ 32  │ 64    │ 32  │ 64     │ 32   │ 16     │ 16  │
│ 32 ║ 64     │ 32  │ 64    │ 32  │ 64     │ 32   │ 32     │ 32  │
│ 64 ║ 64     │ 64  │ 64    │ 64  │ 64     │ 64   │ 64     │ 64  │
└────╨────────┴─────┴───────┴─────┴────────┴──────┴────────┴─────┘

Note that although operations on the larger types may be faster, such types also take more space in cache, and thus using them doesn't necessarily yield better performance. Furthermore, one cannot always trust that the implementation has made the right choice in the first place. As always, measuring is required for optimal results.


Android 用户的表格截图:

Screenshot of above table

(Android 没有使用单一字体 裁判的方块绘图字符)

他们不是,至少不可靠。

快速类型只是常规类型的 typedef,但是如何定义它们取决于实现。它们必须至少达到所要求的尺寸,但是它们可以更大。

It is true that on some architectures some integer types have better performance than others. For example, early 手臂 implementations had memory access instructions for 32-bit words and for unsigned bytes, but they did not have instructions for half-words or signed bytes. The half-word and signed-byte instructions were added later, but they still have less flexible addressing options, because they had to be shoehorned into the spare encoding space. Furthermore all the actual data processing instructions on ARM work on words, so in some cases it may be necessary to mask off smaller values after calculation to give correct results.

然而,还存在缓存压力的竞争问题,即使加载/存储/处理较小的值需要更多的指令。如果较小的值可以减少缓存丢失的次数,那么它仍然可以执行得更好。

许多通用平台上的类型定义似乎没有经过深思熟虑。特别是,现代的64位平台往往对32位整数有很好的支持,然而“快速”类型在这些平台上通常是不必要的64位。

此外,C 语言中的类型成为平台 ABI 的一部分。因此,即使平台供应商发现他们做了愚蠢的选择,以后也很难改变这些愚蠢的选择。

忽略“快速”类型。如果您真的关心整数性能,请使用所有可用的大小对代码进行基准测试。

快速类型并不比其他所有整数类型快——它们实际上是 一模一样到某种“正常”整数类型(它们只是该类型的别名)——无论哪种类型,只要能保持至少那么多位的值,都是最快的。

它只是平台相关的 哪个整数类型,每个快速类型都是。