改进数学函数类以加快 c++ 的速度

Improving a maths function class for speed c++

本文关键字:c++ 速度 函数      更新时间:2023-10-16

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

我不是为 c++11 编译的,所以请记住这一点。 - 我也知道负数的根双精度在数学上不正确。

我认为可能出现的第一件事是将矢量输入转换为通过引用传递,欢迎评论。

就我接受答案而言,我想知道这些功能可以提高什么以及如何提高速度。

++我已经很快发布了这个,希望我没有在里面留下任何令人尴尬的错误!

#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. 也许在速度和开发时间方面最大的收益是使用现有的线性代数库而不是重新发明轮子,见

    • 使用最广泛的C++向量/矩阵数学/线性代数库是什么,以及它们的成本和收益权衡?

    • 对可用、快速C++矩阵库的建议?

  2. 使用针对您的机器架构进行调整的 BLAS 和 LAPACK。在特别是,您机器上可用的矢量指令和缓存大小对性能有很大影响。

  3. 如果您的载体足够小,您可能会得到显着的通过在堆栈上分配它们来提高性能。现在,你是将它们分配到堆上。

  4. 通过使用模板元编程技术,您可以消除编译时的许多临时和不必要的循环。自在这里重复维基百科的例子:

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

    如果你以您正在做的方式实施它,它将花费您至少 2 个临时向量(一个用于u-v,一个用于乘以 alpha ( 2 通过内存(2 或 3 个循环:一个用于u-v,一个用于乘以 alpha,如果未优化,则再乘一个用于赋值(。

    如果你做模板元编程,Vec x = alpha*(u - v);将归结为一个没有临时的循环,这是你能得到的最好的。 使用更复杂的表达式,收益会变得更大。

    在当你没有这些操作时,但我想这只是一个问题您将需要它们的时间(weightValueVector()是一个指示(。

当然,如果您使用线性代数库,则不必知道/担心其中任何一个,但您可以专注于您的应用程序并获得超快的代码。

嗯,我发现了一些改进,

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

  2. 您需要检查其中一些函数的inputs.size()

  3. 提供将引用作为参数并就地修改其值的weightValueVector将是有用且更快的。

在已经提供的答案之上:
maxInVec函数中:
- 零初始化double max
- 我会推荐size_t var而不是unsigned int var = 0
当您提前知道大小时,您还可以将 reserve 用于矢量,以避免在执行多个push_back时重新分配内存