所以我正在编写一个自定义的平滑步长函数,使我可以编辑平滑量。
基本上,低因子平滑步长实际上是线性的,而高因子则有大曲线。
执行此操作的代码如下:
float smoothstep(float x, float factor) {
float c = 0.5f / ((1.0f / (1.0f + exp(-factor))) - 0.5f);
return c * ((1.0f / (1.0 + exp(-factor * (2.0f * x - 1.0f)))) - 0.5f) + 0.5;
}
现在,由于此方法将被调用一帧数千次,因此我试图对其进行优化,以便在运行时计算c。我希望编译器能够做到这一点,因为我传入了数量有限的因素。因此,传递给因数的变量将始终以smoothstep(x, 1.0)
等形式编写。到目前为止,我实际上将通过一个因素。
所以我重写了这样的函数以使用通用参数
template <int F>
float smoothstep(float x) {
const float factor = (float)F / 100.0;
static const float c = 0.5f / ((1.0f / (1.0f + exp(-factor))) - 0.5f);
return c * ((1.0f / (1.0 + exp(-factor * (2.0f * x - 1.0f)))) - 0.5f) + 0.5;
}
这是非常不理想的,因为您只能使用整数作为模板参数,因此我必须传入一个100倍于我实际需要的整数。话虽如此,我相信这种解决方案将使编译器预先计算出系数c。对吧?
现在我的问题是否可以在没有泛型的情况下完成此操作,这是我在此遇到的两个问题
float smoothstep(float x, float factor) {
const float c = 0.5f / ((1.0f / (1.0f + exp(-factor))) - 0.5f);
return c * ((1.0f / (1.0 + exp(-factor * (2.0f * x - 1.0f)))) - 0.5f) + 0.5;
}
和
float smoothstep(float x, float factor) {
static const float c = 0.5f / ((1.0f / (1.0f + exp(-factor))) - 0.5f);
return c * ((1.0f / (1.0 + exp(-factor * (2.0f * x - 1.0f)))) - 0.5f) + 0.5;
}
我希望在其中一种情况下,预编译器(Clang和G ++)都能看到这些并为我传入的每个有限因子预先计算c。
我的理解是const
是一个关键字,用于向预编译器和编译器发出信号,表示变量将不会被更改,因此它应考虑对其进行优化。
我还认为,作用域变量上的static
会向编译器建议该变量属于该函数,因此使编译器对其进行预计算并将其按函数包括在函数定义中。
但是,我非常怀疑我对const
和static
的理解是正确的,因此我猜测这两个定义均未预先计算c。我怎么了?是否有一种非通用的方法来使预编译器预先计算c?
答案 0 :(得分:0)
只需创建函数inline
(这也意味着该函数应该在头文件中)并确保已启用优化。
示例:https://godbolt.org/z/rztmWe-如您所见,只有一个呼叫exp
。
不幸的是,对于您来说,我不认为有保证这种效果的可靠方法-您将不得不依赖编译器优化。另一方面,如今,许多编译器优化都相当可靠。