11

我将这里的代码翻译成C++如下

#include <iostream>

using namespace std;

int t = 20;

bool is_evenly_divisible(const int a, const int b) {
    for (int i=2; i<=b; ++i) { // Line 1
        if (a%i != 0)
            return false;
    }
    return true;
}

void run() {
    int i = 10;
    while (!is_evenly_divisible(i, t)) {
        i += 2;
    }
    cout << i << endl;
}

int main(int argc, char** argv) {
    run();
    return 0;
}

在 Mac OSX 10.8.4 上的编译器 g++ 4.8.1 上使用 -O3 标志,我得到了 0.568 秒的用户时间。

现在如果我将函数 is_evenly_divisible 的第 1 行中的计数器 i 更改为 size_t,时间会突然跳到 1.588s。即使我将所有变量都更改为 size_t,这种情况仍然存在,时间增加到 1.646s

发生了什么?size_t 不应该提高性能而不是降低性能,因为它是比 int 更具体的类型?

4

2 回答 2

19

int通常是最快的全能型。该属性不是标准强制要求的,但通常是当今平台的情况。我们也有像 cstdint 之类的东西int_fast32_t,它更能保证是最快的类型,至少可以保存 32 位——强烈推荐它们用于性能敏感的代码!

size_t不打算给出一个快速整数。它的目的是提供一个整数,可以容纳平台地址空间可以包含的最大对象的大小。通常size_t等效于您的 CPU 支持的最大“本机”整数,但并非必须如此。

我猜你是在 64 位平台上。通常,64 位平台对 32 位和 64 位操作的性能大致相同,但是您已经遇到了它们通常不会的地方:div/mod 在 64 位整数上实际上可以慢 2-3 倍. 在这种情况下,如果int是 32 位和size_t64 位,它很好地解释了这个问题。

有关详细信息,请参阅Agner Fog 的说明表文档。对于 Intel 的 Sandy Bridge 平台,它显示 32 位 div 的延迟为 20-28 个周期,而 64 位 div 需要 30-94 个周期。

于 2013-06-29T21:06:22.193 回答
1

size_t 的大小是实现定义的,如果您运行的是 64 位机器,大多数编译器会将其设为 8 字节长。

使用 8 字节整数的操作通常比使用 4 字节类似物的操作要慢。

于 2013-06-29T21:07:36.537 回答