矢量push_back over std :: copy

时间:2015-12-29 12:44:49

标签: c++ vector openmp push-back

我有一个函数,它有一个无序集作为参数。由于我使用的是openmp,我将这个无序集转换为vector。我使用std :: copy进行此转换。

//pseudo code
func( std::unorderedset s1)
begin
    vector v1;
    std::copy(s1.begin,s2.end,std::back_inserter(v1.end());
#openmp scope
    for( i = 0 ; i < v1.size(); i++ )
    {
         //accessing v1(i)
    }
end

但是我觉得std :: copy是一项代价高昂的操作。所以我认为,如果我创建一个类变量向量并且我继续填充这个向量,当我更新我的集合时,我可以完全避免这个std :: copy操作。由于向量的push_back操作的时间复杂度是分摊的O(1)。你有什么建议?

2 个答案:

答案 0 :(得分:6)

std::back_insert_iterator来电std::vector::push_back,因此您的提案无法改进。

重要的是,您知道v1预先具有的尺寸,因此请使用该信息并使std::vector仅将其存储分配一次以避免在std::push_back时执行重新分配v1.size() == v1.capacity()

这样做:

std::vector<T> v1;
v1.reserve(s1.size());
std::copy(s1.begin(), s2.end(), std::back_inserter(v1));

或者这个:

std::vector<T> v1(s1.size());
std::copy(s1.begin(), s2.end(), v1.begin());

或者,正如@CoryKramer所建议的,从范围中惯用地构建v1

std::vector<T> v1(s1.begin(), s1.end());

<强>更新

所有三个版本都执行s1.size() T份的副本。但是,当使用10^7 T = int元素在GCC上进行衡量时,它显示std::vector::reserve是最快的方法(由于std::distance,速度是范围构造的两倍具有线性复杂度的ForwardIterator与具有常数std::unordered_set::size相比。当处理较少和非常大的物体时,这种差异会减小,但它仍然存在。

第二种方式比第一种方式略慢,因为初始化元素的价值。

结论:使用std::vector::reserve

答案 1 :(得分:2)

使用此功能可以提高性能:

func( std::unorderedset s1)
begin
    vector v1;
    v1.reserve(s1.size()); // HERE
    std::copy(s1.begin,s2.end,std::back_inserter(v1.end());
#openmp scope
    for( i = 0 ; i < v1.size(); i++ )
    {
         //accessing v1(i)
    }
end

但是,复制对象的成本是您必须处理的问题