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.588 秒に跳ね上がります。これは、すべての変数を size_t に変更しても持続し、時間は 1.646 秒に増加します

何が起こっていますか?size_t は int よりも具体的な型であるため、パフォーマンスを低下させるのではなく、パフォーマンスを向上させるべきではありませんか?

4

2 に答える 2

19

int通常、最速のオールラウンド タイプです。このプロパティは標準では義務付けられていませんが、通常、今日のプラットフォームに当てはまります。int_fast32_tまた、少なくとも 32 ビットを保持できる最速の型であることがより適切に保証されているcstdint のようなものもあります。パフォーマンスに敏感なコードには、これらを強くお勧めします!

size_t速い整数を与えることを意図していません。その目的は、プラットフォームのアドレス空間に含めることができる最大サイズのオブジェクトのサイズを保持できる整数を提供することです。通常size_t、CPU がサポートする最大の「ネイティブ」整数と同等ですが、そうである必要はありません。

64 ビット プラットフォームを使用していると思います。一般に、64 ビット プラットフォームは 32 ビットと 64 ビットの操作でほぼ同等のパフォーマンスを発揮しますが、通常そうではない 1 つの場所に到達しました: div/mod は実際には 64 ビット整数で 2 ~ 3 倍遅くなる可能性があります。 . この場合、intが 32 ビットsize_tで 64 ビットの場合、問題がうまく説明されます。

詳細については、 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 に答える