0

std :: map(またはstd :: set、このシナリオでは同じように動作するようです)で奇妙な動作をします。 これがどのように機能するかについて、私は重大な誤解を持っているのかもしれません。 VS2010SP1を使用しています。

この関数を例にとってみましょう。

extern time_t g_nElapsed;
UINT Thread(LPVOID _param)
{
    UINT nRuns = (UINT)_param;

    for(UINT i=0; i<nRuns; ++i)
    {
        time_t _1 = time(NULL);
        std::set<UINT> cRandomSet;
        cRandomSet.insert(1);
        cRandomSet.insert(2);
        cRandomSet.insert(3);
        cRandomSet.insert(4);
        g_nElapsed += (time(NULL) - _1);
    }


    return 0;
}

ここで、それぞれ100,000回の反復で8つのスレッドを実行すると、g_nElapsedは約40秒になります。800,000回の反復で1つのスレッドを実行すると、g_nElapsedは約5秒になります。g_nElapsedは、妥当な量のスレッドでほぼ同じである必要があるという印象を受けています。いわば...作業は同じままですが、プロセッサの使用量はスレッドの数とともに増加します。ただし、セットとのある種のリソース競合により、ランタイムが増加するようです。しかし、なぜ?スレッドローカルです...

それは単純な誤解と単純な修正であると確信していますが、ここでの問題が何であるかはよくわかりません。

次のコードはこの動作を示しません。

extern time_t g_nElapsed;
UINT Thread(LPVOID _param)
{
    UINT nRuns = (UINT)_param;

    for(UINT i=0; i<nRuns; ++i)
    {
        time_t _1 = time(NULL);
        UINT n[4];
    n[0] = 1;
        n[1] = 1;
        n[2] = 1;
        n[3] = 1;
        g_nElapsed += (time(NULL) - _1);
    }


    return 0;
}
4

1 に答える 1

3

あなたは多くのコンテナを作成して破壊していて、それぞれがoperator newメモリを割り当てるために使用しています。多くのシステムでは、これには、あなたのような典型的な小さな割り当てで配られる空きメモリを管理するための同期が必要です。したがって、おそらくそこではかなり多くのスレッド間競合が発生しています。

tcmalloc(http://goog-perftools.sourceforge.net/doc/tcmalloc.html)などの別のアロケータを試すことができます。これに対処するために特別に設計されています。

別のアプローチは、オブジェクトプールまたは他の割り当て戦略を使用して、標準の割り当てメカニズムを完全に使用しないようにすることです。これにはいくつかのコード変更が必要ですが、tcmallocを使用する必要はありません。

于 2013-02-26T12:45:27.200 に答える