Visual Studio 中 unordered_map 的神秘行为
我想在 VS2010 C++ 下的 unsigned int
索引处存储 ~3,000,000 个 double
值。为此,我使用 std::tr1:unordered_map
。不幸的是,当我尝试存储值数字 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)如果我根本不重新散列,则程序在根据 < 输出后需要很长时间的休息code>i == 32000(最终为 2^15),然后继续到 i == 262000
(2^18)。它永远保存在那里(CPU 负载为 100%,内存不增加)。
2) 如果我执行 rehash(1000)
,它会达到 i == 65000
(2^16) 并永远保持(CPU 负载 100%,内存不增加) 。
3)如果我执行rehash(3000000)
,循环成功完成,但程序永远不会退出 - 即,显然析构函数存在一些问题。
那里发生了什么,甚至更重要的是:我该怎么办?!
非常感谢您的帮助!
I want to store ~3,000,000 double
values at unsigned int
indices under VS2010 C++. I use a std::tr1:unordered_map<unsigned int, double>
for this purpose. Unfortunately, when I try to store value number 2^21, an exception is thrown (as if there is only space for 2^21-1 , i.e., some index can only use 20 Bits). I tried to rehash
before storing the values, which did not work either.
Finally I ended up with some very basic test program (which showed even a little different behavior, but anyway):
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;
}
Some cases I checked:
1) If I do not rehash at all, the program takes a long break after the output according to i == 32000
(eventually 2^15) and then continues to i == 262000
(2^18). There it holds forever (with 100% CPU load, memory not increasing).
2) If I do a rehash(1000)
, it comes to i == 65000
(2^16) and holds forever (CPU load 100%, memory not increasing).
3) If I do a rehash(3000000)
, the loop is successfully finished, but the program never exits - i.e., obviously there is some problem with the destructor.
What is going on there, and even more important: What should I do about it?!
Many thanks for your help!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Connect 上的以下错误似乎与您的问题有关:Visual C++: std::unordered_map 调试配置中的析构函数性能
同样的问题不仅发生在析构函数中,而且当
unordered_map
已调整大小。如果启用了迭代器调试,这似乎与使迭代器无效有关。他们说这个问题已经在 VC11 中修复了。还列出了几种解决方法,但我还没有尝试过。
解决调试和发布版本的性能问题的一个非常简单的方法是在“Configuration Options / C/ C++/预处理器/预处理器定义”,它完全禁用所有迭代器调试。然而,这也会禁用一些安全检查,因此您需要在自己的代码中更加小心。我相信这两个都是发布版本下的默认设置,因此您不需要更改任何内容。
这似乎与您的示例代码的问题有关。我不确定原来的问题,因为你没有说抛出了什么异常。
The following bug on Connect appears to be related to your problem: Visual C++: std::unordered_map Destructor Performance in Debug Configuration
The same problem occurs not just in the destructor, but also when the
unordered_map
is resized. It seems to have something to with invalidating iterators if iterator debugging is enabled.They say it has been fixed for VC11. There are also several workarounds listed, but I haven't tried them.
A very simple way to solve the performance problem for both debug and release builds is to set
_SECURE_SCL=0
and_HAS_ITERATOR_DEBUGGING=0
in the project options under "Configuration Options / C/C++ / Preprocessor / Preprocessor definitions", which completely disables all iterator debugging. This does also disable some security checks, however, so you need to be more careful in your own code. I believe both of these are the default under release builds already, so you shouldn't need to change anything there.This appears to be related to the problem of your sample code. I'm not sure about the original problem since you didn't say what exception was thrown.