C++言語で記述したプログラムと、アセンブリ言語で記述した関数を利用したときの性能差を検証してみましょう。
arques.hatenablog.com
符号付64ビット整数型
性能評価プログラム
C++で記述した関数と、アセンブリ言語で記述した関数を複数回呼び出します。それぞれに要した時間をclock関数で計測し、性能を評価します。common.hやアセンブリ言語で記述した関数は「特定値のインデックス抽出」で示したものと同じです。以降に、呼び出し側のソースリストを示します。
#include "..\common.h" // TEMPLATES #define T double extern "C" { void afmaaddpd (const T*, const T*, T*, const T, const size_t); void afmasubpd (const T*, const T*, T*, const T, const size_t); void afnmaaddpd (const T*, const T*, T*, const T, const size_t); void afnmasubpd (const T*, const T*, T*, const T, const size_t); void afmaddsubpd(const T*, const T*, T*, const T, const size_t); void afmsubaddpd(const T*, const T*, T*, const T, const size_t); } typedef void (*Dfunc)(const T*, const T*, T*, const T, const size_t); extern "C" Dfunc afunc[] = { afmaaddpd, afmasubpd, afnmaaddpd, afnmasubpd, afmaddsubpd, afmsubaddpd }; Dfunc cfunc[] = { cfmaadd, cfmasub, cfnmaadd, cfnmasub, cfmaddsub, cfmsubadd }; // main int main(void) { const size_t ArrLen = 32768; static_assert(ArrLen % 16 == 0, "number of elements must be an integral multiple of 16."); T k = 11.5f; #define LOOPS 10000 try { T* a = (T*)_mm_malloc(sizeof(T) * ArrLen, 64); T* b = (T*)_mm_malloc(sizeof(T) * ArrLen, 64); T* c = (T*)_mm_malloc(sizeof(T) * ArrLen, 64); T* v = (T*)_mm_malloc(sizeof(T) * ArrLen, 64); init(a, b, ArrLen); clock_t start; for (int i = 0; i < sizeof(cfunc) / sizeof(*cfunc);i++) { cout << "---[" << i << "]--- " << endl; start = clock(); for (int j = 0; j < LOOPS;j++) cfunc[i](a, b, c, k, ArrLen); print_elTime("cpp: ", start, clock()); start = clock(); for (int j = 0; j < LOOPS;j++) afunc[i](a, b, v, k, ArrLen); print_elTime("asm: ", start, clock()); verify(c, v, ArrLen); } _mm_free(v); _mm_free(c); _mm_free(b); _mm_free(a); } catch (char* str) { cerr << str << endl; } return 0; }
これまでと同様に、時間の計測を行います。上記プログラムへ /O2 オプションを指定してビルド&実行したときの性能を示します。
アセンブリ言語で開発した関数は、C++言語で開発した関数より約1.8倍~10.4倍高速です。