0

我对 std::map 有一个奇怪的行为(或 std::set,在这种情况下它们的行为似乎相同)。 可能是我对这应该如何工作有一个严重的误解。 我正在使用 VS2010 SP1。

以这个函数为例:

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;
}

现在,如果我运行 8 个线程,每个线程进行 100,000 次迭代,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 回答