优化循环中的函数指针检查
optimize function pointer checking in loop
我有渲染函数,但用户可以通过设置函数指针来覆盖它;在每一帧中,我都在检查它是否存在,如果不存在,我将使用默认函数:
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 在两个循环之外?
这取决于几个因素:
- 如果
renderModelFn
(或任何其他线程,就此而言)完全修改 scene
对象
- 如果
gkRenderModel()
声明为 inline
或不声明。
如果它保证是一个外部/外联函数,并且循环中没有任何内容修改scene
指针中指向的对象,那么最好把if
循环之前的语句,所以只需要计算一次。
但是,如果被调用函数有可能修改传入 scene
对象的 renderModelFn
成员,则在循环之前移动检查会改变行为。
此外,对函数指针的调用总是越界的。因此,将 if 语句移到循环之外会破坏任何内联的可能性。在这种情况下,最好将 if
语句保留在循环中。
我有渲染函数,但用户可以通过设置函数指针来覆盖它;在每一帧中,我都在检查它是否存在,如果不存在,我将使用默认函数:
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 在两个循环之外?
这取决于几个因素:
- 如果
renderModelFn
(或任何其他线程,就此而言)完全修改scene
对象 - 如果
gkRenderModel()
声明为inline
或不声明。
如果它保证是一个外部/外联函数,并且循环中没有任何内容修改scene
指针中指向的对象,那么最好把if
循环之前的语句,所以只需要计算一次。
但是,如果被调用函数有可能修改传入 scene
对象的 renderModelFn
成员,则在循环之前移动检查会改变行为。
此外,对函数指针的调用总是越界的。因此,将 if 语句移到循环之外会破坏任何内联的可能性。在这种情况下,最好将 if
语句保留在循环中。