Функция оптимизирована для постоянной времени компиляции - PullRequest
4 голосов
/ 19 марта 2019

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

float calcLength(const float *v, int size, int inc) {
    float l = 0;

    for (int i=0; i<size*inc; i += inc) {
        l += v[i]*v[i];
    }
    return sqrt(l);
}

Теперь calcLength можно вызывать с двумя типами inc параметров: когда inc известен во время компиляции и когда нет.Я хотел бы иметь оптимизированную версию calcLength для общих значений времени компиляции inc (например, 1).

Итак, у меня было бы что-то вроде этого:

template <int C>
struct Constant {
    static constexpr int value() {
        return C;
    }
};

struct Var {
    int v;

    constexpr Var(int p_v) : v(p_v) { }

    constexpr int value() const {
        return v;
    }
};

template <typename INC>
float calcLength(const float *v, int size, INC inc) {
        float l = 0;

        for (int i=0; i<size*inc.value(); i += inc.value()) {
            l += v[i]*v[i];
        }
        return sqrt(l);
    }
}

Итак, это можно использовать:

calcLength(v, size, Constant<1>()); // inc is a compile-time constant 1 here, calcLength can be vectorized

или

int inc = <some_value>;
calcLength(v, size, Var(inc)); // inc is a non-compile-time constant here, less possibilities of compiler optimization

Мой вопрос: можно ли как-то сохранить оригинальный интерфейс и поставить Constant / Var автоматически, в зависимости от типа (постоянная времени компиляции) inc?

calcLength(v, size, 1); // this should end up calcLength(v, size, Constant<1>());
calcLength(v, size, inc); // this should end up calcLength(v, size, Var(int));

Примечание: это простой пример.В моей реальной проблеме у меня есть несколько функций, таких как calcLength, и они большие, я не хочу, чтобы компилятор их встроил.


Примечание 2: Я также открыт для разных подходов,По сути, я хотел бы иметь решение, которое удовлетворяет следующим условиям:

  • алгоритм указывается один раз (скорее всего, в шаблонной функции)
  • , если я задаю 1 какinc, создается специальная функция, и код, скорее всего, становится векторизованным
  • , если inc не является константой времени компиляции, общая функция вызывается
  • в противном случае (не-1константа времени компиляции): не имеет значения, какая функция вызывается

1 Ответ

0 голосов
/ 26 марта 2019

C ++ не позволяет определить, является ли предоставленный параметр функции постоянным выражением или нет, поэтому вы не можете автоматически различать предоставленные литералы и значения времени выполнения.

Если параметр должен будьте параметром функции, и вы не желаете менять способ его вызова в двух случаях, тогда единственный рычаг, который у вас есть, это тип параметра: ваши предложения для Constant<1>() против Var(inc) довольнохорошо в этом отношении.

...