C++ std::vector Reserve() 和 push_back() 比 resize() 和数组索引快,为什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1461276/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:04:17  来源:igfitidea点击:

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

c++optimizationstlvector

提问by Goz

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.

我对原始非常幼稚的实现的速度感到满意,处理 65536 个音频样本只需要 1 毫秒多一点。

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 (i.e. it's 100usec faster than the other implementation).

现在我完全期望这能提供与原始代码完全相同的性能。然而,突然之间,循环现在占用了 900 微秒(即它比其他实现快 100 微秒)。

Can anyone explain why this would give better performance? Does resize()initialize the newly allocated vector where reserve just allocates but does not construct? This is the only thing I can think of.

谁能解释为什么这会提供更好的性能?是否resize()初始化新分配的向量,而reserve 只是分配但不构造?这是我唯一能想到的。

PS this was tested on a single core 2Ghz AMD Turion 64 ML-37.

PS 这是在单核 2Ghz AMD Turion 64 ML-37 上测试的。

回答by sepp2k

Does resize initialize the newly allocated vector where reserve just allocates but does not construct?

resize 是否初始化新​​分配的向量,而reserve 只是分配但不构造?

Yes.

是的。

回答by Satbir

Resize()

调整大小()

Modifies the container so that it has exactly n elements, inserting elements at the end or erasing elements from the end if necessary. If any elements are inserted, they are copies of t. If n > a.size(), this expression is equivalent to a.insert(a.end(), n - size(), t). If n < a.size(), it is equivalent to a.erase(a.begin() + n, a.end()).

修改容器,使其恰好有 n 个元素,如有必要,在末尾插入元素或从末尾删除元素。如果插入任何元素,则它们是 t 的副本。如果n > a.size(),该表达式等价于a.insert(a.end(), n - size(), t)。如果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. Otherwise, it is a request for allocation of additional memory. If the request is successful, then capacity()is greater than or equal to n; otherwise, capacity()is unchanged. In either case, size()is unchanged.

如果 n 小于或等于capacity(),则此调用无效。否则,它是一个分配额外内存的请求。如果请求成功,则capacity()大于等于n;否则,capacity()不变。在任何一种情况下,size()都是不变的。

Memory will be reallocated automatically if more than capacity() - size()elements are inserted into the vector. Reallocation does not change size(), nor does it change the values of any elements of the vector. It does, however, increase capacity()

如果capacity() - size()在向量中插入了多个元素,内存将自动重新分配。重新分配不会改变size(),也不会改变向量的任何元素的值。然而,它确实增加了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 导致手动重新分配。使用的主要原因reserve()是效率:如果您知道向量最终必须增长到的容量,那么一次性分配所有内存通常比依赖自动重新分配方案更有效。

回答by AshleysBrain

First code writes to out[i]which boils down to begin() + i(ie. an addition). Second code uses push_back, which probably writes immediately to a known pointer equivalent to end()(ie. no addition). You could probably make the first run as fast as the second by using iterators rather than integer indexing.

第一个代码写入out[i]归结为begin() + i(即添加)。第二个代码使用push_back,它可能会立即写入一个已知的指针,相当于end()(即没有添加)。通过使用迭代器而不是整数索引,您可能可以使第一次运行与第二次运行一样快。

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). So I think that any performance difference between resize()and reserve()for a vector of floats is not to do with construction.

编辑:还要澄清一些其他评论:向量包含浮点数,并且构造一个浮点数实际上是一个无操作(与声明“float f;”相同的方式不发出代码,只告诉编译器为浮点数节省空间堆栈)。所以我认为,之间的性能差异resize()reserve()对花车的载体是不与施工有关。

回答by aJ.

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. This creates the new elements by calling their default constructor.

由于out的大小 (= 0) 小于audioBlock.size(),因此会创建其他元素并将其附加到out. 这通过调用它们的默认构造函数来创建新元素。

Reserve only allocates the memory.

Reserve 只分配内存。