Я написал несколько математических функций для использования в моей программе, они будут очень интенсивно использоваться. Я хотел бы предложить код, чтобы увидеть, а) есть ли улучшения логики и б) есть ли лучший способ сделать что-либо из этого. Это заголовочный файл, который включается при необходимости.
Я не компилирую для c ++ 11, поэтому, пожалуйста, помните об этом. — Я также знаю, что rootDouble для отрицательных чисел не является математически правильным.
Я думаю, что первое, что может появиться, — это преобразование входных данных вектора для передачи по ссылке, комментарии вокруг которых приветствуются.
С точки зрения того, что я принимаю ответ, я хотел бы знать, что и как можно улучшить для ускорения этих функций.
++ Я написал это довольно быстро, надеюсь, я не оставил никаких смущающих ошибок внутри!
#ifndef MATHSFUNCTIONS_H_
#define MATHSFUNCTIONS_H_
#include <algorithm>
#include <vector>
#include <numeric>
#include <cmath>class MathsFunctions {
public:
MathsFunctions();
virtual ~MathsFunctions();
inline static double squareDouble(double input) {
return input * input;
}
inline static double rootDouble(double input) {
if (input == 0.0) {
return 0.0;
} else if ( input < 0.0) {
input = flipDouble(input);
input = sqrt(input);
return flipDouble(input);
}
return sqrt(input);
}
inline static double flipDouble(double input) {
return input * -1;
}
inline static double rangeInVec(std::vector<double> inputs) {
return maxInVec(inputs) - minInVec(inputs);
}
inline static double stdDevInVec(std::vector<double> inputs) {
if (inputs.size() < 2) {return 0.0;}
double mean = meanInVec(inputs);
double sq_sum = std::inner_product(inputs.begin(), inputs.end(), inputs.begin(), 0.0);
return std::sqrt(sq_sum / inputs.size() - mean * mean);
}
inline static double meanInVec(std::vector<double> inputs) {
double sum = std::accumulate(inputs.begin(), inputs.end(), 0.0);
return sum / inputs.size();
}
inline static double sumOfVec(std::vector<double> inputs) {
double total = 0.0;
for (unsigned int var = 0; var < inputs.size(); ++var) {
total += inputs[var];
}
return total;
}
inline static double maxInVec(std::vector<double> inputs) {
bool first = true;
double max;
for (unsigned int var = 0; var < inputs.size(); ++var) {
if (first) {
max = inputs[var];
first = false;
} else {
if (inputs[var] > max) {
max = inputs[var];
}
}
}
return max;
}
inline static double minInVec(std::vector<double> inputs) {
bool first = true;
double min;
for (unsigned int var = 0; var < inputs.size(); ++var) {
if (first) {
min = inputs[var];
first = false;
} else {
if (inputs[var] < min) {
min = inputs[var];
}
}
}
return min;
}
inline static std::vector<double> weightValueVector(std::vector<double> inputs,std::vector<double> weights) {
std::vector<double> results;
for (unsigned x = 0; x < inputs.size(); ++x) {
results.push_back(inputs[x] * weights[x]);
}
return results;
}
};
#endif /* MATHSFUNCTIONS_H_ */
Возможно, самый большой выигрыш в скорости и времени разработки будет
использовать существующую библиотеку линейной алгебры вместо переизобретения
колесо, см
использование BLAS а также LAPACK это настроено на архитектуру вашей машины. В
В частности, векторные инструкции доступны на вашем компьютере и
размеры кеша оказывают ОГРОМНОЕ влияние на производительность.
Если ваши векторы достаточно малы, вы можете получить значительный
прирост производительности за счет размещения их в стеке. Теперь ты
размещая их в куче.
Используя методы метапрограммирования шаблонов вы можете устранить
многие из временных и ненужных петель во время компиляции. к
повтори пример Википедии здесь:
Скажи у тебя Vec x = alpha*(u -
где
v);alpha
это скаляр и u
а также v
являются Vecs
,
если ты
реализовать его так, как вы это делаете, это будет стоить вам
минимум 2 временных вектора (один для u-v
и один для
умножение с alpha
) а также 2 прохождения по памяти
(2 или 3 петли: одна для u-v
один для
умножение с alpha
и еще один для назначения, если это не оптимизировано далеко).
Если вы делаете шаблонное метапрограммирование, Vec x = alpha*(u -
будет сводиться к одной петле без временных и это лучшее, что вы можете получить. Прибыль становится еще больше с более сложными выражениями.
v);
На
момент, когда у вас нет этих операций, но я думаю, что это только вопрос
времени, что они вам понадобятся (weightValueVector()
это указание).
Конечно, если вы используете библиотеку линейной алгебры, вам не нужно знать / беспокоиться о любом из них, но вместо этого вы можете сконцентрироваться на своем приложении и получить потрясающий быстрый код.
Ну, я заметил несколько улучшений,
std :: vector должен быть передан константной ссылкой или ссылкой.
вам нужно проверить inputs.size()
для некоторых из этих функций.
было бы полезно и быстрее предложить weightValueVector
для принятия ссылки в качестве параметра и изменения его значений на месте.
Наверху ответов уже предоставлено:
в maxInVec
функция:
— нулевая инициализация double max
— Я бы посоветовал size_t var
над unsigned int var = 0
Вы также можете использовать reserve
для вашего вектора, когда вы знаете размер заранее, чтобы избежать перераспределения памяти при выполнении нескольких push_back