我最近写了这篇文章:
How best to store VERY large 2D list of floats in c++? Error-handling?
有人建议我将浮点数的2D列表式结构实现为向量,其他人则说是deque。
从我收集的内容中,矢量需要连续的内存,但因此效率更高。显然,如果可能的话,这将是可取的。
因此,我的问题是基本结构在多长时间内的合理规则是什么...
浮子
2. int
...在你应该从向量切换到双端队列以避免内存问题之前?
e.g。我正在寻找答案,如“大约400万个浮点数或800万个整数,你应该转换......”......如果可能的话。
答案 0 :(得分:4)
嗯,这是两个意见。 C ++标准说(23.1.1 / 2):
当序列中间频繁插入和删除时,应使用
vector
是默认情况下应该使用的序列类型。当大多数插入和删除发生在序列的开头或结尾时,
list
。
deque
是首选的数据结构。
Herb Sutter argues the following(该文章包含他的理由和性能分析):
我想提出一个不同意见的观点:我建议你考虑默认优先使用deque而不是vector,特别是当包含的类型是类或结构而不是内置类型时,除非你真的需要容器的记忆是连续的。
答案 1 :(得分:2)
同样,没有大小限制,高于哪个deque是否比向量更好。在任何一种情况下,内存碎片的含义几乎都是相同的,除非你已经完成了大量的分配/解除分配并且没有足够的连续空间留给大向量。但这种情况非常罕见。请记住,内存空间是每个进程(google for 虚拟内存)。你可以通过在混乱发生之前为矢量分配内存(通过reserve
方法)来解决这个问题。
权衡取决于你想用它做什么。如果结构基本上是不可变的,你只想访问它/通过索引访问覆盖它,那就去矢量。
Deque是指你需要在结尾,开头或中间进行插入时,矢量无法自然处理(除了最后插入)。
Herb Sutter的文章质量很高,但是你会注意到当你在C ++中进行“数字运算”时,你在“普通C ++”书籍中教授的大部分内容都必须加上额外的词汇。谨慎。使用deques时遇到的差的索引性能对您的应用程序可能很重要。在这种情况下,请勿使用deque。
答案 2 :(得分:2)
如果您在开头需要插入,那么请使用deque。
否则,我总是想在vector vs. deque上指出这篇文章(除了James McNellis在这里链接的那篇文章)。 假设使用基于页面的分配的deque的实现,本文对带有&的vector的分配时间(& deallocation time)进行了很好的比较。没有预留()与deque。基本上,使用reserve()使得向量分配时间与deque非常相似。信息丰富,如果您可以提前猜出正确的值,那就很有用。
答案 3 :(得分:1)
有许多因素需要考虑,因此无法给出明确的答案。机器上的内存量,它是多么碎片化,它可能变得多么碎片化等等。我的建议是只选择一个并使用它。如果它导致问题切换。你无论如何都不会遇到这些边缘情况。
如果你真的很担心,那么你可能会实现一种伪PIMPL:
template<typename T>
class VectorDeque
{
private:
enum TYPE { NONE, DEQUE, VECTOR };
std::deque<T> m_d;
std::vector<T> m_v;
TYPE m_type;
...
public:
void resize(size_t n)
{
switch(m_type)
{
case NONE:
try
{
m_v.resize(n);
m_type = VECTOR;
}
catch(std::bad_alloc &ba)
{
m_d.resize(n);
m_type = DEQUE;
}
break;
}
}
};
但这似乎完全矫枉过正。你做过任何基准测试或测试吗?你有理由相信内存分配会失败或者deques会太慢吗?
答案 4 :(得分:1)
您在测试和分析后切换表明您的应用程序比另一个更差。没有“N N Floats或M ints”的普遍答案。
答案 5 :(得分:0)
好吧,关于内存,我可以分享一些经验,可以帮助你决定何时连续的内存块(malloc或std :: vector)可能变得太大:
我使用的应用程序会记录测量数据,大多数是4byte float
,为此,它会分配内部缓冲区来存储数据。这些缓冲区的大小差别很大,但典型的范围可以是数十亿的1-10MB和极少数的> 100MB。缓冲区总是分配有calloc
,即一大块内存。如果缓冲区分配失败,则会记录错误,用户可以选择重试。
缓冲区大小:假设您想要以100Hz记录1000个通道10分钟:4byte x 1000 x 100 x 60x10 == 228 MB(大约)...或100个通道,10Hz 12小时== 41 MB < / p>
我们(几乎)从来没有遇到任何问题,分配40MB缓冲区(大约10万个浮点数)和200-300 MB缓冲区不时失败 - 所有这些都在普通的WinXP / 32bit盒子上,带有4GB RAM。
答案 6 :(得分:0)
鉴于您在创建后没有插入,您可能应该使用普通的旧std::vector
,或者如果碎片确实成为问题,那么自定义向量Sequence实现为向量或指向固定大小数组的指针数组。