快速“备份”(复制)自定义对象的大型STL向量

时间:2011-04-20 09:10:23

标签: c++ optimization stl

我正在使用STL向量来存储大量(~10 ^ 6)个自定义对象(sizeof()为这些对象之一提供368个字节)。我的程序结构要求我频繁备份此向量,因为某些步骤中的更改可能需要在某些条件下展开。大概这看起来像

std::vector<myClass> vecA( largeNumber );
std::vector<myClass> vecB;

do
{
  vecB = vecA;

  //do lots of stuff to vecA

  if ( restoreBackup ) { vecA = vecB; }

} while (someCondition)

进行一些分析,复制操作vecB = vecA实际上是一个相当大的瓶颈。我真的需要加快这部分。你会建议哪种策略?

备注:

  • 出于某些原因,我想保留STL矢量结构。
  • 我知道大多数时候vecA中只有一小部分元素得到更新。所以我可以尝试维护这些元素的额外列表,然后通过循环遍历此列表来回复制这些元素。那会是一个合适的策略吗?
  • 问题肯定与this question有关,但是那里提出的解决方案并没有真正帮助。

4 个答案:

答案 0 :(得分:2)

嗯,这不是一件小事,如果你真的只需要使用(和一个)std::vector,我认为你不能避免这种复制。

最好的解决方案是使用Persistant Data Structure

但如果您需要存储多个版本的容器,这将非常有用。

如果您只需要以前的版本..
在我看来,这对我来说很有用的事情就是备份 元素,你会改变。您可以将std::list(或std::vector)与std::pair< int, myClass >一起使用。因此,该对的first将是元素的索引,您正在更改,second - 备份版本。所以,最后,如果你需要恢复备份,你只需要通过这个容器并“恢复”旧数据。

删除/添加元素的情况会更复杂,但不是无法解决的。您将需要更多容器 - 一个用于已删除的元素,一个用于添加的元素,一个用于更改的元素,另一个用于更改的序列。因此,这将使您有机会执行“撤消”步骤。

嗯,这听起来更复杂,有点难以实现(因为所有可能的情况),但会提高性能(会减少副本)。

其他的事情,我想到了 - 您可以先检查容器大小。如果它很小,请制作一份完整的副本。如果它很大 - 执行“选择性备份”或其他任何调用。

请注意,这不是最佳解决方案(我猜),但只是一个想法,我现在得到了(我从来没有需要这样的东西)

希望有所帮助,甚至认为这听起来很复杂,难以实施。

答案 1 :(得分:0)

Kiril建议的替代方法是制作完整副本,但交换(或移动)在“恢复备份”阶段。

即,替换

if ( restoreBackup ) { vecA = vecB; }

if ( restoreBackup ) { std::swap(vecA, vecB); }

然后“恢复备份”部分基本上是免费的,您只需担心(完整)备份本身。当然,这使得任何“部分备份”策略都不可能。

听起来某种“部分”备份方案会更有效率,但提及替代方案绝不会受到伤害。 :)

答案 2 :(得分:0)

如果myClass是POD,并且两个向量都已经是合适的大小,则可以使用memcpy:

memcpy(&dstVec[0], &srcVec[0], sizeof(myClass)*srcVec.size());

答案 3 :(得分:0)

我知道您要保留现有的std :: vector。但是这个问题听起来像是STM (Software Transactional Memory).的问题。可能值得研究。

作为替代方案,也许您可​​以更改修改矢量的代码,以便不会直接修改它,而是生成一个更改列表。批准更改列表后,可以将其应用于向量。

另一种方法是进行更改并构建一个撤消列表,将矢量恢复为原始形式。

所有这一切都比制作整个载体的复制要复杂得多,但是反复复制兆字节的速度会很慢而且无法解决。