Конструктор копирования работает быстрее при копировании std :: vector чем std :: copy - PullRequest
0 голосов
/ 23 апреля 2020
#include <iostream>
#include <vector>
#include <chrono>
#include <string.h>

std::vector<int64_t> vec;
static const int64_t N = 100000000;
static const int64_t M = N - 1;

void func1() {
    std::cout << __FUNCTION__ << std::endl;
    std::vector<int64_t> dst;
    dst.resize(M);
    std::copy(vec.begin(), vec.begin() + M, dst.begin());
}

void func2() {
    std::cout << __FUNCTION__ << std::endl;
    std::vector<int64_t> dst;
    dst.resize(M);
    memcpy(&dst[0], &vec[0], M * sizeof(int64_t));
}
void func3() {
    std::cout << __FUNCTION__ << std::endl;
    std::vector<int64_t> dst(vec);
    dst.resize(M);
}

int main(int argc, char* argv[]) {
    vec.resize(N);
    for (int i = 0; i < N; i++) {
        vec[i] = i;
    }

    auto begin = std::chrono::steady_clock::now();
    if (argc == 1) {
        func1();
    } else if (argc == 2) {
        func2();
    } else {
        func3();
    }
    auto end = std::chrono::steady_clock::now();
    std::cout << "Time difference = "
        << std::chrono::duration_cast<std::chrono::microseconds> \
        (end - begin).count()
        << "[µs]" << std::endl;
    return 0;
}

Я думал, что std :: copy может быть немного быстрее, чем конструктор копирования, так как func1() vs func3().

Но оказалось, что func3() имеет лучшую производительность. Почему?

func3 Разница во времени = 658007 [мкс]

func2 Разница во времени = 823092 [мкс]

func1 Разница во времени = 838711 [мкс]

Я также протестировал std :: vector, func1 быстрее, чем func3. SomeStruct включает std::string и

struct A {
    A(int64_t a) : A_(a) {}
    int64_t a_;
};

команда компиляции: g ++ test. cpp -std = c ++ 11 Я запускался несколько раз, и результаты выглядят одинаково.

1 Ответ

4 голосов
/ 23 апреля 2020

Конструктор копирования может копировать содержимое исходного вектора непосредственно во вновь выделенную неинициализированную память, особенно если содержащийся тип имеет тип примитива или POD. Векторные реализации часто оптимизируются для этого. А с другой стороны, вызов resize() должен заполнить вновь выделенное пространство значением по умолчанию (или значением, которое вы указали для resize()), поскольку векторные элементы не могут быть инициализированы. Это, очевидно, занимает дополнительное время. Вот почему func1() и func(2) медленнее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...