4

私は「C++ テンプレート完全ガイド」という本を読んでいて、メタ プログラミングに関する部分がありました。ループ展開の例があります (17.7)。内積計算用のプログラムを実装しました。

#include <iostream>
#include <sys/time.h>

using namespace std;

template<int DIM, typename T>
struct Functor
{
    static T dot_product(T *a, T *b)
    {
        return *a * *b + Functor<DIM - 1, T>::dot_product(a + 1, b + 1);
    }
};

template<typename T>
struct Functor<1, T>
{
    static T dot_product(T *a, T *b)
    {
        return *a * *b;
    }
};


template<int DIM, typename T>
T dot_product(T *a, T *b)
{
    return Functor<DIM, T>::dot_product(a, b);
}

double dot_product(int DIM, double *a, double *b)
{
    double res = 0;
    for (int i = 0; i < DIM; ++i)
    {
        res += a[i] * b[i];
    }
    return res;
}


int main(int argc, const char * argv[])
{
    static const int DIM = 100;

    double a[DIM];
    double b[DIM];

    for (int i = 0; i < DIM; ++i)
    {
        a[i] = i;
        b[i] = i;
    }


    {
        timeval startTime;
        gettimeofday(&startTime, 0);

        for (int i = 0; i < 100000; ++i)
        {
            double res = dot_product<DIM>(a, b); 
            //double res = dot_product(DIM, a, b);
        }

        timeval endTime;
        gettimeofday(&endTime, 0);

        double tS = startTime.tv_sec * 1000000 + startTime.tv_usec;
        double tE = endTime.tv_sec   * 1000000 + endTime.tv_usec;

        cout << "template time: " << tE - tS << endl;
    }

    {
        timeval startTime;
        gettimeofday(&startTime, 0);

        for (int i = 0; i < 100000; ++i)
        {
            double res = dot_product(DIM, a, b);
        }

        timeval endTime;
        gettimeofday(&endTime, 0);

        double tS = startTime.tv_sec * 1000000 + startTime.tv_usec;
        double tE = endTime.tv_sec   * 1000000 + endTime.tv_usec;

        cout << "loop time: " << tE - tS << endl;
    }

    return 0;
}

私は xcode を使用しており、すべてのコードの最適化をオフにしました。本によると、テンプレートバージョンは単純なループよりも高速でなければならないことを期待していました。しかし、結果は (t - テンプレート、l = ループ) です。

DIM 5: t = ~5000、l = ~3500

DIM 50: t = ~55000、l = 16000

DIM 100: t = 130000、l = 36000

また、パフォーマンスの違いなしでテンプレート関数をインライン化しようとしました。

単純なループが非常に高速なのはなぜですか?

4

1 に答える 1

5

コンパイラによっては、パフォーマンスの最適化を有効にしないと、ループ展開が行われない場合があります。

理由を理解するのは非常に簡単です。再帰的なテンプレートのインスタンス化は、基本的に一連の関数を作成しています。コンパイラは、そのすべてをインライン化され展開されたループに変換することはできず、それでも適切なデバッグ情報を利用できるようにします。関数の 1 つの中でセグメンテーション違反が発生したり、例外がスローされたりしたとします。各フレームを示すスタック トレースを取得できるようにしたいと思いませんか? コンパイラは、最適化をオンにしない限り、あなたがそれを望んでいると考えます。これにより、コンパイラはコードを処理する許可を得ることができます。

于 2012-04-13T14:22:20.240 に答える