关于德克<T>的额外间接寻址
About deque<T>'s extra indirection
想知道为什么我的内存访问比我预期的要慢,我最终发现deque
的visualc++实现确实有一个额外的内建层,破坏了我的内存局部性。
。它似乎保存的是T*
数组,而不是T
数组。
是否有另一个实现,我可以使用vc++,没有这个"功能",或者有一些方法(虽然我认为它不太可能)能够避免它在这个实现?
我基本上是在寻找一个在前面也有O(1) push/pop的vector
。
我想我可以实现它自己,但处理allocator
s,这是一个痛苦,它需要一段时间才能得到正确的,所以我宁愿使用以前编写/测试的东西,如果可能的话。
无论出于什么原因,至少在MSVC 2010中,std::deque
实现似乎使用了一个令人难以置信的小块大小(如果我没有弄错的话,最大16字节或1个元素!)。
根据我的经验,这可能会导致非常严重的性能问题,因为基本上数据结构中的每个"块"最终只存储一个元素,这会导致各种额外的开销(时间和内存)。
我不知道为什么这样做。据我所知,设置deque
具有如此小的块大小正是而不是应该做的。
查看gcc stdlib
实现。从内存中,它们使用更大的块大小。
编辑:试图解决其他问题:
-
std::deque
应该有一个额外的间接层。它通常被实现为一个"阻塞"的数据结构——即存储一个"节点"数组,其中每个节点本身就是一个数据元素数组。它不像链表——节点数组从来没有像链表那样"遍历",它总是直接索引(即使在每个块有一个元素的情况下)。 -
当然,你可以滚动你自己的数据结构,在前面保留一些额外的空间。它不会有最坏的
O(1) push/pop front/back
行为,因此它不会满足std::deque
容器的要求。但是如果你不关心这些…
c++标准不允许std::deque
在向前或向后推送时进行重新分配。这些操作总是常数时间。非平摊, 总是。
c++标准没有这样的容器。据我所知,Boost没有(Boost想)。容器库可能;
你所抱怨的间接性实际上是强制的,这是push
/pop
front
/back
的标准要求,引用/指针永远不会无效(除了那些指向已删除元素的引用/指针,显然)。
所以你看到这个要求与任何复杂性要求无关。
这个间接也允许更快(但仍然O(size)) push
front
/back
当没有可用的空间
- 从结构寻址时,MMAP变量的行为很奇怪
- 字节真的是最小可寻址单元吗
- 具有两个间接寻址运算符 (C++) 的函数参数的用途
- 间接寻址运算符如何返回带有运算符重载的指针地址
- 在模板 SFINAE 约束中使用间接寻址级别会导致硬错误
- 指针声明和间接寻址之间的区别
- 仅在使用间接寻址时调用虚函数 — 经典的早期绑定问题?
- 内联lambda是否遭受与函数指针间接寻址相同的延迟
- 动态内存分配、堆、间接寻址、空
- 如何为涉及对象成员、间接寻址和强制转换的排序算法实现lambda函数
- C++错误 C2100:非法间接寻址 - 气泡排序
- 为什么允许引用指向指针的间接寻址
- C++指针和多维数组的双重间接寻址
- C++ 非法间接寻址数组和指针
- 带有数组的c++多级间接寻址
- 关于德克<T>的额外间接寻址
- C++vtables中的双重间接寻址
- 标准如何允许通过空指针进行间接寻址
- 间接寻址需要指针操作数和预期的表达式错误
- 无法解决错误:间接寻址需要指针操作数("int"无效)