优化C代码

时间:2013-11-20 14:15:09

标签: c optimization if-statement

我有以下代码

    void Fun2()
    {
        if(X<=A)
            X=ceil(M*1.0/A*X);
        else
            X=M*1.0/(M-A)*(M-X);
    }

我想使用C99快速编程,考虑以下注释。

  1. XA是32位变量,我将其声明为uint64_t,而Mstatic const uint64_t

  2. 此函数由另一个函数调用,A的值每n次调用一次更改为新值。

  3. 执行时需要优化,CPU是Core i3,OS是windows 7

  4. 我想实现的数学模型是

    F=ceil(Max/A*X) if x<=A
    
    F=floor(M/(M-A)*(M-X)) if x>A
    

    为了清晰而没有混淆我以前的帖子是 我有以下代码

    void Fun2()
    {
        if(X0<=A)
            X0=ceil(Max1*X0);
        else
            X0=Max2*(Max-X0);
    }
    

    我想使用C99快速编程,考虑以下注释。

    1. X0,A,Max1和Max2是32位变量,我将它们声明为uint64_t,而Max则表示为静态const uint64_t。

    2. 此函数由另一个函数调用,Max1,A,Max2的值每n次调用后更改为随机值。

    3. 我在Windows 7和codeblocks软件中工作

    4. 由于

4 个答案:

答案 0 :(得分:3)

在没有特定目标的情况下优化这样的代码是完全没有意义的,也是不可能的。为此,您需要以下知识:

  • 使用了哪个CPU。
  • 使用哪个操作系统(如果有)。
  • 深入了解上述内容,了解更多,或者与为给定编译器端口编写优化器的人一样多的系统。
  • 最重要的是哪种优化:执行速度,RAM使用或程序大小。

在不知道上述情况的情况下,您可以做的唯一一种优化是在算法级别上。发布的代码中没有这样的算法。

因此,在提供更多信息之前,任何人都无法回答您的问题。

答案 1 :(得分:0)

如果“快速方式”意味着快速执行,那么您的第一个更改就是将此功能声明为内联版本,这是C99的一项功能。

inline void Fun2()
{
   ...
   ...
}

我记得GNU CC有一些有趣的宏可能有助于优化这些代码。我认为这不符合C99,但总是很有趣。我的意思是:你的函数有一个if语句。如果您可以提前了解每个分支的可能性,您可以执行以下操作:

if (likely(X0<=A)).....

如果X0可能小于或等于A.或者:

if (unlikely(X0<=A)).....

如果X0不可能小于或等于A。

有了这些信息,编译器将优化比较和跳转,这样最可能的分支将在没有跳转的情况下执行,因此它将在没有分支预测的架构中更快地执行。

可以提高速度的另一件事是使用?:三元运算符,因为两个分支都为同一个变量赋值,如下所示:

inline void Func2()
{
  X0 = (X0>=A)? Max1*X0 : Max2*(Max-X0);
}

BTW:为什么要使用ceil()ceil()用于将二进制数向下舍入为最接近的非整数。如果X0Max1是整数,则结果中不会有小数,因此ceil()不会产生任何影响。

答案 2 :(得分:0)

我认为可以改进的一件事就是不使用浮点数。你的代码主要处理整数,所以你想坚持整数运算。

唯一的浮点数是Max1。如果它总是完整的,它可以是整数。如果没有,您可以用两个整数替换它:Max1*X0 - &gt; X0 * Max1_nom / Max1_denom。如果你计算一次指数/分母,并多次使用,这可以加快速度。

答案 3 :(得分:0)

我将数学模型转换为

Ceil  (M*(X-0) / (A-0))  when A<=X
Floor (M*(X-M) / (A-M))  when A>X

Ceil (A / B) =  Floor((A + (B-1)) / B)

替换为第一个给出:

((M * (X - m0) + c ) / ( A - m0))

,其中

c = A-1; m0 = 0, when A <= X
c = 0; m0 = M,   when A >= X

所有内容都将以整数运算方式执行,但提前计算倒数非常困难;

可能仍然可以使用某种形式的DDA来避免计算迭代之间的划分。

使用临时常量c,m0仅用于统一两个分支的管道,因为下一步是追求并行性。