确定基本算术计算的最快无符号整数类型

时间:2017-06-06 08:42:30

标签: c

我正在编写一些用于计算任意大的无符号整数的代码。这只是为了娱乐和训练,否则我会使用 libgmp 。我的表示使用无符号整数数组,并选择“基本类型”,我使用typedef:

#include <limits.h>
#include <stdint.h>

typedef unsigned int hugeint_Uint;

typedef struct hugeint hugeint;

#define HUGEINT_ELEMENT_BITS (CHAR_BIT * sizeof(hugeint_Uint))
#define HUGEINT_INITIAL_ELEMENTS (256 / HUGEINT_ELEMENT_BITS)

struct hugeint
{
    size_t s;         // <- maximum number of elements
    size_t n;         // <- number of significant elements
    hugeint_Uint e[]; // <- elements of the number starting with least significant
};

代码工作正常,所以我只在这里显示与我的问题相关的部分。

我想选择比unsigned int更好的“基本类型”,因此目标系统上的计算速度最快(例如,针对x86_64时为64位类型,针对i686时为32位类型,为8位在定位avr_attiny时输入,...)

uint_fast8_t应该做我想做的事。但是我发现它没有,例如,这里是MinGW stdint.h的相关部分:

/*  7.18.1.3  Fastest minimum-width integer types
 *  Not actually guaranteed to be fastest for all purposes
 *  Here we use the exact-width types for 8 and 16-bit ints.
 */
typedef signed char int_fast8_t;
typedef unsigned char uint_fast8_t;

评论很有意思:为什么unsigned char会比win32上的unsigned int更快?好吧,重要的是:uint_fast8_t不会做我想做的事。

有没有一些好的,可移植的方法来找到最快的无符号整数类型?

2 个答案:

答案 0 :(得分:2)

不是那么黑与白;处理器可能具有用于某些操作的不同/专用寄存器,如x86_64上的AVX寄存器,可以在半尺寸寄存器上最有效地操作或者根本没有寄存器。因此,“最快整数类型”的选择在很大程度上取决于您需要执行的实际计算。

话虽如此,C99定义uintmax_t表示最大宽度无符号整数类型,但要注意,它可能只是64位,因为编译器能够模拟 64比特数学。

如果您定位商用处理器,size_t通常会为底层硬件的“bitness”提供良好的近似值,因为它直接与机器的内存寻址能力相关联,并且因此,最有可能是整数数学的最佳大小。

在任何情况下,您都必须在计划支持的所有硬件上测试您的解决方案。

答案 1 :(得分:0)

使用平台拥有的最大整数类型uintmax_t 启动代码是一个好主意。正如已经指出的那样,这不是必然,而是最可能最快。我宁愿说有例外但事实并非如此,但默认情况下,这可能是你最好的选择。

要非常小心地将大小粒度构建到编译器可以在编译类型而不是运行时中解析的表达式中以获得速度。

将基本类型定义为

之类的内容最有可能是个好主意
#define LGINT_BASETYPE uintmax_t
#define LGINT_GRANUL   sizeof(LGINT_BASETYPE)

这将允许您在一个位置更改基本类型并快速适应不同的平台。这导致代码很容易移动到新平台,但仍然可以适应最大int类型不是最高性能的异常情况(在通过测量证明之后)

与往常一样,在设计代码时考虑最佳性能并没有多大意义 - 从合理的平衡开始,设计用于优化&#34;和&#34;设计可维护性&#34; - 您可能很容易发现基类型的选择并不是代码中最耗费CPU的部分。根据我的经验,当我将猜测用于CPU花费在测量上时,我几乎总是总是。不要陷入过早的优化陷阱。