常见体系结构的最快整数类型

stdint.h头文件缺少int_fastest_tuint_fastest_t以与{,u}int_fastX_t类型对应。 对于整数类型的宽度无关紧要的情况,如何选择允许处理最大位数且性能损失最小的整数类型? 例如,如果使用朴素方法在缓冲区中搜索第一个设置位,则可以考虑这样的循环:

 // return the bit offset of the first 1 bit size_t find_first_bit_set(void const *const buf) { uint_fastest_t const *p = buf; // use the fastest type for comparison to zero for (; *p == 0; ++p); // inc p while no bits are set // return offset of first bit set return (p - buf) * sizeof(*p) * CHAR_BIT + ffsX(*p) - 1; } 

当然,使用char会导致比int更多的操作。 但是long long可能导致比在32位系统上使用int的开销更昂贵的操作,等等。

我目前的假设是主流架构,使用long是最安全的选择:它在32位系统上是32位,在64位系统上是64位。

int_fast8_t始终是正确实现中最快的整数类型。 永远不会有小于8位的整数类型(因为CHAR_BIT>=8是必需的),并且由于int_fast8_t是具有至少8位的最快整数类型,因此它是最快的整数类型,周期。

从理论上讲, int是最好的选择。 它应映射到CPU的本机寄存器大小,因此在您询问的意义上是“最佳”。

但是,您可能仍然发现int-64或int-128在某些CPU上比int-32更快,因为虽然它们大于寄存器大小,但它们将减少循环的迭代次数,因此可能通过最小化循环开销和/或利用DMA更快地加载/存储数据来提高效率。

(例如,在ARM-2处理器上,加载一个32位寄存器需要4个存储器周期,但是顺序加载2个周期只需要5个周期,顺序加载4个周期需要7个周期。上面建议的例程将被优化用作你可以释放许多寄存器(通常是8到10),因此每次循环迭代使用多个寄存器可以运行快3到4倍)

唯一可以确定的方法是编写几个例程,然后在特定的目标机器上对它们进行分析,以找出哪个能够产生最佳性能。

我不确定我是否真的理解这个问题,但为什么你不只是使用int ? 引用我的(错误的,即C ++的标准副本)标准,“简单的内容具有执行环境架构所建议的自然大小。”

但我认为如果你想为某个操作获得最佳整数类型,它将根据它的操作而不同。 试图找到大数据缓冲区中的第一个位,或者在整数序列中找到一个数字,或者移动它们,可能会有完全不同的最优类型。

编辑:

无论它值多少,我都做了一个小基准。 在我的特定系统(带有Linux的英特尔i7 920,gcc -O3)上,结果certificate,在这个特定的例子中,长整数(64位)比普通整数(32位)快得多。 我猜对了。

如果你想确定你有最快的实现,为什么不在你期望运行的系统上对每一个进行基准测试,而不是试图猜测?

答案是int本身。 至少在C ++中,标准的3.9.1 / 2表示:

Plain int具有执行环境体系结构所建议的自然大小

我希望C也是如此,尽管我没有任何标准文件。

我猜测类型size_t (对于无符号类型)和ptrdiff_t (对于有符号类型)通常对应于任何给定平台上非常有效的整数类型。

但是没有什么可以certificate这比检查生产的汇编程序和做基准测试。

在此处和其他回复中编辑 ,包括不同的评论:

size_tptrdiff_t是唯一在C99中是规范性的typedef,并且可以合理地假设它们与体系结构相关。

标准整数类型有5种不同的可能等级( charshortintlonglong long )。 所有的力都朝向具有宽度8,16,32,64的类型并且在不久的将来128.因此int将被卡在32位上。 它的定义与平台上的效率无关,只是受到宽度要求的限制。

由于问题不完整,因此无法回答这个问题。 作为类比,请考虑以下问题:

什么是最快的车辆

布加迪威龙 ? 当然很快,但从伦敦到纽约没有好处。

问题中缺少的是整数将用于的上下文。在上面的原始示例中,我怀疑如果数组很大且稀疏,你会看到8位,32位或64位值之间存在很大差异,因为你将会在cpu限制之前达到内存带宽限制。

重点是,架构没有定义各种整数类型的大小,编译器设计者就是这样做的。 对于给定的架构,设计师将仔细权衡每种类型的各种尺寸的优缺点,并选择最合适的。

我猜选64位系统上的32位int是因为大多数操作int用于32位就足够了。 由于内存带宽是一个限制因素,节省内存使用可能是最重要的因素。

对于所有现有的主流架构而言,目前最长的类型是环路吞吐量。

如果您正在使用gcc进行编译,我建议使用__builtin_ffs()来查找第一个位集:

内置函数:int __builtin_ffs(unsigned int x)返回一个加上x的最低有效1位的索引,或者如果x为零,则返回零。

这将被编译成(通常是单个)本机汇编指令。