Я разрабатываю некоторые высокопроизводительные статистические функции и пытаюсь заставить их выполнять различные операции на основе аргументов некоторых функций. Настоящая проблема заключается в разработке общего кода, который гибко выполняет различие, частичное / обобщенное различие, темпы роста и лог-различие на основе аргументов функции. Чтобы дать базовый c пример:
// General code to first-difference a vector:
std::vector<double> diff(std::vector<double> x, int ret = 1, double rho = 1, ...) { // ... = more arguments int l = x.size();
std::vector<double> res(l);
for (int i = 1; i < l; ++i) res[i] = FUN(x[i], x[i - 1]);
// rest of code ...
}
Теперь FUN(y, x)
- это то, что я хочу эффективно варьировать, основываясь на аргументах ret
и rho
. Для простых различий это y-x
, для обобщенных различий - y-rho*x
, для логарифмических разностей - log(y/x)
, для темпов роста (y-x)*(100/x)
, и могут быть добавлены дополнительные параметры. Код применяется к большим наборам данных и должен быть быстрым, поэтому оптимально я бы использовал что-то вроде условно созданного макроса для FUN
, то есть что-то вроде:
std::vector<double> diff(std::vector<double> x, int ret = 1, double rho = 1, ...) {
int l = x.size();
std::vector<double> res(l);
#define FUN(y, x) (ret==1 && rho==1) ? ((y)-(x)) : \
(ret==1) ? ((y)-rho*(x)) : \
(ret==2) ? (log((y)/(x))) : \
(ret==3) ? ((y)-(x))*(100/(x))
for (int i = 1; i < l; ++i) res[i] = FUN(x[i], x[i - 1]);
}
Это работает, но, судя по уменьшенному Скорость кода мне кажется, что я не создаю макрос, а только один макрос, и каждый раз, когда вызывается FUN
, все условия оцениваются для выполнения правильной операции. Я немного рассмотрел эти команды препроцессора (#if, #elif, #else, #endif, #define и #undef), но мне кажется, что вы не можете использовать их для условного создания макроса на основе аргументов функции. Вторым подходом может быть использование встроенных функций, например:
inline double do_diff(double y, double x, double r) {
return y-x;
}
inline double do_gdiff(double y, double x, double r) {
return y-r*x;
}
inline double do_logdiff(double y, double x, double r) {
return log(y/x);
}
inline double do_growth(double y, double x, double r) {
return (y-x)*(100/x);
}
std::vector<double> diff(std::vector<double> x, int ret = 1, double rho = 1, ...) {
int l = x.size();
std::vector<double> res(l);
auto FUN = (ret==1 && rho==1) ? do_diff :
(ret==1) ? do_gdiff :
(ret==2) ? do_logdiff :
(ret==3) ? do_growth;
for (int i = 1; i < l; ++i) res[i] = FUN(x[i], x[i - 1], rho);
}
Проблема здесь заключается только в том, что он уменьшает скорость кода примерно в 1,5 раза. Учитывая, что это действительно простые операции и этот код должен быть максимально быстрым, я бы предпочел этого избежать. Итак, мой вопрос: есть ли способ изменить операцию, выполняемую FUN
, с минимальными затратами на производительность?
Примечание. Дублирование кода здесь нежелательно, так как фактический код, над которым я работаю, гораздо сложнее, то есть он может выполнять многократные различия неупорядоченных данных панели и т. Д. c, около 700 строк, в которых FUN
входит в нескольких местах.