3

最初は s の配列であったシリアル メモリ 2D 配列のクラスがありintます。別の型の同様の配列が必要になったので、テンプレートを使用してクラスを書き直しました。唯一の違いは、格納されたオブジェクトのタイプにあります。

template <class T>
class Serial2DArray
{
    ...
    T ** Content;
}

コンテンツを処理するいくつかのテスト関数があります。たとえば、配列内のすべての要素を無効にする関数です (それらはクラス メンバーではなく、Serial2DArray<int>オブジェクトを操作する関数の外部にあります。1- 2% 遅い - クラス内の他のすべてのコードは変更されていません。唯一の違いは、以前は単なる通常のクラスでしたがint ** Content、現在はテンプレートになっていることです。

似たような質問: C++ テンプレートはプログラムを遅くしますか? -コンパイルだけが遅くなるという意見があります(コンパイラがコード内で見つけたそれぞれのクラスを生成する理由がわかります)が、ここではプログラムが実行時に遅くなることがわかります-合理的な説明はありますか?

Upd: ここで問題を少し絞り込みました: https://stackoverflow.com/a/11058672/1200000

Upd2: コメントで述べたように、遅くなった関数は次のとおりです。

#include <windows.h>
#include <mmsystem.h>
...
int Size = G_Width * G_Height * sizeof(int);
DWORD StartTime = timeGetTime();
for(int i=0; i<100; ++i)
{
    FillMemory(TestArray.Content[0], Size, 0);
}
MeasuredTime = timeGetTime() - StartTime;

実際のクラス テンプレートは次のとおりです。

#include <malloc.h>

template <class T>
class Serial2DArray
{
    public:
    Serial2DArray()
    {
        Content = NULL;
        Width = 0;
        Height = 0;
    }
    Serial2DArray(int _Width, int _Height)
    {
        Initialize(_Width, _Height);
    }
    ~Serial2DArray()
    {
        Deinitialize();
    }
    T ** Content;
    int GetWidth()
    {
        return Width;
    }
    int GetHeight()
    {
        return Height;
    }
    int Initialize(int _Width, int _Height)
    {
        // creating pointers to the beginning of each line
        if((Content = (T **)malloc(_Height * sizeof(T *))) != NULL)
        {
            // allocating a single memory chunk for the whole array
            if((Content[0] = (T *)malloc(_Width * _Height * sizeof(T))) != NULL)
            {
                // setting up line pointers' values
                T * LineAddress = Content[0];
                for(int i=0; i<_Height; ++i)
                {
                    Content[i] = LineAddress; // faster than Content[i] =
                    LineAddress += _Width;    // Content[0] + i * _Width;
                }
                // everything went ok, setting Width and Height values now
                Width = _Width;
                Height = _Height;
                // success
                return 1;
            }
            else
            {
                // insufficient memory available
                // need to delete line pointers
                free(Content);
                return 0;
            }
        }
        else
        {
            // insufficient memory available
            return 0;
        }
    }
    int Resize(int _Width, int _Height)
    {
        // deallocating previous array
        Deinitialize();
        // initializing a new one
        return Initialize(_Width, _Height);
    }
    int Deinitialize()
    {
        // deleting the actual memory chunk of the array
        free(Content[0]);
        // deleting pointers to each line
        free(Content);
        // success
        return 1;
    }
    private:
    int Width;
    int Height;
};

リクエストに応じて、バイナリ サイズの比較。

次のコードを使用します。

Serial2DArray<int> TestArray; 
Serial2DArray<int> ZeroArray;
  • 1 016 832 バイト。

次のコードを使用します。

Serial2DArray TestArray; // NOT-template class with ints
Serial2DArray ZeroArray; // methods are in class declaration
  • 1 016 832 バイト

次のコードを使用します。

Serial2DArray<int> TestArray;
Serial2DArray<int> ZeroArray;
Serial2DArray<double> AnotherArray;
Serial2DArray<double> YetAnotherArray;
  • 1 017 344 バイト
4

2 に答える 2

2

ええ-プログラム全体が遅いという事実は言うまでもなく、ランダムなベンチマークの変動性は、この特定のクラスとはまったく関係がないかもしれません。

于 2012-06-15T21:31:27.017 に答える
-2

コンテナ クラスでテンプレートを使用すると、テンプレート コードの肥大化という既知の問題が発生する可能性があります。大まかに言うと、プログラムのページ フォールトが増えてパフォーマンスが低下する可能性があります。

では、なぜあなたは尋ねるのですか?テンプレートは、1 つではなく、テンプレートのクラス インスタンスごとにクラスを生成するため、バイナリ プロダクトのページが増え、必要に応じてコード ページが増えます。ランタイムの実行によっては、統計的にページ フォールトが増える可能性があります。

1 つのクラス テンプレート インスタンスと、最も重いはずの 2 つのインスタンスを使用して、バイナリのサイズを確認します。新しいインスタンスで導入された新しいコード サイズを把握できます。

そのトピックに関するウィキペディアの記事は次のとおりです。 Code bloat article。コンパイラで使用できる場合のみ、プログラム内のすべての関数とメソッドをインライン化するようにコンパイラに強制する場合、問題は同じになる可能性があります。inline標準では、キーワードをコンパイラが毎回従う必要のない" request "にすることで、それを防ごうとしています。たとえば、GCC は中間言語でコードを生成して、結果のバイナリがコードの肥大化につながらないかどうかを評価し、結果としてインライン リクエストを破棄する場合があります。

于 2012-06-15T21:36:12.803 に答える