性能評価:抽出・インデックス

C++言語で記述したプログラムと、アセンブリ言語で記述した関数を利用したときの性能差を検証してみましょう。
arques.hatenablog.com

符号付64ビット整数型

性能評価プログラム

C++で記述した関数と、アセンブリ言語で記述した関数を複数回呼び出します。それぞれに要した時間をclock関数で計測し、性能を評価します。common.hやアセンブリ言語で記述した関数は「抽出」で示したものと同じです。以降に、呼び出し側のソースリストを示します。

#include "..\common.h"  // TEMPLATES

#define T long long
extern "C"
{
    int extWidxQLow (const T*, T*, int*, const T, size_t );
    int extWidxQHigh(const T*, T*, int*, const T, size_t );
    int extWidxQ    (const T*, T*, int*, const T, size_t , const T);
}

int main(void)
{
    const int ArrLen = 32768;
    static_assert(ArrLen % 16 == 0,
        "number of elements must be an integral multiple of 16.");
    int cIdx[ArrLen], vIdx[ArrLen];
    const T low = -500, high = 500;

    try
    {
        int cLen, aLen;
        T* a = (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);

        clock_t start;

        #define LOOPS   10000
        init(a, ArrLen);

        cout << endl << "[ v < " << low << "]" << endl;
        start = clock();
        for (int j = 0; j < LOOPS;j++)
            cLen = cextractLow (a, c, cIdx, low, ArrLen);
        print_elTime("cpp: ", start, clock());

        start = clock();
        for (int j = 0; j < LOOPS;j++)
            aLen = extWidxQLow(a, v, vIdx, low, ArrLen);
        print_elTime("asm: ", start, clock());

        verify(cLen, aLen, cIdx, vIdx, c, v, ArrLen);


        cout << endl << "[ v > " << high << "]" << endl;
        start = clock();
        for (int j = 0; j < LOOPS;j++)
            cLen = cextractHigh (a, c, cIdx, high, ArrLen);
        print_elTime("cpp: ", start, clock());

        start = clock();
        for (int j = 0; j < LOOPS;j++)
            aLen = extWidxQHigh(a, v, vIdx, high, ArrLen);
        print_elTime("asm: ", start, clock());

        verify(cLen, aLen, cIdx, vIdx, c, v, ArrLen);


        cout << endl << "[ " << low << " < v < " << high << "]" << endl;
        start = clock();
        for (int j = 0; j < LOOPS;j++)
            cLen = cextract (a, c, cIdx, low, ArrLen, high);
        print_elTime("cpp: ", start, clock());

        start = clock();
        for (int j = 0; j < LOOPS;j++)
            aLen = extWidxQ(a, v, vIdx, low, ArrLen, high);
        print_elTime("asm: ", start, clock());

        verify(cLen, aLen, cIdx, vIdx, c, v, ArrLen);


        _mm_free(v);
        _mm_free(c);
        _mm_free(a);
    }
    catch (char* str)
    {
        cerr << str << endl;
    }
    return 0;
}

これまでと同様に、時間の計測を行います。上記プログラムへ /O2 オプションを指定してビルド&実行したときの性能を示します。

アセンブリ言語で開発した関数は、C++言語で開発した関数より約2.8倍から7.7倍高速です。データ依存がありそうで、値によってC++言語で記述した関数の処理時間は変動します。以降の性能評価も、データ依存があると考えて参考にしてください。

符号なし64ビット整数型


アセンブリ言語で開発した関数は、C++言語で開発した関数より約1.3倍から3.2倍高速です。

符号付16ビット整数型


アセンブリ言語で開発した関数は、C++言語で開発した関数より約10.5倍から16.4倍高速です。

符号なし16ビット整数型


アセンブリ言語で開発した関数は、C++言語で開発した関数より約11.1倍から17.1倍高速です。

64ビット浮動小数点型


アセンブリ言語で開発した関数は、C++言語で開発した関数より約80.倍から17.4倍高速です。

32ビット浮動小数点型


アセンブリ言語で開発した関数は、C++言語で開発した関数より約13.4倍から34.7倍高速です。