vector push_back over std::copy

vector push_back over std::copy

本文关键字:std copy over back push vector      更新时间:2023-10-16

我有一个函数,它有一个无序集作为参数。由于我使用openmp,所以我将这个无序集转换为向量。我使用std::副本进行转换。

//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操作。由于向量的推回运算的时间复杂度被分摊为O(1)。你有什么建议?

std::back_insert_iterator调用std::vector::push_back,所以您的提案没有任何改进。

重要的是,您事先就知道v1的大小,因此请利用该信息并使std::vector只分配其存储一次以避免std::push_backv1.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());

更新:

所有三个版本都执行Ts1.size()份数。然而,当在具有T = int10^7元素的GCC上进行测量时,结果表明std::vector::reserve是最快的方法(因为ForwardIterator的std::distance具有线性复杂度,而std::unordered_set::size具有>常数)。当处理更少和非常大的对象时,这种差异会减少,但它仍然存在。

第二种方法只比第一种稍微慢一点,因为初始化元素的值。

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

您可以使用以下功能来提高性能:

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

然而,复制对象的成本是一个问题,您必须处理它