繁体   English   中英

为什么std :: vector <uint8_t> :: insert使用MSVC 2015编译器的速度比std :: copy快5倍?

[英]Why std::vector<uint8_t>::insert works 5 times faster than std::copy with MSVC 2015 compiler?

我有一个微不足道的功能,它将一个字节块复制到std :: vector:

std::vector<uint8_t> v;

void Write(const uint8_t * buffer, size_t count)
{
    //std::copy(buffer, buffer + count, std::back_inserter(v));

    v.insert(v.end(), buffer, buffer + count);
}

v.reserve(<buffer size>);
v.resize(0);

Write(<some buffer>, <buffer size>);

如果我使用std::vector<uint8_t>::insert它的速度比我使用std::copy速度快5倍。

我尝试使用启用和禁用优化的MSVC 2015编译此代码,并得到相同的结果。

似乎std::copystd::back_inserter实现有些奇怪。

标准库实现的编写考虑了性能,但是只有在优化打开时才能实现性能。

 //This reduces the performance dramatically if the optimization is switched off. 

试图在优化关闭的情况下测量功能性能就像问自己,如果宇宙中没有质量,引力定律是否仍然成立,那毫无意义。

v.insert的调用正在调用容器的成员函数。 成员函数知道容器的实现方式,因此它可以执行更通用的算法无法执行的操作。 特别是,在将随机访问迭代器指定的值范围插入向量中时,该实现知道要添加多少个元素,因此它可以一次调整内部存储的大小,然后只需复制这些元素即可。

另一方面,使用insert-iterator调用std::copy时,必须为每个元素调用insert 它不能预分配,因为std::copy使用序列而不是容器; 它不知道如何调整容器的大小。 因此,对于向向量的大插入,每次向量满时需要重新调整内部存储器的大小,并且需要重新插入。 该重新分配的开销是摊销的固定时间,但是该常数比仅进行一次调整大小时的常数大得多。

通过调用reserve (我忽略了,@ ChrisDrew,我忽略了它),重新分配的开销并不那么重要。 但是insert的实现知道要复制多少个值,并且知道这些值在内存中是连续的(因为迭代器是指针),并且知道这些值是可微复制的,因此将使用std::memcpy一次炸掉所有的碎片。 对于std::copy ,都不适用; 后面的插入程序必须检查是否需要重新分配,并且无法优化代码,因此您最终会得到一个循环,该循环一次复制一个元素,并检查为每个元素分配的空间的结尾。 这比普通的std::memcpy要贵得多。

通常,算法对所访问的数据结构的内部了解越多,则速度越快。 STL算法是通用的,与容器特定算法相比,这种通用的开销可能会更大。

通过std::vector的良好实现, v.insert(v.end(), buffer, buffer + count); 可能实现为:

size_t count = last-first;
resize(size() + count);
memcpy(data+offset, first, count);

另一方面std::copy(buffer, buffer + count, std::back_inserter(v))将实现为:

while ( first != last )
{
   *output++ = *first++;
}

等效于:

while ( first != last )
{
   v.push_back( *first++ );
}

或(大致):

while ( first != last )
{
   // push_back should be slightly more efficient than this
   v.resize(v.size() + 1);
   v.back() = *first++;
}

从理论上讲,编译器可以将以上内容优化为一个memcpy ,但最好的情况是,您最多可以内联这些方法,这样就不会产生函数调用开销,但每次仍将写入一个字节,而memcpy通常将使用向量指令一次复制多个字节。

暂无
暂无

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

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