Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 标准::向量<;标准::向量<;无符号字符>&燃气轮机;或std::deque<;标准::向量<;无符号字符>>;?_C++_Optimization_Vector_Memory Management_Deque - Fatal编程技术网

C++ 标准::向量<;标准::向量<;无符号字符>&燃气轮机;或std::deque<;标准::向量<;无符号字符>>;?

C++ 标准::向量<;标准::向量<;无符号字符>&燃气轮机;或std::deque<;标准::向量<;无符号字符>>;?,c++,optimization,vector,memory-management,deque,C++,Optimization,Vector,Memory Management,Deque,我有一个现有的算法,如果可能的话,我需要对它进行轻微的优化。目前,在这个算法中进行大量修改是不可取的。该算法适用于std::vector的实例。看起来是这样的: typedef std::vector<unsigned char> internal_vector_t; std::vector< internal_vector_t > internal_vectors; while (fetching lots of records) { internal_vec

我有一个现有的算法,如果可能的话,我需要对它进行轻微的优化。目前,在这个算法中进行大量修改是不可取的。该算法适用于
std::vector
的实例。看起来是这样的:

typedef std::vector<unsigned char> internal_vector_t;
std::vector< internal_vector_t > internal_vectors; 

while (fetching lots of records) {
   internal_vector_t tmp;
   // reads 1Mb of chars in tmp...
   internal_vectors.push_back(tmp);
   // some more work
}

// use this internal_vectors
据我所知,
std::deque
不需要重新定位曾经分配的位置。在这种情况下,
std::deque
将在推送时减少分配和复制,这是对的吗


更新:
1) 根据MSVC9,进行此类优化(Swapoptimization-)。GCC4.3可能不会进行这种类型的优化

2) 我分析了使用
std::deque
的算法版本,发现它的性能更好

3) 我还利用了作者建议的使用
swap
。使用此选项可以提高性能:

   internal_vector_t tmp;
   internal_vectors.push_back(empty);
   tmp.swap(internal_vectors.back());

你在索引外向量吗?如果没有,那么
std::list

每次在
内部向量中插入
内部向量时,它都会复制
内部向量。无论您使用的是
vector
还是
deque
,这都是正确的。标准容器始终制作要插入的对象的副本

您可以通过插入一个空的
internal\u vector\t
,然后
swap
将插入对象的内容与您真正想要插入的对象交换,来消除复制

在插入过程中,向量有时会因空间不足而需要调整自身大小,这将导致再次复制对象。只要始终在开头或结尾插入,deque就会消除这种情况

编辑:我上面给出的建议可以用这些代码更改来总结。这段代码应该避免所有大向量的复制

typedef std::vector<unsigned char> internal_vector_t;
std::deque< internal_vector_t > internal_vectors; 
internal_vector_t empty;

while (fetching lots of records) {
   internal_vector_t tmp;
   // reads 1Mb of chars in tmp...
   internal_vectors.push_back(empty);
   tmp.swap(internal_vectors.back());
   // some more work
}
typedef std::vector internal\u vector\t;
std::deque<内部向量>内部向量;
内部向量为空;
while(获取大量记录){
内部向量tmp;
//在tmp中读取1Mb字符。。。
内部向量。推回(空);
swap(internal_vectors.back());
//还有工作吗
}

根据实施情况,出列可能更有效。与向量不同,出列不能保证连续存储,因此可以分配几个单独的内存块。因此,它可以在不移动已添加元素的情况下分配更多内存。您应该尝试一下并测量其影响。

std::deque
不连续存储元素,而是将其存储分解为一系列大小恒定的“块”。这意味着当一个
std::deque
的容量用完时,它只需要分配一个大小不变的新块,而不需要重新分配它的整个内部缓冲区并移动它的所有现有元素

另一方面,std::vector确实维护连续存储,因此当它的容量耗尽并重新分配时,它确实需要移动所有现有元素—这可能会很昂贵

std::vector
对其重新分配方案非常“聪明”,根据几何级数分块分配(通常将容量加倍或增加1.5倍等)。这意味着重新分配并不经常发生

在这种情况下,
std::deque
可能更有效,因为当重新分配发生时,它所做的工作更少。和往常一样,你必须进行基准测试才能得到真实的数字

您的代码可能会在其他方面得到进一步改进。似乎在
循环的每次迭代中,您都在创建一个新的
内部向量\u t tmp
。在循环之外声明它可能更有效,只需在每次迭代时将其存储起来。每次调用
internal\u vectors时,您也在复制整个
tmp
向量。push\u back(tmp)
-您可以通过
internal\u vectors移动
tmp
向量来改进这一点。push\u back(std::move(tmp))
-这将只复制几个指针


希望这能有所帮助。

MSVC9为其标准容器实现了一种称为“Swapimization”的功能。这是一个较弱的移动语义版本。调整外部向量的大小时,它不会复制内部向量


不过,您最好只需将编译器升级到MSVC10或GCC(我认为是4.5),这将为您提供移动语义,从而使此类操作更加高效。当然,
std::deque
可能仍然是更智能的容器,但是移动语义在很多地方对性能有益。

您使用的是
insert
还是
push_back
?代码说的是插入文本,这两种方法的成本对于一个向量来说是完全不同的。显然,当它的容量用完时,它必须分配更多的RAM。它是基于增量值来实现的。增量和初始容量都应可根据需要设置。增量值越高,每次用完时分配的内存就越多。只要
reserve()
一大块(2048?),就可以解决这个问题…我使用
push_back
,在我的question@skwllsp:那么您的代码示例与您的问题无关,我们无法提供可靠的进一步帮助。是的,我在问题中提到了这一点。我认为STD::DEQE,因为我仍然需要访问索引,比如内部向量(10)。@ SKWLLSP,你真的需要随机访问吗?您可能不必遍历列表。只需增加一个计数器,并检查您需要的元素之一是否在该索引处。我希望我正在努力sense@pezcode
你真的需要随机访问吗?
不确定。但遗憾的是,这种算法的重大改变不是一种选择。实际上,我主要感兴趣的是优化这一点:
Occa
typedef std::vector<unsigned char> internal_vector_t;
std::deque< internal_vector_t > internal_vectors; 
internal_vector_t empty;

while (fetching lots of records) {
   internal_vector_t tmp;
   // reads 1Mb of chars in tmp...
   internal_vectors.push_back(empty);
   tmp.swap(internal_vectors.back());
   // some more work
}