优化循环中的函数指针检查

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

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

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在两个循环之外?

c optimization function-pointers function-calls
1个回答
2
投票

这取决于几个因素:

  • 如果renderModelFn(或任何其他线程,就此问题)修改scene对象
  • 如果gkRenderModel()被宣布为inline或不。

如果它保证是外部/外部函数,并且循环中没有任何内容修改scene指针中指向的对象,那么最好将if语句放在循环之前,因此它只需要进行求值一旦。

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

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

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