Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fast copy of `std::vector<std::uint8_t>`

Tags:

I have an std::vector<std::uint8_t>, which needs to be duplicated. This is done simply by calling the copy constructor.

My profiling results show, that the Microsoft Visual C++ (msvc100) implementation, uses std::uninitialized_copy internally. This copies every element one-by-one. In this case, a more optimised copy can be done by copying entire blocks of memory at once (like memcpy may do).

In other words, this could be a significant optimization. Is there a way to force the vector to use such an optimised method?

Note: I have tried using std::basic_string<std::uint8_t>, and it does perform better, but it has other issues.

like image 468
Ruud Avatar asked Apr 12 '13 06:04

Ruud


People also ask

Is std :: vector fast?

A std::vector can never be faster than an array, as it has (a pointer to the first element of) an array as one of its data members. But the difference in run-time speed is slim and absent in any non-trivial program. One reason for this myth to persist, are examples that compare raw arrays with mis-used std::vectors.

Does STD vector copy?

std:: copy is inbuilt to copy the elements from one vector to another.

Does vector do a deep copy?

At the time of declaration of vector, passing an old initialized vector copies the elements of the passed vector into the newly declared vector. They are deeply copied.

Is std :: copy a deep copy?

5) std::copy() function And yes, it does a deep copy.


1 Answers

This answer is not specific to the msvc100.

If you use the copy constructor like in

std::vector<uint8_t> newVect(otherVect); 

the otherVect's allocator object has to be copied (and used) as well, which needs more efforts to get it performant in the STL implementation.

If you just want to copy the contents of otherVect, use

std::vector<uint8_t> newVect(otherVect.begin(), otherVect.end()); 

which uses the default allocator for newVect.

Another possibility is

std::vector<uint8_t> newVect; nevVect.assign(otherVect.begin(), otherVect.end()); 

All of them (including the copy constuctor when otherVect uses the default allocator) should boil down to a memmove/memcpy in a good STL implementation in this case. Take care, that otherVect has exactly the same element type (not e.g. 'char' or 'int8_t') as newVect.

Using the container's method is generally more performant than using generic algorithms, so a combination of vector::resize() and std::copy() or even memmove()/memcpy() would be a work-around, if the vendor didn't optimize the container sufficiently.

like image 58
Jacob Avatar answered Oct 06 '22 14:10

Jacob