理論性能の見積もり|行列積高速化#2
この記事は、以下の記事を分割したものです。
[元の記事]行列積計算を高速化してみる
一括で読みたい場合は、元の記事をご覧ください。
理論性能の計算方法については、下記の記事で解説しています。
ここでは、評価マシンであるMacBook Proの理論性能を計算してみましょう。しかし、毎回手で計算するのは面倒ですので、前回作成したCPUIDプログラムを使って、プログラムにしてしまいます。
まず、FLOPS値をいつでも再計算できるように、必要な情報を格納する構造体を作りました。
typedef struct _flops_info_t {
size_t base_freq;
size_t max_freq;
size_t num_cores;
size_t fp_operator;
size_t fp_operation;
size_t vlen_bits;
double mflops_single_base;
double mflops_single_max;
double mflops_double_base;
double mflops_double_max;
} flops_info_t;
まず、base_freqとmax_freqは、CPUの動作周波数の基本周波数と最大周波数を格納する変数です。これらは、全てMHz単位で取得されます。
num_coresは、コア数です。コア数が2倍になると理論性能も2倍になるため、理論性能の計算に必要になります。
fp_operatorは、浮動小数点演算器の個数です。これは、CPUのマイクロ・アーキテクチャに依存します。Intel製CPUでは、Skylake Microarchitectureまでは、Port 0(ADD)とPort 1(MUL)の2個でした。Skylake Server Microarchitectureでは、少し増えているみたいです。
fp_operationは、浮動小数点演算器で1回に計算できる演算数です。ADDやMULは1回につき1演算ですが、FMA(Fused Multiply and Add)は1回でADD/MULの両方を計算するため、1回につき2演算となります。
vlen_bitsは、ビット単位のベクトル長です。ベクトル長は、一命令で同じ演算をするデータ数なので、理論性能の計算に必要です。ベクトル長は、拡張命令セットが更新されるたびに長くなっています。MMXでは64ビット、SSE2で128ビット、AVXで256ビット、AVX512で512ビット、という具合です。
Mflops_single_baseとMflops_single_maxは、単精度不動小数点(float型)演算の場合のMFLOPS値です。2種類の動作周波数に合わせて、2つの値を用意しています。mflops_double_baseとMflops_double_maxは、倍精度不動小数点(double型)演算のMFLOPS値です。
これらをCPUIDの値から計算するプログラムは、下記の通りです。
void peak_flops( flops_info_t* out ){
cpuid_info_t info;
read_cpuid_info( &info );
// Frequency (MHz)
size_t base_freq = info.proc_freq_info.proc_base_freq;
size_t max_freq = info.proc_freq_info.max_freq; // on Tarbo Boost
// Number of cores
size_t num_cores = 0;
for( int i=0; i< info.num_tplevel; i++ ){
num_cores += info.topology[i].num_log_procs;
}
// Number of Floting-point operators
size_t fp_operator = 2;
// Floting-point Operations in an operator
size_t fp_operation = 1;
if( info.basic_info.features[0] & F_FMA ){ fp_operation = 2; }
// Vector length
size_t vlen_bits = 0;
if( info.basic_info.features[1] & F_MMX ){ vlen_bits = 64; } // introduced MM registers
if( info.basic_info.features[1] & F_SSE2 ){ vlen_bits = 128; } // introduced XMM registers
if( info.more_feature[0].features[1] & F_AVX2 ){ vlen_bits = 256; } // introduced YMM registers
if( info.more_feature[0].features[1] & F_AVX512F ){ vlen_bits = 512; } // introduced ZMM registers
out->base_freq = base_freq;
out->num_cores = num_cores;
out->max_freq = max_freq;
out->fp_operator = fp_operator;
out->fp_operation = fp_operation;
out->vlen_bits = vlen_bits;
out->mflops_single_base = num_cores * fp_operator * fp_operation * (vlen_bits/(8*sizeof(float))) * base_freq;
out->mflops_single_max = num_cores * fp_operator * fp_operation * (vlen_bits/(8*sizeof(float))) * max_freq;
out->mflops_double_base = num_cores * fp_operator * fp_operation * (vlen_bits/(8*sizeof(double))) * base_freq;
out->mflops_double_max = num_cores * fp_operator * fp_operation * (vlen_bits/(8*sizeof(double))) * max_freq;
}
コア数の計算とvlen_bitsを浮動小数点型要素数に変換する処理がやや面倒ですが、それ以外は前段で説明したことをそのままプログラムに直しています。
vlen_bitsは、ビット単位をバイト単位に直すために8で割り、バイト単位を浮動小数点型の要素単位に直すためにsizeof(float)やsizeof(double)で割っています。
ここで使用しているCPUIDのデータを取得するプログラムは、下記の記事をご覧下さい。
さて、上記のpeak_flops関数を使って、MacBook Proの1コア理論ピーク性能を計算してみると、次のとおりでした。
Max Peak MFlops per Core: 52800 MFlops
Base Peak MFlops per Core: 46400 MFlops
これによって、基本周波数で動作している時は46.4GFlops、最大周波数で動作している時は52.8GFlopsと分かりました。
次の記事
元の記事はこちらです。
ソースコードはGitHubで公開しています。
この記事が気に入ったらサポートをしてみませんか?