std::unordered_set如何避免迭代中每个元素上潜在的页面错误
How does an std::unordered_set avoid potential page faults on every element in iteration?
还是这样?
澄清一下:在std::vector
中,如果在迭代期间访问了当前不在缓存到内存中的页面上的元素,则存在页面错误,并且该页面已加载,但随后的k-1
元素保证缓存到内存,其中k
是适合内存页面的元素数。
在我看来,在像std::unordered_set
这样的哈希表数据结构中,在迭代过程中,根本不能保证访问的任何元素的后续元素都会在内存中接近它,这意味着在具有大量元素的生成条件下,迭代过程中访问的每个元素都可能出现页面错误。我错了吗?如果是,std::unordered_set
使用什么方法来防止这种情况发生?
只是好奇。我正在概述我现在计划实施的一个算法,并试图了解它在退化条件下如何在有限的内存和大量元素的情况下预成型,而我对std::unordered_set
如何在引擎盖下工作的不完全了解是一个限制因素。
没有。std::unordered_set
是使用哈希表实现的,带有单独的链接。也就是说,每个bucket都有一个链表,用来存储bucket中的项目。这意味着,当您一个桶接一个桶地迭代时,每次都必须取消引用指向动态内存的指针,并冒着缓存未命中的风险
如果你想要类似的东西,它使用连续内存,从而在迭代时避免页面错误,你可以使用一个带有开放寻址的哈希表。例如,你可以使用线性探测,或者使用杜鹃散列之类的东西。但是您必须自己实现这些,或者使用其他人的非标准容器库。这些类型的映射和集合不能完全以尊重标准映射和集合的迭代器无效要求的方式来完成。
无序和有序的关联容器都必然受到引用内存不连续性的影响。
我写了"必然",因为C++标准坚持认为,只要元素没有从容器中删除,指向关联容器中元素的指针和引用就会保持有效。这使得某些技术无法改进引用的局部性,这将需要移动元素来改进存储器布局。
内存分散不仅(甚至主要)会导致过多的分页。最明显的后果通常是内存缓存利用率降低,这会显著增加运行时间。(显然,过度的交换也会产生巨大的影响,但如果你把我们限制在内存中,无论哈希表引用的位置如何,你都会遇到问题。)
缓存感知算法确实存在,但它们不经常使用有几个原因:
-
优化仅在一些非常特定的用例中有用。
-
在不了解大量被散列的数据的情况下,很难编写一个缓存感知算法。通用库函数可以处理任何数据类型,很少为特定的数据类型提供优化的专业化。
-
标准关联容器的引用稳定性在大量用例中非常有用。
无序列表可以被认为是一个向量(由键的散列键控),具有类似散列元素的链表。
通过无序列表的迭代迭代会迭代向量(共享相同的页面错误模式),然后是链表。如果没有项目共享一个槽,它将具有与向量相同的读取模式。
由于它是无序的,所以这个迭代是数据的随机视图。
- 从矢量中删除元素后出现隔离错误
- 删除映射和分割错误中的一个过去结束元素
- 在 alglib::real_1d_array 中获取元素总和的奇怪错误
- C++ - 将元素按升序插入数组的 SEG 错误
- 使用 <list> (错误 C2760) 打印队列的元素
- C++:使用类在向量中搜索特定元素时,我得到了错误的结果
- 用于查找数组中最大元素的出现次数的代码,给出分段错误
- C++ 将元素分配给映射值时访问错误
- 从加密项目向量中解密任意选择的元素会导致无效的 PKCS #7 块错误
- C++通过别名指针以静默方式将错误的类型分配给数组元素
- Leetcode 540 上的运行时错误.排序数组中的单个元素
- std::我不明白的矢量元素错误
- 如何修复从矢量中删除元素的错误?
- 为什么我在对向量的第二个元素"push_back"中有C3867错误
- 尝试访问 3D 矢量中的元素时出现 Seg 错误
- OpenCV 文件存储 - 错误:元素之间的解析错误 (icvYMLParseValue) 缺失
- 访问range_expression中的嵌套元素会返回不完整的映射(段错误)
- 打印向量元素错误消息
- 数组中的cout元素错误,错误
- 迭代并移除Vector中的元素.错误:Vector迭代器不可递增