x64では32ビット整数と64ビット整数の演算はどちらが高速?
特別困っているわけではないのですが、気になったので質問です。
int_fast16_t/int_fast32_tの実態がWindowsとLinuxで異なっているのですが、x64では32ビット整数と64ビット整数の演算はどちらが高速なのでしょうか?
(Wikipediaの注釈5にある資料がどういう比較なのか理解できていません。)
| 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)
以下、int_fastN_tの実態を調査したプログラムです。
#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);
}
Linux(64)での実行結果:
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)
Windows(64)での実行結果:
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)
16ビット以上あれば良い整数は長らくint型を使ってきましたが、64ビットマシン時代になってint型が「そのマシンでのワードの自然な大きさ」ではなくなってしまったようなので、これからはint型の代わりに何を使おうかなぁとふと思いまして。
Linuxと同じくLP64モデルを採用しているFreeBSDを調べてみると、LinuxともWindowsとも異なる結果でした。データモデルとは関係なさそうです。
FreeBSD(64)での実行結果:
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)