Самый быстрый способ копирования большого вектора

Есть большой вектор std::vector<unsigned char> Source на 134217728 элементов

И есть пустой std::vector<unsigned char> Copy;

Как быстрее всего и без большого (более 64 Mb) дополнительного расхода памяти скопировать Source в Copy?

Спасибо!


Ответы (2 шт):

Автор решения: Harry

Написать vector<unsigned char> Copy = Source; - это будет реально самый быстрый способ :)

Если очень хочется руками...

vector<unsigned char> Copy;
Copy.resize(Source.size());
memcpy(Copy.data(),Source.data(),sizeof(unsigned char)*Source.size());

Примерно так. Но этот способ годится не для любых типов, но для POD - сработает.

→ Ссылка
Автор решения: AR Hovsepyan

Я немного не согласен с Harry в данном случаи. Во первых разберемся что делает Copy.resize(Source.size());

  1. вызывается vector::size()
  2. чтобы распределить память для такого количества элементов,
  3. инициализировав их значением по умолчанию Дальше memcpy копирует все элементы одного вектора в другой, заодно получая указатели на массив (Copy.data() и Source.data()).

Теперь рассмотрим что делает копирующий конструктор вектора. Этому конструктору известен размер, и ничего не нужно вызывать(хоть и vector::size() встроенная функция, но все же). Если вектор пустой, копирующий конструктор создает неинициализированную область памяти(т.е. нет никаких элементов, а захвачены последовательности байтов) и инициализирует эти поля значениями из элементов другого вектора. Т.е. копирование происходит максимально быстро(быстрее не напишете ни руками, ни другими средствами). И вот доказательство:

class Timer {
    using T = std::chrono::time_point<std::chrono::steady_clock>;
    T t1, t2;
public:
    void start() { t1 = std::chrono::steady_clock::now(); }
    void stop() {
        t2 = std::chrono::steady_clock::now();
        std::cout << '\n' << (t2 - t1).count() << '\n';
    }
};
int main() {  
    std::vector<unsigned char> Source(134217728, 1), Copy;
    Timer t1, t2, t3;
    t1.start();
    vector Copy1 = Source;
    t1.stop();
    // 80249486      

    t2.start();
    Copy.resize(Source.size());
    memcpy(Copy.data(), Source.data(), sizeof(unsigned char) * Source.size());
    t2.stop();
    // 88608380
    return 0;
}

Вообше std::vector написан очень тщательно, и там не найти место, где можно оптимизировать. Единственное, что вы можете сделать, это просто считать копируемый вектор более не нужным и перемещать данные(move конструктор) или менять местами представления векторов применяя std::swap. Так что, даже при том, что memcpy выполняет быстрое копирование, и ответ от Harry является полезным и достоен внимания, я не согласен, что этот способ быстрее.

Можно еще использовать std::array вместо вектора, если удобно использовать его в вашей программе(не всегда же вектор нужно использовать), и тогда копирование будет таким же быстрым, как и для обычных массивов.

→ Ссылка