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

时间:2018-09-19 02:19:12

标签: c++ g++ clang

所以我正在编写一个自定义的平滑步长函数,使我可以编辑平滑量。

基本上,低因子平滑步长实际上是线性的,而高因子则有大曲线。

执行此操作的代码如下:

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会向编译器建议该变量属于该函数,因此使编译器对其进行预计算并将其按函数包括在函数定义中。

但是,我非常怀疑我对conststatic的理解是正确的,因此我猜测这两个定义均未预先计算c。我怎么了?是否有一种非通用的方法来使预编译器预先计算c?

1 个答案:

答案 0 :(得分:0)

只需创建函数inline(这也意味着该函数应该在头文件中)并确保已启用优化。

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

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