这些语句是否等效(静态变量、常量变量和泛型)



所以我正在编写一个自定义平滑步骤函数,允许我编辑平滑量。

本质上,对于低因子,平滑步骤实际上是线性的,但对于高因子,有一个很大的曲线。

执行此操作的代码如下:

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;
}

这是相当不理想的,因为您只能使用整数作为模板参数,因此我必须传入一个 int,它是我实际需要的 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会向编译器建议该变量属于该函数,从而使编译器预先计算它并将其包含在每个因子的函数定义中。

然而,我非常怀疑我对conststatic的理解是否正确,因此我猜测这些定义都没有预先计算c。我做错了什么?有没有一种非通用的方法可以让预编译器预计算 c?

只需使函数inline(这也意味着该函数应该在头文件中(并确保进行了优化。

示例:https://godbolt.org/z/rztmWe - 如您所见,只有一个调用exp

不幸的是,我认为没有一种保证的方法可以获得这种效果 - 您将不得不依赖编译器优化。另一方面,如今许多编译器优化都相当可靠。

最新更新