对 gprof 输出感到困惑——调用太多?

Posted

技术标签:

【中文标题】对 gprof 输出感到困惑——调用太多?【英文标题】:Confused by gprof output -- too many calls? 【发布时间】:2014-03-25 23:01:10 【问题描述】:

我刚刚开始使用 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++ 也是个新手。但是我一直无法在网上找到答案,所以希望您能帮助我。

非常感谢您的宝贵时间!

【问题讨论】:

【参考方案1】:

对于 Vector3D 类类型的对象,这是一个 copy constructor。隐式调用复制构造函数的一种情况是,通过值将现有实例作为参数传递给函数。我的猜测是在对AddToVectorSetPositionSetVelocity 的调用中发生这种情况,正如我在下面的 cmets 中指出的那样,总共有 5 个调用。您可能会好奇为什么在调用 SetVelocity(Vector3D()) 时不调用 copy constructor,如果您想知道,最好通过阅读此处的解释来解释:

Correct usage of rvalue references as parameters

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;

【讨论】:

你是绝对正确的。原来我忘了把这些函数设为“const Vector3D&”……我想我还是得习惯这个,来自Java。感谢一百万发现我的错误并如此迅速地回答!

以上是关于对 gprof 输出感到困惑——调用太多?的主要内容,如果未能解决你的问题,请参考以下文章

对标准输入、标准输出和标准错误感到困惑?

对几何着色器的最大输出感到困惑

Vector2.Normalize 函数,对对角线输出感到困惑

为啥循环摘要在 gprof 的调用图输出中没有任何调用者?

gprof 输出显示不存在的调用图边缘

对WindowBuilder感到困惑[重复]