Смущен тем, что gprof выводит слишком много вызовов?

Я только начал использовать gprof для оптимизации своего медленного кода. Меня смущает один вывод, и я надеюсь, что вы можете мне помочь.

Вот:

                0.01    0.46     500/500         System::Update() [2]
[3]     96.2    0.01    0.46     500         Verlet::Advance() [3]
                0.02    0.19   61000/61122       CalculateAcceleration(std::vector<Particle, std::allocator<Particle> > const&, int) [4]
                0.00    0.06  183000/244127      Vector3D::Vector3D() [8]
                0.00    0.06  305000/676956      Vector3D::Vector3D(Vector3D const&) [6]
                0.00    0.03  122000/122000      Particle::SetPosition(Vector3D const&) [18]
                0.00    0.03  122000/122000      Particle::SetVelocity(Vector3D const&) [19]
                0.02    0.01  183000/183000      Vector3D::LinearCombine(double, Vector3D, double) [23]
                0.00    0.03  549000/921083      Vector3D::~Vector3D() [14]
                0.00    0.00  122000/364484      Vector3D::AddToVector(Vector3D) [30]
                0.00    0.00   61000/182242      std::pow(double, int) [44]
                0.00    0.00   61000/303484      Vector3D::ScalarMultVector(double) [51]
                0.00    0.00   61500/7579826     std::vector<Particle, std::allocator<Particle> >::size() const [25]
                0.00    0.00  366000/366122      std::vector<Particle, std::allocator<Particle> >::operator[](unsigned int) [127]
                0.00    0.00  122000/365606      Particle::GetPosition() const [128]

Я запускаю функцию 500 раз, а цикл for имеет размер 122, поэтому 61 ​​000 соответствует одному выполнению за прогон, 122 000 — 2, 183 000 — 3, 244 000 — 4 и 305 000 — 5. Вот цикл:

    void Advance() {

        for(int i = 0; i < (int)Particles.size(); i++) {

            const Vector3D& CurrentR_NMinus1 = Particles[i].GetPosition();
            const Vector3D& CurrentR_N = Particles1[i].GetPosition();
            const Vector3D& CurrentA_N = CalculateAcceleration(Particles1,i);

            // Calculate R_N+1

            Vector3D CurrentR_NPlus1;
            CurrentR_NPlus1.AddToVector(CurrentR_N);
            CurrentR_NPlus1.LinearCombine(2, CurrentR_NMinus1, -1);
            CurrentR_NPlus1.LinearCombine(1, CurrentA_N, pow(StepSize,2));

            // Calculate V_N

            Vector3D CurrentV_N;
            CurrentV_N.AddToVector(CurrentR_NPlus1);
            CurrentV_N.LinearCombine(1,CurrentR_NMinus1,-1);
            CurrentV_N.ScalarMultVector(1/(2*StepSize));

            // Update

            Particles[i].SetPosition(CurrentR_N);
            Particles[i].SetVelocity(CurrentV_N);
            t0 += StepSize;

            Particles1[i].SetPosition(CurrentR_NPlus1);
            Particles1[i].SetVelocity(Vector3D());
            t1 += StepSize;

        }

    }

Все записи мне понятны, кроме одной: Vector3D(Vector3D const&) вызывается, по-видимому, 5 раз. Но этого нигде в коде нет! Его дети, конечно, называют это, но я думал, что у них есть своя запись в списке gprof. Где ошибка в моем мышлении? Это как-то связано с тем, что Particles[] является вектором Vector3D?

Извините, если это очевидный вопрос - я только начал использовать gprof, и я тоже новичок в C++. Однако мне не удалось найти ответы в Интернете, поэтому я надеюсь, что вы можете мне помочь.

Спасибо вам большое за ваше время!


person noctilux    schedule 25.03.2014    source источник


Ответы (1)


Это copy constructor для объектов типа класса Vector3D. Один из случаев, когда вы неявно вызываете конструктор копирования, — это когда вы передаете существующий экземпляр по значению в качестве аргумента функции. Я предполагаю, что это происходит при вызовах AddToVector и SetPosition и SetVelocity, как я указал в комментариях ниже, всего 5 вызовов. Вам может быть любопытно, почему copy constructor не вызывается, когда вы вызываете SetVelocity(Vector3D()), это лучше всего объяснить, если вы хотите знать, прочитав объяснение здесь:

Правильное использование ссылок rvalue в качестве параметров

const Vector3D& CurrentR_NMinus1 = Particles[i].GetPosition();
const Vector3D& CurrentR_N = Particles1[i].GetPosition();
const Vector3D& CurrentA_N = CalculateAcceleration(Particles1,i);

// Calculate R_N+1

Vector3D CurrentR_NPlus1;
CurrentR_NPlus1.AddToVector(CurrentR_N);          // copy constructor called
CurrentR_NPlus1.LinearCombine(2, CurrentR_NMinus1, -1);
CurrentR_NPlus1.LinearCombine(1, CurrentA_N, pow(StepSize,2));

// Calculate V_N

Vector3D CurrentV_N;
CurrentV_N.AddToVector(CurrentR_NPlus1);          // copy constructor called
CurrentV_N.LinearCombine(1,CurrentR_NMinus1,-1);  
CurrentV_N.ScalarMultVector(1/(2*StepSize));

// Update

Particles[i].SetPosition(CurrentR_N);             // copy constructor called
Particles[i].SetVelocity(CurrentV_N);             // copy constructor called
t0 += StepSize;

Particles1[i].SetPosition(CurrentR_NPlus1);       // copy constructor called
Particles1[i].SetVelocity(Vector3D());
t1 += StepSize;
person amdn    schedule 25.03.2014
comment
Вы абсолютно правы. Оказывается, я забыл сделать эти функции const Vector3D& ... Думаю, мне еще нужно привыкнуть к этому, исходя из Java. Огромное спасибо, что заметили мою ошибку и так быстро ответили! - person noctilux; 26.03.2014