优化循环

时间:2018-01-04 18:49:29

标签: c optimization function-pointers function-calls

我有渲染功能,但是用户可以通过设置函数指针来覆盖它;在每一帧中我都会检查它是否存在,如果没有,我会使用默认功能:

GK_EXPORT
void
gkScenePerLightRenderPath(GkScene *scene) {
  /* ... */

  do {
    /* ... */
    for (i = 0; i < c; i++) {
      modelInst = objs[i];

      if (!scene->renderModelFn)
        gkRenderModel(scene, modelInst);
      else
        scene->renderModelFn(scene, modelInst);
    }
  } while (/* next light */);
}

我想也许我可以写下面的内容:

GK_EXPORT
void
gkScenePerLightRenderPath(GkScene *scene) {
  /* ... */
  GkRenderModelFn renderModelFn;

  /* ... */

  if (!scene->renderModelFn)
    renderModelFn = gkRenderModel;
  else
    renderModelFn = scene->renderModelFn;

  do {
    /* ... */
    for (i = 0; i < c; i++) {
      modelInst = objs[i];
      renderModelFn(scene, modelInst);
    }
  } while (/* next light */);
}

哪个更好?在第二个版本似乎我隐藏gkRenderModel所以编译器可能无法应用优化?如果编译器将gkRenderModel分配给指针并不重要,那么第二个似乎更优,因为if / else在两个循环之外?

1 个答案:

答案 0 :(得分:2)

这取决于几个因素:

  • 如果renderModelFn(或其他任何线程)修改scene对象
  • 如果gkRenderModel()被声明为inline

如果它保证是外部/外部函数,并且循环中没有任何内容修改scene指针中指向的对象,那么最好放置if语句在循环之前,所以它只需要评估一次。

但是,如果被调用函数有可能修改传入的renderModelFn对象的scene成员,则在循环之前移动检查会改变行为。

此外,对函数指针的调用总是不符合要求。因此,在循环外移动if语句将会破坏任何内联的可能性。在这种情况下,最好将if语句保留在循环中。