【问题标题】:optimizing C code with imbedded for loops使用嵌入式 for 循环优化 C 代码
【发布时间】:2020-08-02 02:45:36
【问题描述】:
    void evolve(board prv, board nxt){
      
       int i, j;
       int n;
    
       printf("\rGeneration %d\n", generation++);
       if (printLazy == 1){
         lazyPrint(prv);
       
for (j=0; j < WIDTH; ++j) {
          for (i = 0; i < HEIGHT; ++i) {
             n = neighbors(prv, i, j);
             if (prv[i][j] && (n == 3 || n == 2))
                nxt[i][j] = true;
             else if (!prv[i][j] && (n == 3)) 
                nxt[i][j] = true;
             else
                nxt[i][j] = false;
          }
       }
    }

** 有人要求我添加邻居方法

static int neighbors (board b, int i, int j) {
   int n = 0;
   int i_left = max(0,i-1);
   int i_right  = min(HEIGHT, i+2);
   int j_left = max(0,j-1);
   int j_right  = min(WIDTH, j+2);
   int ii, jj;

   for (ii = i_left; ii < i_right; ++ii) {
      for (jj = j_left; jj < j_right; ++jj) {
         n += b[ii][jj];
      }
   }

   return n - b[i][j];
}

所以我正在努力优化它,以便它运行得更快,但我一直在思考如何进一步优化它。这是我目前所拥有的

void evolve(board prv, board nxt) {
  
   register int i, j;
   int n;
   bool next;

   printf("\rGeneration %d\n", generation++);
   if (printLazy == 1){
     lazyPrint(prv);
   }
   
   for (j=0; j < WIDTH; ++j) {
      for (i = 0; i < HEIGHT; ++i) {
         n = neighbors(prv, i, j);
         if (prv[i][j])
                if (n == 2)
                        next = true;
                else if (n == 3)
                        next = true;
                else
                        next = false;
         else
                if(n == 3)
                        next = true;
                else
                        next = false;
         nxt[i][j] = next;
      }
   }
}

有没有更好的方法来做到这一点,或者你们有什么推荐的资源或视频?

谢谢,感谢任何帮助。

【问题讨论】:

  • 编译启用优化。这很可能比你手工做的任何事情都要好。
  • 我想知道切换循环(首先有主轴)嵌套是否可以实现更好的数据局部性。我也喜欢使用临时变量,通过减少重复表达式来“阅读简单” if没有别的。
  • 你优化,因为你大概关心性能,但你不衡量性能,所以你不关心它。看到问题了吗?制作一个优化的发布版本,在 VTune 或 cachegrind 之类的东西下运行它,看看你“改进”的东西是否真的改进了东西。
  • 发布neighbors()的定义以获得更好的想法。

标签: c optimization conways-game-of-life


【解决方案1】:

一些想法内联你的函数neighbors()。或者把它变成一个宏。整理条件。要展开内部循环,请将 i 的每次使用都替换为文字值,这样您的代码如下所示:

for (j =0;.......
   n = fun(prev, 0 ,j);
   If.....
      n = fun(prev, 1, j);
   if......

等等。 如果 HEIGHT 的值是 100,那么你会得到 100 个函数调用和 100 个复合条件的代码爆炸。如果展开外循环,情况会更糟。

【讨论】:

    【解决方案2】:

    如果 n 被限制为 8 个邻居,请使用查找表

    bool foo[2][8] = { [1][2] = true,  [1][3] = true, [0][3] = true };
    
    for (j=0; j < WIDTH; ++j) {
      for (i = 0; i < HEIGHT; ++i) {
        n = neighbors(prv, i, j);
        nxt[i][j] = foo[prv[i][j]][n];
      }
    }
    

    一个常见的弱点是neighbors(prv, i, j) 函数本身。一个技巧是在所有四个边上将 2D 数组的大小增加 1 并用 false 填充边缘,因此 neighbors() 始终可以检查 8 个邻居,因为它从不在边缘/角落使用。

    确保第二维是 2 的幂也有助于简化指数计算。所以如果原数组方式为12*11,则制作新数组(1+12+1)*(1+11+1+4)14*16

    【讨论】:

    • @0x476f72616e 我怀疑是这样,但 OP 提供的细节很少。像往常一样,“如何加速代码”这类帖子关注的是一个小的线性问题,而不是减少 O()。
    猜你喜欢
    • 2021-12-22
    • 1970-01-01
    • 2020-09-07
    • 2011-10-12
    • 1970-01-01
    • 2019-04-21
    • 1970-01-01
    • 1970-01-01
    • 2014-03-05
    相关资源
    最近更新 更多