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


107

在ISO / IEC 9899:2018(C18)中,在7.20.1.3中进行了规定:

7.20.1.3最快的最小宽度整数类型

1下列每个类型都指定一个整数类型,该类型通常最快(268)以与至少具有指定宽度的所有整数类型一起使用。

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

3需要以下类型:

int_fast8_tint_fast16_tint_fast32_tint_fast64_tuint_fast8_tuint_fast16_tuint_fast32_tuint_fast64_t

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


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


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

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

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


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


24
这里的关键是这些整数类型不是分离的,而且速度更快。它们只是该机器上用于该操作的最快的普通现有类型的别名。
mtraceur

3
编译器发出CPU操作操作码,以加载,存储,屏蔽和修改特定大小的内存位置和寄存器。这就是CPU所能看到的一切。操作系统与此无关。这就是编译器的全部工作,就像您自己指定了给定的typedef一样。(我假设允许编译器在内部对其进行不同的处理-如果可能的话,可能比用户typedef更有效率,只要行为上没有明显的区别即可。)
彼得-恢复莫妮卡

1
@ RobertS-ReinstateMonica确切地说,这些“别名”只是typedef陈述。因此,通常,它是在标准库级别完成的。当然,他们有什么C标准看跌期权没有真正的限制,typedef因此,例如,一个典型的实现是让-以int_fast32_t一个typedefint32位系统,但一个假设编译器能够例如实现一个__int_fast内在的类型,并承诺做一些花哨进行优化以根据具体情况为该类型的变量选择最快的机器类型,然后库可以typedef做到这一点。
mtraceur

1
@ RobertS-ReinstateMonica是的,是的。您将获得具有特定于体系结构的编译标志的性能最高的程序,这会使二进制文件的可移植性降低。
彼得-恢复莫妮卡

1
@罗伯茨ReinstateMonica这将是最有效的编译它的平台上,不一定
哈博

Answers:


152

想象一下一个仅执行64位算术运算的CPU。现在想象一下如何在这种CPU上实现无符号8位加法。为了获得正确的结果,它必然涉及多个操作。在这种CPU上,64位运算要比其他整数宽度上的运算更快。在这种情况下,所有Xint_fastY_t可能都是64位类型的别名。

如果CPU支持窄整数类型的快速运算,因此宽类型的速度不比窄类型的快,那么Xint_fastY_t它就不会是宽类型的别名,而不是表示所有Y位所需的别名。

出于好奇,我检查了某些体系结构上特定实现(GNU,Linux)的大小。在同一体系结构上的所有实现中,这些都不相同:

┌────╥───────────────────────────────────────────────────────────┐
 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  
└────╨────────┴─────┴───────┴─────┴────────┴──────┴────────┴─────┘

请注意,尽管对较大类型的操作可能更快,但此类类型在缓存中也会占用更多空间,因此使用它们不一定会产生更好的性能。此外,人们不能总是信任该实施方案一开始就做出了正确的选择。与往常一样,需要进行测量以获得最佳结果。


表格截图,适用于Android用户:

上表的屏幕截图

(Android没有单色字体的框画字符-ref


评论不作进一步讨论;此对话已转移至聊天
塞缪尔·柳

@RobertSsupportsMonicaCellio号“在所有体系结构中都不相同”也是正确的,但是从显示的数据中可以立即看出来,因此我认为没有必要陈述显而易见的内容。我只显示了一种实现的值,实际上其他实现会有不同的选择。例如在Windows上检查x86-64。与此处显示的尺寸相比,您会发现不同的尺寸。
eerorika

@RobertSsupportsMonicaCellio在我看来,这些评论与答案有关,在此处适当。如果他们认为有必要,我会让主持人移动它们。
eerorika

11

他们不是,至少是不可靠的。

快速类型只是常规类型的typedef,但是如何定义它们取决于实现。它们必须至少为请求的大小,但可以更大。

的确,在某些架构上,某些整数类型比其他整数类型具有更好的性能。例如,早期的ARM实现具有针对32位字和无符号字节的内存访问指令,但没有针对半字或有符号字节的指令。稍后添加了半字和带符号字节的指令,但它们的寻址选项仍然较不灵活,因为必须将它们插入备用编码空间。此外,ARM上的所有实际数据处理指令都对字起作用,因此在某些情况下,可能有必要在计算后屏蔽较小的值以给出正确的结果。

但是,即使需要更多指令来加载/存储/处理较小的值,也存在缓存压力的竞争问题。如果较小的值可以减少高速缓存未命中的次数,则可能仍会更好。

在许多常见平台上,这些类型的定义似乎尚未经过深思熟虑。特别是,现代的64位平台倾向于对32位整数提供良好的支持,但是“快速”类型在这些平台上通常不必要地为64位。

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

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


7

快速类型并不比所有其他整数类型都要快-实际上它们某些“普通”整数类型相同(它们只是该类型的别名)-哪种类型碰巧是保持值最快的类型至少有那么多位

它只是平台相关的每个快速类型的别名是哪种整数类型。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.