12

我想在 VS2010 C++ 下double的索引中存储约 3,000,000 个值。unsigned intstd::tr1:unordered_map<unsigned int, double>为此目的使用 a 。不幸的是,当我尝试存储值编号 2^21 时,会引发异常(好像只有 2^21-1 的空间,即某些索引只能使用 20 位)。我在存储值之前尝试过rehash,这也不起作用。

最后我得到了一些非常基本的测试程序(它甚至表现出一些不同的行为,但无论如何):

    std::tr1::unordered_map<unsigned int, float> mapOut;
    //mapOut.rehash(SOMESIZE);
    for (unsigned int i=0; i<3000000; i++)
    {
        if (i%1000==0) std::cout << i << std::endl;
        mapOut[i] = 0.0;
    }

我检查的一些案例:

1)如果我根本不重新散列,程序在输出后根据i == 32000(最终2 ^ 15)休息很长时间,然后继续i == 262000(2 ^ 18)。它永远存在(CPU 负载为 100%,内存不增加)。

2)如果我做 a rehash(1000),它会达到i == 65000(2^16) 并永远保持(CPU 负载 100%,内存不增加)。

3) 如果我执行 a rehash(3000000),则循环成功完成,但程序永远不会退出 - 即,显然析构函数存在问题。

那里发生了什么,甚至更重要的是:我该怎么办?!

非常感谢您的帮助!

4

1 回答 1

4

Connect 上的以下错误似乎与您的问题有关:Visual C++: std::unordered_map Destructor Performance in Debug Configuration

同样的问题不仅发生在析构函数中,而且在unordered_map调整大小时也会发生。如果启用了迭代器调试,它似乎与使迭代器无效有关。

他们说它已为 VC11 修复。还列出了几种解决方法,但我还没有尝试过。

解决调试和发布版本的性能问题的一种非常简单的方法是在“配置选项/C/C++/预处理器/预处理器定义”下的项目选项中设置_SECURE_SCL=0和设置,这会完全禁用所有迭代器调试。_HAS_ITERATOR_DEBUGGING=0但是,这也会禁用一些安全检查,因此您需要在自己的代码中更加小心。我相信这两个都是默认的发布版本,所以你不应该在那里改变任何东西。

这似乎与您的示例代码的问题有关。我不确定原来的问题,因为你没有说抛出了什么异常。

于 2011-07-28T13:55:22.550 回答