簡體   English   中英

std ::設置得快又慢,發生什么事了?

[英]std::set fast and slow, what is going on?

我遇到了std :: set的奇怪行為。

這是代碼:

#include <cstdio>
#include <windows.h>
#include <stdlib.h>

#include <vector>
#include <set>

using namespace std;

int main(int argc, char *argv[])
{
    set<int> b[100];

    for (int o=0; o<10; o++)
    {
        int tt = GetTickCount();

        for (int i=0; i<5000000; i++)
        {
            b[o].insert(i);
        }

        tt = GetTickCount() - tt;

        b[o].clear();

        printf("%d\n", tt);
    }

    return 0;
}

我在Windows XP上運行。

這是有趣的部分:第一次打印時間約為3500毫秒,而接下來的時間都超過9000毫秒! 為什么會這樣?

哦,這只發布在發布版本(-O2優化)。

它不會發生在Linux上(在更改代碼后進行編譯)。

還有一件事:當我使用英特爾VTune進行性能分析時運行它總是需要大約3000毫秒,所以它應該是這樣的。

更新:這是一些新代碼:

#include <cstdio>
#include <windows.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
const int count = 10000000;
int **a = new int*[count];

for (int o=0; o<10; o++)
{
    int ttt = GetTickCount();

    for (int i=0; i<count; i++)
    {
        a[i] = new int;

        *a[i] = i;
    }

    int ttt2 = GetTickCount();

    for (int i=0; i<count; i++)
    {
        int r1 = rand() * 10000 + rand();
        int r2 = rand() * 10000 + rand();
        r1 = r1%count;
        r2 = r2%count;

        int *e = a[r1];
        a[r1] = a[r2];
        a[r2] = e;
    }

    int ttt3 = GetTickCount();

    for (int i=0; i<count; i++)
    {
        delete a[i];
    }

    int ttt4 = GetTickCount();

    printf("%d %d\n", ttt2-ttt, ttt4-ttt3);
}

return 0;
}

這是同樣的問題。 發生的事情是我分配了許多小對象,然后以隨機順序刪除它們 - 所以它類似於它在std :: set中的樣子。 所以這是Windows內存管理問題。 它無法真正處理很多小的alloc和delete。

我無法解釋為什么會發生這種情況,但我可以提出一個解決方案。 當我在調試器(使用F5 )下運行發布版本時,我已經能夠在我的PC上重現這一點。 當我從命令行或使用Ctrl-F5運行構建時,我沒有得到那種行為。

這與調試堆有關,在調試器下啟動時默認啟用調試堆。 這里詳細介紹了它 為了防止這種情況發生

  1. 從命令行或使用Ctrl-F5 (Debug - > Start Without Debugging)。
  2. 轉到項目 - >屬性 - >調試 - >環境並添加_NO_DEBUG_HEAP=1

如果我不得不猜測我會說它與Windows / VS運行時中內存分配跟蹤的實現有關。 可能一些內部列表會填充並重新分配或沿着這些行添加其他內容。

我認為std::set是作為二叉搜索樹實現的。 因為每次實際上為這種類型的數據結構創建一個對抗(最壞情況)場景時,你將i增加1(幾乎每個插入都需要重新平衡樹)。

此外,它是5000萬插入,所以有一段時間,但我不認為它將是5毫秒。

此外,打印您的時間之后,我會“清除”,因為我沒有看到您對插入和移除項目進行基准測試的原因。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM