初始化向量向量

Posted

技术标签:

【中文标题】初始化向量向量【英文标题】:Initializing vector vector 【发布时间】:2013-07-07 11:54:35 【问题描述】:

我正在使用一个

vector<vector<size_t>> Ar;

结构。结构的内容随时间变化,特别是每个嵌套向量的长度是随机的并且随时间变化。顺序很重要,如果嵌套向量为空,我不能忽略它。我知道嵌套向量(比如 m)和外部向量(比如 n)的最大容量。

我在正确初始化时遇到了一些困难。如果我使用

Ar(n);

没有问题,但我最终得到了内存碎片,因为分配器不知道嵌套向量的大小。如果可能的话,我想避免这种情况,因为我不知道随着我试图处理的数据大小的增加,它会产生什么影响。我尝试通过提前固定嵌套向量的长度来解决碎片以获得紧凑的表示,但我在这样做时遇到了麻烦。我用

Ar(n,vector<size_t>(m));

但这超级慢,而且会大量浪费内存,因为大部分条目都不会被使用。

我已经成功实现了这一点

vector<list<size_t> > Ar(n);

不会出现碎片,但它的运行速度比使用嵌套向量要慢得多。像 Boost::multi_array 这样的固定表示会占用太多空间,原因与上面的第二个初始化相同,并且实现起来会更加困难,因为我需要跟踪有用的条目停止的位置。

有什么建议吗?提前致谢。

【问题讨论】:

为什么您的原始设计的“内存碎片”是个问题?你测量过它并确定它真的是一个瓶颈吗? 我已经测量了虚拟内存的使用情况。这样做有错吗?我应该使用其他工具吗? 我只是看不出你最初的方法有什么特别的问题。如果您有一组不同大小的集合,那么向量的向量似乎是明智的。如果您正在缩小容器并且担心内存,则可以使用交换技巧,否则您已经在每个内部容器中获得了良好的内存局部性...... 【参考方案1】:

在使用典型用例分析代码之前,您不会知道内存碎片是否是一个问题。 除非mn 前面非常小,否则我认为它根本不会成为瓶颈,因为您仍然有大部分顺序内存访问。

如果你想避免它,你可以使用reserve 而不是resize 或使用m 对象进行初始化。它只会分配内存,没有构造不会被使用的对象的开销,提高了初始化速度。

此外,向量的reserveing 容量可能只会消耗虚拟内存,而不是“真实”内存,直到您有效地使用它。

如果你知道内部向量的大小分布,使用平均值作为默认长度,它可以帮助你减少内存的浪费。

无论如何,std::list 是更大的空间浪费,考虑到碎片化,情况更糟。

【讨论】:

感谢您的全面回答。通常,m 至少比 n 大 5 或 10 倍。原因是 m 是最大容量,因为我使用嵌套向量作为对 n 个容器中的 m 个对象进行排序的一种手段,字面意思是鸽巢原则。这意味着一些嵌套向量可能是空的。每次运行算法时,我需要清除和重新填充 Ar 超过 60 次。过去我在嵌套列表方面遇到过一些问题,所以可能因为这次经历而变得偏执。将尝试我正在做的事情,如果有问题,请实施调整大小。 奇怪的是,我没有使用嵌套列表在实际内存中增加......无论如何,使用嵌套向量的实现要快得多,所以如果有的话,我将使用你上面建议的技术之一内存问题变得非常棘手。 当你说你没有内存增量时你的参考是什么?另外,我很确定碎片不会成为问题:要么你的向量相对较小,结束然后不需要调整大小并且会保留它们的第一个分配空间,要么它们很大,然后内存访问有点连续。问题可能是如果您需要经常调整它们的大小,reserve 方法可以避免这个问题而不会浪费太多内存:)【参考方案2】:

也许resize 函数会对您有所帮助。有关详细信息,请参阅here。

【讨论】:

在示例中,行中的条目数是先验已知的。就我而言,我不知道每个嵌套向量将包含多少条目或何时添加它们。把它想象成一个鱼塘问题。您是否建议我每次向嵌套向量添加条目时调整大小? 这不是一个好的解决方案,但是权衡取决于我没有的参数(例如更改的数量和频率)。您可能总是以超过 1 的增量调整大小(各种滞后)

以上是关于初始化向量向量的主要内容,如果未能解决你的问题,请参考以下文章

在定义的位置初始化向量向量 - C++

初始化用户定义的向量的向量

使用 boost assign 初始化具有固定大小的向量的向量

初始化结构向量向量的好方法(每个都有一个初始值)?

C ++ 11向量的向量初始化

在类构造函数上初始化向量