简体   繁体   English

std :: vector reserve()和push_back()比resize()和数组索引更快,为什么?

[英]std::vector reserve() and push_back() is faster than resize() and array index, why?

I was doing a quick performance test on a block of code 我正在对一段代码进行快速性能测试

void ConvertToFloat( const std::vector< short >& audioBlock, 
                     std::vector< float >& out )
{
    const float rcpShortMax = 1.0f / (float)SHRT_MAX;
    out.resize( audioBlock.size() );
    for( size_t i = 0; i < audioBlock.size(); i++ )
    {
        out[i]  = (float)audioBlock[i] * rcpShortMax;
    }
}

I was happy with the speed up over the original very naive implementation it takes just over 1 msec to process 65536 audio samples. 我很高兴原来非常天真的实现速度超过1毫秒来处理65536个音频样本。

However just for fun I tried the following 然而,为了好玩,我尝试了以下

void ConvertToFloat( const std::vector< short >& audioBlock, 
                     std::vector< float >& out )
{
    const float rcpShortMax = 1.0f / (float)SHRT_MAX;
    out.reserve( audioBlock.size() );
    for( size_t i = 0; i < audioBlock.size(); i++ )
    {
        out.push_back( (float)audioBlock[i] * rcpShortMax );
    }
}

Now I fully expected this to give exactly the same performance as the original code. 现在我完全希望它能提供与原始代码完全相同的性能。 However suddenly the loop is now taking 900usec (ie it's 100usec faster than the other implementation). 然而,突然循环现在正在使用900usec(即它比其他实现快100usec)。

Can anyone explain why this would give better performance? 谁能解释为什么这会带来更好的表现? Does resize() initialize the newly allocated vector where reserve just allocates but does not construct? resize()是否初始化新​​分配的向量,其中reserve只分配但不构造? This is the only thing I can think of. 这是我唯一能想到的。

PS this was tested on a single core 2Ghz AMD Turion 64 ML-37. PS这是在单核2Ghz AMD炫龙64 ML-37上测试的。

Does resize initialize the newly allocated vector where reserve just allocates but does not construct? resize是否初始化新​​分配的向量,其中reserve只分配但不构造?

Yes. 是。

Resize() 调整()

Modifies the container so that it has exactly n elements, inserting elements at the end or erasing elements from the end if necessary. 修改容器,使其具有正好n个元素,在末尾插入元素或在必要时从末尾删除元素。 If any elements are inserted, they are copies of t. 如果插入了任何元素,则它们是t的副本。 If n > a.size() , this expression is equivalent to a.insert(a.end(), n - size(), t) . 如果n > a.size() ,则此表达式等效于a.insert(a.end(), n - size(), t) If n < a.size() , it is equivalent to a.erase(a.begin() + n, a.end()) . 如果n < a.size() ,则相当于a.erase(a.begin() + n, a.end())

Reserve() 保留()

If n is less than or equal to capacity() , this call has no effect. 如果n小于或等于capacity() ,则此调用无效。 Otherwise, it is a request for allocation of additional memory. 否则,它是分配额外内存的请求。 If the request is successful, then capacity() is greater than or equal to n; 如果请求成功,则capacity()大于或等于n; otherwise, capacity() is unchanged. 否则, capacity()不变。 In either case, size() is unchanged. 在任何一种情况下, size()都保持不变。

Memory will be reallocated automatically if more than capacity() - size() elements are inserted into the vector. 如果向量中插入了多个capacity() - size()元素,则会自动重新分配内存。 Reallocation does not change size() , nor does it change the values of any elements of the vector. 重新分配不会更改size() ,也不会更改向量的任何元素的值。 It does, however, increase capacity() 但它确实增加了capacity()

Reserve causes a reallocation manually. 保留会导致手动重新分配。 The main reason for using reserve() is efficiency: if you know the capacity to which your vector must eventually grow, then it is usually more efficient to allocate that memory all at once rather than relying on the automatic reallocation scheme. 使用reserve()主要原因是效率:如果您知道向量必须最终增长的容量,那么一次分配该内存通常更有效,而不是依赖于自动重新分配方案。

First code writes to out[i] which boils down to begin() + i (ie. an addition). 第一个代码写入out[i] ,其归结为begin() + i (即添加)。 Second code uses push_back , which probably writes immediately to a known pointer equivalent to end() (ie. no addition). 第二个代码使用push_back ,它可能立即写入一个等同于end()的已知指针(即没有添加)。 You could probably make the first run as fast as the second by using iterators rather than integer indexing. 您可以通过使用迭代器而不是整数索引来使第一次运行与第二次运行一样快。

Edit: also to clarify some other comments: the vector contains floats, and constructing a float is effectively a no-op (the same way declaring "float f;" does not emit code, only tells the compiler to save room for a float on the stack). 编辑:也澄清一些其他的注释:向量包含浮点数,构造一个浮点数实际上是一个无操作(同样的方式声明“浮点数f;”不发出代码,只告诉编译器为浮点数节省空间堆栈)。 So I think that any performance difference between resize() and reserve() for a vector of floats is not to do with construction. 所以我认为浮点数向量的resize()reserve()之间的任何性能差异都与构造无关。

out.resize( audioBlock.size() );

Since out 's size (= 0) is lesser than audioBlock.size() , additional elements are created and appended to the end of the out . 由于out的大小(= 0)小于audioBlock.size() ,因此会创建其他元素并将其附加到out的末尾。 This creates the new elements by calling their default constructor. 这通过调用它们的默认构造函数来创建新元素。

Reserve only allocates the memory. 保留仅分配内存。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM