22348


特別困っているわけではないのですが、気になったので質問です。

int_fast16_t/int_fast32_tの実態がWindowsとLinuxで異なっているのですが、[x64](https://ja.wikipedia.org/wiki/X64)では32ビット整数と64ビット整数の演算はどちらが高速なのでしょうか？  
（Wikipediaの[注釈5](https://ja.wikipedia.org/wiki/X64#cite_note-x86-compat-
perf-5)にある資料がどういう比較なのか理解できていません。）

[code]

                 | Linux(64)      | Windows(64)    | FreeBSD(64)
    -------------+----------------+----------------+-------------
    int_fast8_t  | signed char(8) | signed char(8) | int(32)
    int_fast16_t | long(64)       | int(32)        | int(32)
    int_fast32_t | long(64)       | int(32)        | int(32)
    int_fast64_t | long(64)       | long long(64)  | long(64)
    
[/code]

以下、int_fastN_tの実態を調査したプログラムです。

[code]

    #include <climits>
    #include <cstdint>
    #include <type_traits>
    
    #include <iostream>
    #include <sstream>
    
    using namespace std;
    
    #define PRINT_SAME_TYPE(d_type) \
        do { \
            ostringstream ostream; \
            ostream << #d_type << " = "; \
            if ( is_same<d_type, signed char>::value ) { \
                ostream << "signed char(" << CHAR_BIT << ")"; \
            } \
            else if ( is_same<d_type, short>::value ) { \
                ostream << "short(" << sizeof(short) * CHAR_BIT << ")"; \
            } \
            else if ( is_same<d_type, int>::value ) { \
                ostream << "int(" << sizeof(int) * CHAR_BIT << ")"; \
            } \
            else if ( is_same<d_type, long>::value ) { \
                ostream << "long(" << sizeof(long) * CHAR_BIT << ")"; \
            } \
            else if ( is_same<d_type, long long>::value ) { \
                ostream << "long long(" << sizeof(long long) * CHAR_BIT << ")"; \
            } \
            else { \
                ostream << "unknown"; \
            } \
            cout << ostream.str() << '\n'; \
        } while ( false )
    
    int main()
    {
        cout << "sizeof(char) = " << CHAR_BIT << '\n';
        cout << "sizeof(short) = " << sizeof(short) * CHAR_BIT << '\n';
        cout << "sizeof(int) = " << sizeof(int) * CHAR_BIT << '\n';
        cout << "sizeof(long) = " << sizeof(long) * CHAR_BIT << '\n';
        cout << "sizeof(long long) = " << sizeof(long long) * CHAR_BIT << '\n';
        cout << "sizeof(void *) = " << sizeof(void *) * CHAR_BIT << '\n';
    
        PRINT_SAME_TYPE(int_fast8_t);
        PRINT_SAME_TYPE(int_fast16_t);
        PRINT_SAME_TYPE(int_fast32_t);
        PRINT_SAME_TYPE(int_fast64_t);
    
        PRINT_SAME_TYPE(int_least8_t);
        PRINT_SAME_TYPE(int_least16_t);
        PRINT_SAME_TYPE(int_least32_t);
        PRINT_SAME_TYPE(int_least64_t);
    }
    
[/code]

Linux(64)での実行結果：

[code]

    sizeof(char) = 8
    sizeof(short) = 16
    sizeof(int) = 32
    sizeof(long) = 64
    sizeof(long long) = 64
    sizeof(void *) = 64
    int_fast8_t = signed char(8)
    int_fast16_t = long(64)
    int_fast32_t = long(64)
    int_fast64_t = long(64)
    int_least8_t = signed char(8)
    int_least16_t = short(16)
    int_least32_t = int(32)
    int_least64_t = long(64)
    
[/code]

Windows(64)での実行結果：

[code]

    sizeof(char) = 8
    sizeof(short) = 16
    sizeof(int) = 32
    sizeof(long) = 32
    sizeof(long long) = 64
    sizeof(void *) = 64
    int_fast8_t = signed char(8)
    int_fast16_t = int(32)
    int_fast32_t = int(32)
    int_fast64_t = long long(64)
    int_least8_t = signed char(8)
    int_least16_t = short(16)
    int_least32_t = int(32)
    int_least64_t = long long(64)
    
[/code]

16ビット以上あれば良い整数は長らくint型を使ってきましたが、64ビットマシン時代になってint型が「そのマシンでのワードの自然な大きさ」ではなくなってしまったようなので、これからはint型の代わりに何を使おうかなぁとふと思いまして。

* * *

Linuxと同じくLP64モデルを採用しているFreeBSDを調べてみると、LinuxともWindowsとも異なる結果でした。データモデルとは関係なさそうです。

FreeBSD(64)での実行結果：

[code]

    sizeof(char) = 8
    sizeof(short) = 16
    sizeof(int) = 32
    sizeof(long) = 64
    sizeof(long long) = 64
    sizeof(void *) = 64
    int_fast8_t = int(32)
    int_fast16_t = int(32)
    int_fast32_t = int(32)
    int_fast64_t = long(64)
    int_least8_t = signed char(8)
    int_least16_t = short(16)
    int_least32_t = int(32)
    int_least64_t = long(64)
    
[/code]


CC BY-SA 3.0
2016-02-21T07:04:38.700
22346
2022-07-17T23:37:38.160
2022-07-17T23:37:38.160
4236
7291
question
c++ c cpu
x64では32ビット整数と64ビット整数の演算はどちらが高速？


インテルの発行している[インテル®64アーキテクチャーおよびIA-32アーキテクチャー最適化リファレンス・マニュアルの９章 64
ビット・モードのコーディング・ガイドライン](http://www.intel.co.jp/content/dam/www/public/ijkk/jp/ja/documents/developer/248966-024JA.pdf#page=459)にいくつか説明がありますが

> ほとんどの命令では、デフォルトのオペランドサイズは 32 ビットである。
>
> **アセンブリー / コンパイラー・コーディング規則 65（影響 H、一般性 M）。**
> 64ビット・モードでは、64ビット・データや追加のレジスターへのアクセスに64
> ビット版の命令が必要な場合を除き、32ビット版の命令を使うことでコードサイズを削減する。

とあるように、64ビット・モードにおいても32bitがほぼほぼデフォルトです。64bit演算を行うためには命令が１バイト長くなり、これによりキャッシュ効率が落ちます。

深い話は本書および本章を読まれるといいでしょう。

* * *

> なぜLinux（ClangもGCCも）はint_fast16～32_t=long(64)としたんでしょうね…？

残念ながらコンパイラーには選択権はありません。プラットフォームが決定したサイズに従うのみです。

ではどこで定められたものかというと、私も詳しくはありませんが、[Linux Standard
Base](https://ja.wikipedia.org/wiki/Linux_Standard_Base)の決定した[LSB
3.2](http://refspecs.linuxfoundation.org/lsb.shtml#LSB_3_2_0)に於いてAMD64アーキテクチャについては`int_fast16_t`=`int_fast32_t`=64bitと定められていました。


CC BY-SA 3.0
2016-02-21T08:01:02.833
22348
2016-02-22T07:54:16.100
2020-06-17T08:14:45.997
-1
4236
22346
answer