【问题标题】:Why can't I insert 6 million elements in STL set?为什么我不能在 STL 集中插入 600 万个元素?
【发布时间】:2013-03-18 13:10:35
【问题描述】:

我正在尝试在 stl 集中插入超过 650 万个元素(整数)。代码如下:

set<int> s;
cout << s.max_size() << endl;
for(int i = 0; i < T.MULT * T.MAXP; i++) {
    s.insert(a[i]);
}

T.MULT10T.MAXP666013

a 是一个数组 - 静态分配 - (int a[T.MULT * T.MAXP];),其中包含不同的元素。

在大约 460 万个元素之后,s.insert() 引发 bad_alloc 异常。 Windows 7 上可用的资源监视器说我还有 3 GB 可用内存。 我究竟做错了什么?为什么 STL set 不能分配内存?

编辑:这里是完整代码:http://ideone.com/rdrEnt

Edit2:显然插入的元素毕竟可能并不明显,但这应该不是问题。

Edit3:这是代码的简化版本:http://ideone.com/dTp0fZ

【问题讨论】:

  • 任务管理器为您的进程的工作集报告什么?您的代码是编译为 32 位还是 64 位代码?
  • 很可能,您的进程虚拟内存不足。这是什么平台?
  • @JoachimPileborg:不需要std::set 的大块,你只需要足够的节点大小。
  • 这应该可以。可能其他一些代码正在破坏堆。
  • 请显示a short, self-contained, compilable example 并准确说明您正在使用哪些工具(编译器、版本、目标机器、操作系统等)。可能是您程序中的其他东西干扰了此代码。我能够在 OS X 上毫无问题地编译和执行它(在用数字替换 T.MULTT.MAXP 并定义 a 之后)。

标签: c++ stl set max-size


【解决方案1】:

问题实际上在于您为数组 A 静态分配了超过 650 万个元素,这破坏了您的程序堆栈空间。如果您在堆上分配数组,它实际上可以工作。我根据您的描述做了一些代码更改,效果很好。

int *A = new int[T.MULT * T.MAXP];
for (int i= 0; i <  T.MULT * T.MAXP; ++i)
{
    A[i] = i; //for simplicity purpose, your array may have different elem. values
}

set<int> s;
for (int i = 0; i <  T.MULT * T.MAXP; ++i )
{
    s.insert(A[i]);
}

cout << s.size();

set<int>::iterator iter;
int count = 0;
for (iter = s.begin(); iter != s.end(); ++ iter)
{
    cout << *iter << " ";
    count ++;
    if (count == 100)
    {
        cout <<endl;
        count = 0;
    }
}

delete [] A;

return 0;

它在矢量和集合上都工作得很好。它可以在屏幕上打印所有这 660 万个元素。

正如其他帖子所指出的,如果您有兴趣,也可以尝试 STXXL。

【讨论】:

  • 不是全局的、静态声明的数组分配在堆上吗?
  • 你的意思是a是一个全局数组?您可以动态分配数组,然后在需要时将数组作为参数传递,这应该是微不足道的。同时,恕我直言,使用全局变量并不是一个好习惯。
【解决方案2】:

您可能想看看STXXL

【讨论】:

    【解决方案3】:

    虽然我无法直接回答您的问题,但我认为将您的数据存储在 std::vector 中,对其进行排序,然后使用 std::binary_search 来测试该项目的存在会更有效。与 std::vector 相比,std::set 中的存储相对昂贵。那是因为在存储每个元素时会有一些开销。

    例如,您可以这样做。这会对静态数组进行排序。

    std::sort(a,a+(T.MULT*T.MAXP));
    bool existence=std::binary_search(a,a+(T.MULT*T.MAXP),3);
    

    快速简单。

    【讨论】:

    • 别忘了他已经将它存储在一个数组中(stl 算法可以像在向量中一样轻松地对其进行操作)。
    • 确实如此,我假设需要保留静态分配的顺序,但现在我再次考虑它似乎不太可能。
    • 主要问题实际上是 a 是静态分配的,这会破坏堆栈空间,如果 a 是动态分配的,它实际上适用于集合和向量。顺便说一句:当 set 存储每个元素时,“一些开销”是什么?因为它按排序顺序维护元素?
    • 它似乎不太可能导致堆栈损坏。它只有 640 万个整数,大约 25 MB。不?而且我不希望这会撞到堆栈空间。至于集合的每个元素成本,请记住它可能使用红/黑树类型实现。两个指针(左子和右子)和一个颜色标志将是每个元素额外的 17 个字节。哎哟!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-07
    • 1970-01-01
    • 2022-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多