繁体   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