-6

昨日、スタックとヒープの割り当ての違いが実際にどのくらい大きくなるかを確認するために、いくつかのパフォーマンス テストを行っていました。このようなテストから予想されることは、ヒープの割り当てがわずかに遅いか、スタックの割り当てと同等であるということです。しかし、私はその反対を発見して唖然としました。論理的に可能である理由と方法を説明することはできませんが、ヒープ割り当ては常にわずかに高速です (最適化をオフにしてコンパイルしていました)。

これは出力例です:

ticks (stack): 42698
ticks (stack): 43977
ticks (stack): 44024
ticks (stack): 44070
ticks (stack): 45038

ticks (heap): 42588
ticks (heap): 43525
ticks (heap): 43633
ticks (heap): 43681
ticks (heap): 43071

これは小さな違いですが、非常に一貫しており、ヒープ割り当てを優先して 100% の確率で再現します。

なぜこれらの奇妙な結果が得られるのか、誰か説明できますか?

これは私が実行したコードです:

#include <vector>
#include <iostream>
#include <string>
#include <windows.h>

using namespace std;

struct JJ
{
    int c[50];
    JJ(int i) { c[5] = 3; c[29] = 4; c[30] = i; c[49] = c[5]; }
};

void fill_direct_stack()
{
    vector<JJ> vec;
    for (int i=0; i<1000; ++i)
        vec.push_back(i);
}

void fill_direct_heap()
{
    vector<JJ>* pVec = new vector<JJ>();
    for (int i=0; i<1000; ++i)
        pVec->push_back(i);
    delete pVec;
}

CRITICAL_SECTION cs_print;

void print(string msg, DWORD val)
{
    EnterCriticalSection(&cs_print);
    cout << msg << val << endl;
    LeaveCriticalSection(&cs_print);
}

DWORD __stdcall threadEntry(void*)
{
    DWORD ticks1,ticks2;

    ticks1 = GetTickCount();
    for (int i=0; i<10000; ++i)
        fill_direct_stack();
    ticks2 = GetTickCount();
    print("ticks (stack): ", ticks2 - ticks1);

    ticks1 = GetTickCount();
    for (int i=0; i<10000; ++i)
        fill_direct_heap();
    ticks2 = GetTickCount();
    print("ticks (heap): ", ticks2 - ticks1);

    return 0;
}

int main()
{
    cout<<"hi"<<endl;

    InitializeCriticalSection(&cs_print);

#define N_THREADS 5

    HANDLE thr[N_THREADS];
    for (int i=0; i<N_THREADS; ++i)
        thr[i] = CreateThread(NULL, 0, &threadEntry, NULL, 0, NULL);

    for (int i=0; i<N_THREADS; ++i)
        WaitForSingleObject(thr[i], INFINITE);

    DeleteCriticalSection(&cs_print);

    system("pause");
}
4

2 に答える 2

6

割り当て

vector<JJ>* pVec = new vector<JJ>();

vector<JJ> vec;

プッシュバックや内部メモリ管理に比べれば何もありvectorません。

于 2013-01-09T13:40:25.817 に答える
1

このような人為的なベンチマークで、このようなわずかな違いの原因を説明するのは困難です。しかし、私の推測では、それはアライメントの問題です。ヒープから割り当てると、任意の型を格納するために適切に配置されたメモリのチャンクが得られます。スタックから割り当てると、格納する型に適した、最小限に整列されたメモリのチャンクが取得されます。

私のもう 1 つの理論は、データ キャッシュのヒット率だというものです。1 つのスレッドが終了し、次に同じコアで別のスレッドが実行されていることを考慮してください。スタック割り当てでは、各スレッドに独自のスタックがあるため、メモリの同じチャンクに割り当てられることはありません。データ キャッシュはコールドになります。ヒープ割り当てを使用すると、割り当ては、前のスレッドによって解放されたばかりの同じブロックを取得する可能性があります。メモリのチャンクは、CPU データ キャッシュでホットになります。(ただし、この理論では、数字にはかなりの変動があると予測されます。私は、あなたが見ているよりも大きいと思います。)

しかし、違いは非常に小さいので、何でもかまいません。

于 2013-01-09T13:48:23.800 に答える