在 gcc 中使用 erase(begin()) 从unordered_set "remove one element"很慢
"remove one element" from unordered_set using erase(begin()) is slow in gcc
我想有一个函数来从unordered_set中"删除一个元素"。
但是,当它使用 erase(begin()) 实现时,它会变得非常慢。(这是在 g++-4.5.3 中;也许 begin() 必须遍历更多的空哈希桶?)
请参阅下面的示例代码,其中包含令人惊讶的时间。
有没有其他方法可以实现"删除一个元素",从而提高效率? (我确实想允许其他干预集合操作,这些操作会使迭代器无效。
#include <unordered_set>
#include <iostream>
#include <chrono>
using namespace std;
struct Timer {
Timer(string s) : _s(s), _start(Clock::now()) { }
~Timer() {
auto t=chrono::duration_cast<chrono::milliseconds>(Clock::now()-_start).count();
cerr << "Timer(" << _s << ") = " << t << "msn";
}
private:
typedef chrono::high_resolution_clock Clock;
string _s;
Clock::time_point _start;
};
int main()
{
unordered_set<int> s;
const int num=200000;
{ Timer t("insert"); for (int i=0;i<num;i++) { s.insert(i); } }
{ Timer t("remove half"); for (int i=0;i<num/2;i++) { s.erase(s.begin()); } }
long long s1=0, s2=0;
{ Timer t("access begin()"); for (int i=0;i<num/2;i++) { s1+=*s.begin(); } }
{ Timer t("access all"); for (auto it=s.begin();it!=s.end();++it) { s2+=*it; } }
cerr << s1 << " " << s2 << "n";
return 0;
}
// Timer(insert) = 36ms
// Timer(remove half) = 3039ms
// Timer(access begin()) = 5958ms
// Timer(access all) = 1ms
它看起来像是该版本的 GNU 库的问题,在较新的版本中修复。以下是我的测试结果,使用我碰巧安装的两个版本:
mikes@seymour-desktop:~$ g++-4.4.5 -std=c++0x -O3 test.cpp
mikes@seymour-desktop:~$ ./a.out
Timer(insert) = 15ms
Timer(remove half) = 3815ms
Timer(access begin()) = 7722ms
Timer(access all) = 0ms
10000000000 14999950000
mikes@seymour-desktop:~$ g++-4.6.1 -std=c++0x -O3 test.cpp
mikes@seymour-desktop:~$ ./a.out
Timer(insert) = 16ms
Timer(remove half) = 2ms
Timer(access begin()) = 0ms
Timer(access all) = 1ms
10000000000 14999950000
通过使用 boost::unordered_set
,我也获得了类似的快速结果,所以如果你无法更新编译器,这是一个选项。
相关文章:
- CMake项目Boost库错误:Boost/config/compiler/gcc.hpp:165:10:致命错误:cs
- 奇怪的结构&GCC&clang(void*返回类型)
- GCC本机矩阵运算库
- PowerPC ppc64le上的Gcc Woverloaded虚拟错误
- gcc和c++17的过载解析失败
- 数据成员SFINAE的C++17测试:gcc vs clang
- 为什么我无法更改"set<set>"循环中的值<int>
- GCC对可能有效的代码抛出init list生存期警告
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 使用 GCC 卸载的 OpenMP 卸载失败,并出现"Ptx assembly aborted due to errors"
- 为什么与常规GCC不同,即使有"学究性错误",MinGW-GCC也能容忍丢失的返回类型
- 使用gcc从静态链接的文件中查找可选符号
- 普通环路未使用gcc 4.8.5自动矢量化
- 对于set上的循环-获取next元素迭代器
- 有了gcc,是否可以链接库,但前提是它存在
- 在clang++预处理器中确定gcc工具链版本
- 为什么 gcc 编译这个而 msvc 没有
- 为什么lambda在clang上崩溃而不是在gcc上崩溃
- 我可以检测和更改 gcc/g++ 中结构的当前数据对齐设置吗?
- 为什么GCC中std::set的推导失败