Улучшение класса математической функции для скорости переполнения стека

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

Я не компилирую для 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_ */

1

Решение

  1. Возможно, самый большой выигрыш в скорости и времени разработки будет
    использовать существующую библиотеку линейной алгебры вместо переизобретения
    колесо, см

  2. использование BLAS а также LAPACK это настроено на архитектуру вашей машины. В
    В частности, векторные инструкции доступны на вашем компьютере и
    размеры кеша оказывают ОГРОМНОЕ влияние на производительность.

  3. Если ваши векторы достаточно малы, вы можете получить значительный
    прирост производительности за счет размещения их в стеке. Теперь ты
    размещая их в куче.

  4. Используя методы метапрограммирования шаблонов вы можете устранить
    многие из временных и ненужных петель во время компиляции. к
    повтори пример Википедии здесь:

    Скажи у тебя 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() это указание).

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

1

Другие решения

Ну, я заметил несколько улучшений,

  1. std :: vector должен быть передан константной ссылкой или ссылкой.

  2. вам нужно проверить inputs.size() для некоторых из этих функций.

  3. было бы полезно и быстрее предложить weightValueVector для принятия ссылки в качестве параметра и изменения его значений на месте.

1

Наверху ответов уже предоставлено:
в maxInVec функция:
— нулевая инициализация double max
— Я бы посоветовал size_t var над unsigned int var = 0
Вы также можете использовать reserve для вашего вектора, когда вы знаете размер заранее, чтобы избежать перераспределения памяти при выполнении нескольких push_back

1
По вопросам рекламы [email protected]