改进数学函数类以获得速度c ++

时间:2013-10-11 23:24:07

标签: c++ math inline vectormath

我在我的程序中编写了一些数学函数,它们将得到非常大的使用。我想提供代码,看看a)是否有改进的逻辑和b)如果有更好的方法来做这些。它是一个头文件,包含在需要的地方。

我没有为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_ */

3 个答案:

答案 0 :(得分:1)

好吧,我发现了一些改进,

  1. std :: vector应该通过const引用或引用传递。

  2. 您需要检查inputs.size()部分功能。

  3. 提供weightValueVector以将参考作为参数并在适当的位置修改其值会更有用,也更快。

答案 1 :(得分:1)

在已提供的答案之上:
maxInVec函数中:
- 零初始化double max
- 我建议size_t var超过unsigned int var = 0 当您事先知道大小时,也可以使用reserve作为向量,以避免在执行多个push_back时重新分配内存

答案 2 :(得分:1)

  1. 也许速度和开发时间的最大收获是 使用现有的线性代数库而不是重新发明 方向盘,见

  2. 使用调整到您的计算机体系结构的BLASLAPACK。在 特别是,您的机器上可用的矢量指令和 缓存大小对性能有很大影响。

  3. 如果你的向量足够小,你可能会得到一个重要的 通过在堆栈上分配它们来获得性能提升。现在你是 在堆上分配它们。

  4. 使用template metaprogramming techniques可以消除 许多临时和不必要的循环在编译时。 To 在这里重复维基百科的例子:

    假设您Vec x = alpha*(u - v);其中alpha是标量而uvVecs

    如果你 以你正在做的方式实现它,它将花费你 至少2个临时向量(一个用于u-v,一个用于。{ 乘以alpha 2通过内存 (2或3个循环:一个用于u-v,一个用于alpha 如果未进行优化,则使用Vec x = alpha*(u - v);乘以及另外一个用于赋值。

    如果您进行模板元编程,weightValueVector()将归结为没有临时的单个循环和,这是您可以获得的最佳。表达式越复杂,增益就越大。

    在 你没有这些操作的那一刻,但我想这只是一个问题 你需要它们的时间({{1}}是一个指示)。

  5. 当然,如果你使用线性代数库,你不必知道/担心任何这些,但你可以专注于你的应用程序,并获得超快的代码。