为啥插入 set<vector<string>> 这么慢?

Posted

技术标签:

【中文标题】为啥插入 set<vector<string>> 这么慢?【英文标题】:Why is inserting into a set<vector<string>> so slow?为什么插入 set<vector<string>> 这么慢? 【发布时间】:2016-12-02 21:08:50 【问题描述】:

对于一个类项目,我们正在制作一个简单的编译器/关系数据库。我的产生正确答案,但在大型查询中速度太慢。我运行了 Visual Studio 的性能分析,我的程序花费了 80% 的时间将我的元组(表格中的行)插入到一个集合中。该函数是计算叉积的一部分,因此结果有很多很多行,但我需要有关将元组插入集合的更快方法的建议。

for (set<vector<string>>::iterator it = tuples.begin(); it != tuples.end(); ++it)

    for (set<vector<string>>::iterator it2 = tuples2.begin(); it2 != tuples2.end(); ++it2)
    
        vector<string> f(*it);
        f.insert(f.end(), it2->begin(), it2->end());
        newTuples.insert(f); //This is the line that takes all the processing time
    

【问题讨论】:

什么是newTuples 您的向量是在每次插入时通过复制创建的。使用指针和新的。 @PierreEmmanuelLallemant,多么糟糕的建议…… @SergeyA:不知道 std::move,ty。 newTuples 是我正在制作的新表中的所有行。 【参考方案1】:

您无缘无故地按值复制大向量。你应该移动:newTuples.insert(std::move(f));

【讨论】:

有道理,但对函数花费的时间没有影响。向量不是很大(最多 20 项)【参考方案2】:

set 可能是错误的容器。 set 是有序的,并且只保留唯一的元素。当您插入一个新的vector 时,可能会发生许多string 比较。

改用listvector(如果可以的话)。

...避免不必要的复制,正如 SergeyA 在他的回答中已经指出的那样

【讨论】:

你可能是对的,我最初使用一组作为摆脱重复项的简单方法。现在更改它需要大量重构,并且可能不值得我的 1% 的成绩。【参考方案3】:

我们还不如去 C++11(完全未经测试的代码)

for (const auto& it : tuples) 
    for (const auto& it2 : tuples2) 
        auto where = newTuples.emplace(it); // returns where its placed
        auto& vect = where.first; // makes the next more readable
        vect.insert(vect.end(), it2.begin(), it2.end());
    

注意碰撞,一些字符串会从结果中消失,这真的是你想要的吗? 您使用向量作为键,这会不会是碰撞?添加

if (!where.second) 
  ; // collision

检查。

这应该消除所有移动的双重工作(如果编译器无论如何都没有优化它)。

【讨论】:

以上是关于为啥插入 set<vector<string>> 这么慢?的主要内容,如果未能解决你的问题,请参考以下文章

招生(vector,有序插入insert),遍历

vector, map, queue,set常用总结

1052 卖个萌

std::set 唯一 ptr 范围插入

为啥这段代码可以正常工作? (vector.clear(), vector<vector<int>>)

为啥c++的set容器的自定义比较函数要用一个结构体重载()符