条件不变的if语句会使我的C ++代码变慢吗?

问题描述 投票:0回答:2

我正在解决一个耦合常微分方程的系统,我希望在程序运行之间更改要集成的函数。到目前为止,我只需要注释和取消注释三个return语句即可在不同的功能之间进行切换,如下所示:

arma::vec acceleration(arma::vec u, double t)
{   /*
    The current acceleration of the system.
    */

    // return acceleration_1(u);
    // return acceleration_2(u);
    return acceleration_3(u);
}

acceleration被调用了很多次,我想使代码高效,但是我也想更改要与输入参数集成的函数,而不是通过输入代码的深度来进行注释和取消-评论不同的陈述。

[如果我要发送一个参数,比如说choice,它只能是{1, 2, 3}之一,并且choice在程序运行期间永不改变,if语句是否会使我的程序变慢?示例:

arma::vec acceleration(arma::vec u, double t, int choice)
{   /*
    The current acceleration of the system.
    */

    if (choice == 1)
    {
        return acceleration_1(u);

    }

    else if (choice == 2)
    {
        return acceleration_2(u);

    }

    else if (choice == 3)
    {
        return acceleration_3(u);

    }
}

switch语句是否更适合(更快)用于此目的?是否有其他选择不会降低代码速度?

编辑:accelerationacceleration_x是成员函数,这些成员函数使使用函数指针的替代解决方案变得困难。

c++ optimization scientific-computing
2个回答
0
投票

答案取决于情况。

您的程序已编译并在CPU上运行。您没有提及您的项目针对的是哪种CPU体系结构,但是大多数现代CPU使用分支预测,当条件在运行时可能发生变化时,这有助于加快朴素条件检查的速度。

即使就您而言,如您所说,选择变量在程序生命周期中也不会改变,如果没有分支预测,编译器和CPU也就没有太多机会避免每次在您指示时进行检查源代码。它是一个运行时变量,对于C ++,没有适当的结构可帮助编译器或CPU知道何时更改。他们可能会使用巧妙的启发式方法,例如用调用分派(函数调用)替换许多if语句,但是如果您执行以下操作,那将是相同的:

arma::vec (*chosen_acceleration_proc)(arma::vec, double);

arma::vec acceleration(arma::vec u, double t)
{
    return chosen_acceleration_proc(u);
}

您可以在运行时切换所选过程的位置:

chosen_acceleration_proc = acceleration_1; /// For example

如果编译器没有使用inline您不同的加速过程,那么acceleration过程的唯一额外费用就是调用chosen_acceleration_proc。现在,实际选择的加速过程的成本可能远远超过调用它的成本。同样,内联将没有太大好处,只要编译器可以自行决定内联而不是您自己决定(C和C ++中的inline关键字不会强制编译器内联过程)。

您必须分析已编译的程序,以查看此类分发的成本是可忽略的还是巨大的。

返回分支预测,对于具有分支预测的CPU,在进行相同选择一定次数后,CPU将“学习”:

arma::vec acceleration(arma::vec u, double t) {
    switch(acceleration_proc_id) {
        case 1: return acceleration_1(u, t);
        case 2: return acceleration_2(u, t);
        /// etc
    }
}

......的意思是,当您将acceleration_proc_id设置为某个选定值时,一段时间后,CPU只会假设它将保持该状态,并预取并推测执行指令,就好像该选择是给定的一样。有关分支预测及其帮助或失败的更多信息,请参见this most excellent answer

总而言之,CPU可以运行的最佳代码根本就是没有代码-如果您需要在运行时进行切换或调用实际的,非内联的过程,那么成本就在上面,而不是使用预处理器或常数表达式,以确定在编译程序时要使用哪个加速功能。

您最终需要分析使用switch的程序(它可能比过程指针更快,因为C ++需要switch中的常量值-编译器可能会生成CPU优化的代码)与使用过程指针。概要分析将确定CPU大部分时间都花在哪里。如果经过分析后得出结论,与实际计算加速度相比,在运行时能够决定一次加速过程的成本可以忽略不计,那么只需编写您可以编写的最具可读性,最短和最简单的代码,剩下的就交给编译器-这就是它的工作。


-1
投票

两种方法的效率几乎相等。使用哪种方法应该没有区别

© www.soinside.com 2019 - 2024. All rights reserved.