优化以下代码块

时间:2017-01-04 17:05:07

标签: c performance optimization

考虑以下C代码。描述可以提高性能的三种不同优化(包括它们的名称),它们改进性能的原因以及优化后代码的外观。假设所有变量都在代码序列之前声明并启动/具有一些值。

 condition2 = condition1 | input_flag; 

 for(i=0;i<10000;i++){

   if ( (t1==0) && (t2==0) && (t3==0) ) 
      a = sin(45∗b∗3.14/180);  

   else  
      a = sin(135∗b∗3.14/180);  

   if ( condition2 & COND1 ) 
      DoOneThing(a);

   else if ( condition2 & COND2 ) 
      DoAnotherThing(a); 

   else 
      DoYetAnotherThing(a); 
 } 

我在C中有以下代码示例。我正在学习性能优化的方法,但我对它很新,并且不知道如何优化以下代码......

也许一种方法是在循环内初始化a。但我想不出任何其他方法来优化它。

1 个答案:

答案 0 :(得分:0)

虽然大多数这些优化都是由自动优化编译器执行的,但仍然很好理解编译器背后的操作。
以下是一些可能性:

  1. 常量折叠

    3.14除以180涉及两个编译时常量,因此可以提前计算并且只将结果存储在二进制中。这样可以节省运行时的计算速度,从而加快代码的执行速度。

    3.14/180 = 0.0174444   // assume 64-bit precision, like a double
    

    因此,代码变为:

    for(i=0;i<10000;i++) {    
      if ( (t1==0) && (t2==0) && (t3==0) ) 
         a = sin(45*b*0.0174444);  
      else  
         a = sin(135*b*0.0174444);  
    
      if ( condition2 & COND1 ) 
         DoOneThing(a);
      else if ( condition2 & COND2 ) 
         DoAnotherThing(a); 
      else 
         DoYetAnotherThing(a); 
    } 
    
  2. 常见的子表达式消除

    请注意,在a的赋值中,if语句的两边包含相同的计算。无论条件的评估如何都可以无条件地提升和完成。因此:

    if ( (t1==0) && (t2==0) && (t3==0) ) 
       a = sin(45*b*0.0174444);  
    else  
       a = sin(135*b*0.0174444);  
    

    变为:

    a = b*0.0174444;
    if ( (t1==0) && (t2==0) && (t3==0) ) 
       a *= 45;  
    else  
       a *= 135; 
    a = sin(a); 
    

    这并不能直接使代码执行得更快,尽管可以想象地减少代码的 size (因为同样的事情不会在两个不同的地方被评估两次地方),有时缩小尺寸可以提高速度(由于更好地利用缓存等)。

    事实上,仔细观察,我们注意到tempfor循环的所有迭代中都是不变的,因为b未在循环内部进行修改。这意味着它可以升得更高:

     a = b*0.0174444;
     for(i=0;i<10000;i++) {
        if ( (t1==0) && (t2==0) && (t3==0) ) 
           a *= 45;  
        else  
           a *= 135; 
        a = sin(a); 
    
       // etc.
     } 
    

    导致速度提升,因为现在我们不需要计算temp 10000次 - 我们只计算一次,存储它,并且每次重复使用它通过循环的时间。

  3. 循环不变代码促销

    我们只是尝试了这种优化,但还有更多可以做的事情。查看for循环,您会看到唯一被修改的变量是i。在循环体中,没有表达式依赖于i的值,这意味着这些结果实际上都不需要在循环内部计算。因此,我们可以将它们提升到循环之外,这样它们只能完成一次,而不是重复10000次。

    只有一点需要注意:我们不知道函数调用的内容(DoOneThingDoAnotherThingDoYetAnotherThing)是否在内部执行,因此我们无法做到做出任何假设。 (编译器可以,如果函数的定义是可见的。)我们所知道的只是它们只依赖于a的值,所以我们只需要确保每个函数被调用10000次

      a = b*0.0174444;
      if ( (t1==0) && (t2==0) && (t3==0) ) 
          a *= 45;  
      else  
          a *= 135;
      a = sin(a);  
    
      if ( condition2 & COND1 )
          for(i=0;i<10000;i++)
              DoOneThing(a);
      else if ( condition2 & COND2 ) 
          for(i=0;i<10000;i++)
              DoAnotherThing(a);
      else 
          for(i=0;i<10000;i++)
              DoYetAnotherThing(a);
    

    这将(显着)更快,因为我们不必每次都通过循环测试if条件,或进行任何其他计算。

  4. 当然可以进行其他优化,但这些是您可能希望看到的重要优化。正如其他人所评论的那样,这是非常可怕的代码。