Являются ли эти операторы эквивалентными (статические переменные, константные переменные и универсальные переменные) - PullRequest
0 голосов
/ 19 сентября 2018

Итак, я пишу пользовательскую функцию плавного шага, которая позволяет мне редактировать степень сглаживания.

По существу, при низких коэффициентах плавный шаг практически линейный, но при высоких коэффициентах получается большая кривая.

Код для этого выглядит следующим образом:

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 для переменной области действия предложиткомпилятору, что переменная принадлежит функции и, следовательно, имеет компилятор, предварительно вычисляющий ее и включающий в определение функций по факторам.

Однако я очень скептически отношусь к тому, что мое понимание const и staticправильно, поэтому я предполагаю, что ни одно из этих определений предварительно не вычислило c.Что я делаю не так?Есть ли неуниверсальный способ заставить прекомпилятор предварительно вычислить c?

1 Ответ

0 голосов
/ 19 сентября 2018

Просто сделайте функцию inline (что также означает, что функция должна быть в заголовочном файле) и убедитесь, что у вас есть оптимизации.

Пример: https://godbolt.org/z/rztmWe - как вы можете видетьесть только один вызов exp.

К сожалению для вас, я не думаю, что есть гарантированный способ получить этот эффект - вам придется полагаться на оптимизацию компилятора.С другой стороны, многие оптимизации компилятора в наши дни довольно надежны.

...