一次元配列から特定の値を探すプログラムを応用して、C++言語で記述したプログラムと、アセンブリ言語で記述した関数を利用したときの性能差を検証してみましょう。
本記事は、性能評価:値の検索 - arques’s diaryをAVX512からAVX命令へ書き換えたものです。
32ビット浮動小数点型
全ての型を解説すると冗長になるため、32ビット浮動小数点型の例だけ示します。なお、整数型を扱いたい場合はAVX2命令を使用する必要があります。
#include "..\common.h" // TEMPLATES #define T float extern "C" { int asrchps(const T*, const T, const size_t); } // 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 a[ArrLen]; T value = 80000; try { T cindex, aindex; clock_t start; T* a = (T*)_mm_malloc(sizeof(T) * ArrLen, 64); #define LOOPS 10000 for (size_t j = 1; j < 18; j++) { init(a, ArrLen); start = clock(); for (int i = 0; i < LOOPS;i++) { a[ArrLen - j] = value; cindex = cSrch(a, value, ArrLen); } print_elTime("cpp: ", start, clock()); init(a, ArrLen); start = clock(); for (int i = 0; i < LOOPS;i++) { a[ArrLen - j] = value; aindex = asrchps(a, value, ArrLen); } print_elTime("asm: ", start, clock()); string okng = cindex == aindex ? " OK!" : " NG!"; cout << "cpp: " << cindex << ", asm: " << aindex << okng << endl; } _mm_free(a); } catch (char* str) { cerr << str << endl; } return 0; }
これまでと同様に、時間の計測を行います。アセンブリ言語で開発した関数、C++言語で開発した関数の両方を10,000回呼び出し、それぞれに要した時間を表示します。プログラムを起動すると、それぞれに要した時間が表示されます。横軸は比較の種類、縦軸は処理に要した時間(ミリ秒)です。
アセンブリ言語で開発した関は、C++言語で開発した関数より約5.7倍高速です。理想的には8倍高速になることを期待しますが、オーバヘッドやメモリアクセスなどに時間を奪われているのでしょう。