64 位计算机上的 STL 矢量大小
stl vector size on 64-bit machines
我有一个将使用数百万个向量的应用程序。
似乎 std::vector 的大多数实现都使用 4 个指针(_First、_Last、_End 和 _Alloc),在 64 位机器上消耗 32 个字节。 对于矢量的大多数"实际"用例,人们可能会使用单个指针和两个"无符号 int"字段分别存储当前大小和分配大小。 忽略支持自定义分配的潜在挑战(而不是假设分配必须通过全局 new &delete 运算符),似乎可以构建一个仅使用 16 个字节(或者最坏的情况是 24 个字节来支持 _Alloc 指针)的符合 STL 的向量类。
在我开始编写代码之前,1)我应该注意任何陷阱吗?2)是否存在开源实现?
你可以完成这样的事情 - 但你不太可能获得那么多。
首先是性能方面。您正在用时间来换取内存消耗。无论您保存什么内存,都必须在每次调用end
时进行加法和乘法(好吧,如果它是一个可以优化sizeof(vector<t>::value_type) == 1
乘法的向量)。请注意,大多数基于向量的手写循环代码在每次循环迭代中都会调用end
。在现代CPU上,这实际上将是一个重大胜利,因为它允许处理器在缓存中保留更多内容;除非内部循环中的那几条额外指令迫使处理器过于频繁地交换指令缓存中的内容)
矢量中的总体内存使用而言,内存节省可能很小,原因如下:
- 内存管理器开销。在大多数内存管理器实现中,来自内存管理器的每个分配(当然需要哪个向量)都会增加 16-24 字节的开销。(假设像
dlmalloc
(UNIX/Linux/等)或RtlHeap
(Windows)) - 过度配置负载。为了实现最后的摊销常量插入和删除,当向量调整大小时,它的大小调整为向量中数据大小的某个倍数。这意味着向量分配的典型内存容量足以满足向量中实际存储的元素数的 1.6 (MSVC++) 或 2 (STLPort, libstdc++) 倍数。
- 对齐限制。如果要将这许多向量放入数组(或其他向量)中,请记住,该向量的第一个成员仍然是指向分配的内存块的指针。无论如何,此指针通常需要 8 个字节对齐 - 因此您保存的 4 个字节将丢失到数组中的结构填充中。
我现在将使用矢量的简单实现。如果您通过内存探查器运行代码,并发现通过删除这两个指针可以节省大量成本,那么您可能正在实现自己的优化类,该类符合您的性能特征,而不是依赖于内置的矢量实现。(在实现小字符串优化的平台上std::string
此类优化类的示例)
(注意:据我所知,唯一优化Alloc
指针的编译器是VC11,它尚未发布。虽然 Nim 说当前的 libstdc++ 预发布版本也可以这样做......
除非这些向量的内容非常小,否则保存内容的 16 字节与 32 字节之间的差异将只占它们消耗的总内存的一小部分。重新发明这个轮子需要付出很多努力,所以请确保你为所有这些工作获得足够的回报。
顺便说一句,教育也有价值,这样做你会学到很多东西。如果您选择继续,您可以考虑先编写一个测试套件,然后在当前实现上练习它,然后在您发明的实现上练习它。
要回答是否值得付出努力,请找到或编写适合您需求的兼容实现(也许 std::vector 中还有其他您不需要的东西),并将性能与相关平台上的std::vector<your_type>
进行比较。您的建议至少可以提高移动构造函数以及移动赋值运算符的性能:
typedef int32_t v4si __attribute__ ((vector_size (16)));
union
{
v4si data;
struct
{
T* pointer;
uint32_t length;
uint32_t capacity;
} content;
} m_data;
这仅涵盖"理智"T
(除了移动语义)。 https://godbolt.org/g/d5yU3o
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 在C应用程序中运行C++(带有STL)函数
- 为什么使用 P/Invoke 调用 dll 时,某些计算机中的 LoadLibrary 失败?
- 使用2个键的cpp-stl::优先级队列排序不正确
- EvtExportLogneneneba API正在将远程计算机的事件日志保存到远程PC本身.如何将其保存到主机
- 在STL容器中使用模板类
- 用C++中的CPerson(类)类型的对象初始化STL矢量
- 将stl字符串缩小到小于15个字符的容量
- 在为LINUX创建共享库时,如何避免STL的私有/弱副本
- 检查函数返回类型是否与STL容器类型值相同
- STL算法函数在多个一维容器上的使用
- 在STL - C++中按成绩对学生列表进行排序?
- 为什么 STL 容器适配器堆栈中的 top 返回常量引用?
- λ可以适应STL吗?
- 为什么使用 NDK 不能存在不同的 stl 实现?
- 如果我真的真的想从 STL 容器继承,并且我继承构造函数并删除新运算符,会发生什么?
- 使用 char 分隔符解析C++中的字符串,但将可重复的字符保留为每个解析的子字符串 (C++ STL) 中的分隔符
- 在C++中迭代 STL 集时出现奇怪的问题<CStudent>
- 如何在 C++17 STL 并行算法中处理调度?