簡體   English   中英

使用帶預分配 std::unordered_map 的嵌套向量快速構造 unordered_map <int, vector<thing *> >?</int,>

[英]Fast construction of unordered_map with nested vector with preallocation std::unordered_map<int, vector<Thing *>>?

我想創建 map 的 int 到 Things* 的向量。 我知道Thing將不再是 1-50。 如何在開始時分配 50 以加快 map 的構建?

我嘗試了三種方法,但仍然不確定它是否足夠快。 你能建議更好的優化嗎? 我在 10 年前使用 c++,我不確定我是否正確使用。 你能幫我嗎? 歡迎所有優化建議。 代碼是從實際問題中簡化而來的。

#include <iostream>
#include <vector>
#include <unordered_map>

#include <time.h>

class Thing {
};

int main()
{
    clock_t start;
    start = clock();
    auto int_to_thing = std::unordered_map<int, std::vector<Thing *>>();
    for (int i = 0; i < 1000; i++) {
        for (int j = 0; j < 25; j++) {
            int_to_thing[i].push_back(new Thing());
        }
    }
    for (int i = 0; i < 1000; i++) {
        for (int j = 0; j < 25; j++) {
            int_to_thing[i].push_back(new Thing());
        }
    }
    std::cout << (clock() - start) << std::endl;

    start = clock();
    int_to_thing = std::unordered_map<int, std::vector<Thing *>>();
    for (int i = 0; i < 1000; i++) {
        int_to_thing[i].reserve(50);
        for (int j = 0; j < 25; j++) {
            int_to_thing[i].push_back(new Thing());
        }
    }
    for (int i = 0; i < 1000; i++) {
        for (int j = 0; j < 25; j++) {
            int_to_thing[i].push_back(new Thing());
        }
    }
    std::cout << (clock() - start) << std::endl;

    start = clock();
    int_to_thing = std::unordered_map<int, std::vector<Thing *>>();
    for (int i = 0; i < 1000; i++) {
        auto it = int_to_thing.find(i);
        if (it != int_to_thing.end()) {
            auto v = std::vector<Thing *>(50);
            auto pair = std::pair<int, std::vector<Thing *>>(i, v);
            int_to_thing.insert(pair);
        }
    }
    for (int i = 0; i < 1000; i++) {
        for (int j = 0; j < 25; j++) {
            int_to_thing[i].push_back(new Thing());
        }
    }
    std::cout << (clock() - start) << std::endl;
    
    return 0;
}

您是否關心map的構造(然后查看@ShadowRanger 的評論)或向量的構造?

我假設一個向量中有 1..50 個Thing ,而不是 map 中的 1..50 個向量。

你的代碼:

int_to_thing = std::unordered_map<int, std::vector<Thing *>>();
for (int i = 0; i < 1000; i++) {
    int_to_thing[i].reserve(50);

是最好的選擇。 它構造一個 map 向量,並在循環內創建每個向量並為 50 個元素預分配空間。

如果沒有reserve() ,您可能會在將 50 個元素推入這些向量時遇到幾次重新分配。

使用:

auto v = std::vector<Thing *>(50);

實際上在你的向量中創建了50 個元素,並默認初始化它們。 這可能會或可能不會花費您額外的費用。 具體來說,對於您當前使用的指針,它會很便宜,而如果您轉而存儲Thing對象本身,則會很昂貴。

如果您不確定某件事是否足夠快,那么您就沒有在衡量性能,這是初步證據表明您根本不在乎它。 如果你不測量它,那么你就不能對它提出任何要求。 在你做任何其他事情之前先測量它。 否則你會浪費大家的時間。 您假設此類預分配會有所幫助。 我有一種暗示,他們根本幫不上忙,因為你做的太少了,你只是在浪費時間。 再說一次:如果你對性能很認真,你現在就停下來,進行適當的測量,然后帶着一些數字回來討論。 並且不要測量調試構建——只測量啟用了全面優化的發布構建,包括鏈接時間代碼生成 (LTCG)。 如果你不優化,你也不關心性能。 時期。 句號。 這些是規則。

是的,你有代碼來計算時間,但這不是測量的目的。 它們需要在您使用數據的上下文中發生,以便您可以看到您有多少相對開銷。 如果這項任務需要一個小時,而你花了一秒鍾來做這個“非最佳”,那么首先優化它是沒有意義的——你有更大的魚要先煎。 此外,在大多數情況下,代碼是緩存驅動的,即數據訪問模式決定性能,所以我認為您目前根本沒有做任何有用的事情。 這樣的微優化完全沒有意義。 此代碼不存在於真空中。 如果是這樣,您可以將其刪除並忘記這一切,對嗎?

暫無
暫無

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

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