簡體   English   中英

為什么引用調用比內聯代碼慢得多?

[英]Why is call by reference so much slower than inline code?

我正在編寫一個帶有少量粒子(通常是 3 個,不超過 5 個)的物理模擬。

在精簡版中,我的代碼結構如下:

#include<iostream>

class Particle{
  double x; // coordinate
  double m; // mass
};


void performStep(Particle &p, double &F_external){
   p.x += -0.2*p.x + F_external/p.m; // boiled down, in reality complex calculation, not important here
}
 
int main(){

 dt = 0.001; // time step, not important

 Particle p1;
 p1.x = 5; // some random number for initialization, in reality more complex but not important here
 p.m = 1;

 Particle p2;
 p2.x = -1; // some random numbersfor initialization, in reality more complex but not important here
 p.m = 2;

 Particle p3;
 p3.x = 0; // some random number for initialization, in reality more complex but not important here
 p.m = 3;

 double F_external = 0; // external forces

 for(unsigned long long int i=0; i < 10000000000; ++i){ // many steps, typically 10e9
    F_external = sin(i*dt);
    performStep(p1, F_external);
    performStep(p2, F_external);
    performStep(p3, F_external);
 }

 std::cout << "p1.x: " << p1.x << std::endl;
 std::cout << "p2.x: " << p2.x << std::endl;
 std::cout << "p3.x: " << p3.x << std::endl;

}

我用clock()確定performStep(p, F_external)調用是我代碼中的瓶頸)。 當我嘗試進行內聯計算時performStep(p1, F_external)替換為p1.x += -0.2*p1.x + F_external/p1.m; 計算突然快了大約 2 倍。 請注意,performStep() 實際上是大約 20 行的大約 60 次基本算術計算,所以如果我只為每個粒子內聯它,代碼就會變得非常臃腫。

為什么會這樣? 我正在使用 MinGW64/g++ 和 -O2 標志進行編譯。 我以為編譯器會優化這些東西?

編輯:

這里是調用的function。 請注意,實際上,我使用幾個不同的外力計算所有三個坐標 x、y、z。 未通過 function 傳遞的變量是SimulationRun的成員。 該算法是一種四階跳躍算法。

void SimulationRun::performLeapfrog_z(const unsigned long long int& i, const double& x, const double& y, double& z, const double& vx, const double& vy, double& vz, const double& qC2U0, 
    const double& U0, const double& m, const double& C4, const double& B2, const double& f_minus, const double& f_z, const double& f_plus, const bool& bool_calculate_xy,
    const double& Find, const double& Fheating) {

    // probing for C4 == 0 and B2 == 0 saves some computation time
    if (C4 == 0) {
        Fz_C4_Be = 0;
    }
    if (B2 == 0 || !bool_calculate_xy) {
        Fz_B2_Be = 0;
    }


    z1 = z + c1 * vz * dt;


    if (C4 != 0 && !bool_calculate_xy) {
        Fz_C4_Be = (-4) * q * C4 * U0 * z1 * z1 * z1;
    }
    else if (C4 != 0 && bool_calculate_xy) {
        Fz_C4_Be = q * C4 * U0 * (-4 * z1 * z1 * z1 + 6 * z1 * (x * x + y * y));
    }
    if (B2 != 0 && bool_calculate_xy) {
        Fz_B2_Be = q * B2 * (-vx * z1 * y + vy * z1 * x);
    }
    acc_z1 = (qC2U0 * (-2) * z1 + Find + Fz_C4_Be + Fz_B2_Be + Fheating) / m;
    vz1 = vz + d1 * acc_z1 * dt;
    z2 = z1 + c2 * vz1 * dt;


    if (C4 != 0 && !bool_calculate_xy) {
        Fz_C4_Be = (-4) * q * C4 * U0 * z2 * z2 * z2;
    }
    else if (C4 != 0 && bool_calculate_xy) {
        Fz_C4_Be = q * C4 * U0 * (-4 * z2 * z2 * z2 + 6 * z2 * (x * x + y * y));
    }
    if (B2 != 0 && bool_calculate_xy) {
        Fz_B2_Be = q * B2 * (-vx * z2 * y + vy * z2 * x);
    }
    acc_z2 = (qC2U0 * (-2) * z2 + +Find + Fz_C4_Be + Fz_B2_Be + Fheating) / m;
    vz2 = vz1 + d2 * acc_z2 * dt;
    z3 = z2 + c3 * vz2 * dt;

    if (C4 != 0 && !bool_calculate_xy) {
        Fz_C4_Be = (-4) * q * C4 * U0 * z3 * z3 * z3;
    }
    else if (C4 != 0 && bool_calculate_xy) {
        Fz_C4_Be = q * C4 * U0 * (-4 * z3 * z3 * z3 + 6 * z3 * (x * x + y * y));
    }
    if (B2 != 0 && bool_calculate_xy) {
        Fz_B2_Be = q * B2 * (-vx * z3 * y + vy * z3 * x);
    }
    acc_z3 = (qC2U0 * (-2) * z3 + Find + Fz_C4_Be + Fz_B2_Be + Fheating) / m;
    vz3 = vz2 + d3 * acc_z3 * dt;

    z = z3 + c4 * vz3 * dt;
    vz = vz3;
}

優化很難,即使對於編譯器也是如此。 以下是一些優化技巧:

  1. 由於您的performStep是熱點,請將其放入 header 文件中(以防您將聲明和定義拆分為 header/source),然后添加inline關鍵字,例如:
// at file xxx.h
inline void performStep(Particle &p, double F_external){
   p.x += -0.2*p.x + F_external/p.m; // boiled down, in reality complex calculation, not important here
}
 
  1. 升級你的編譯器,也許是最新的。
  2. 使用https://godbolt.org/檢查匯編代碼。 在這種情況下,不必要的取消引用是性能的頭痛。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM