2013-10-11 57 views
1

我寫了一些數學函數在我的程序中使用,他們將得到非常大的使用。我想提供代碼,看看是否a)有邏輯上的改進,b)如果有更好的方法來做這些事情。它的頭文件包含在需要的地方。改進速度的數學函數類C++

我不是爲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_ */ 
+0

有什麼具體問題嗎?它似乎是一個代碼審查 –

+0

是的,這是我猜,但主要問題是,有什麼地方我可以提高速度 – joeButler

+0

你不需要編寫最大,總和,最小功能,STL算法提供它們已經 – billz

回答

1
  1. 也許在速度和開發時間最大的收穫將是 使用現有的線性代數庫,而不是重新發明 車輪,看到

  2. 使用BLASLAPACK調整到您的機器體系結構。特別是,在您的機器上可用的矢量指令和緩存大小對性能有很大影響。

  3. 如果您的載體足夠小,您可能通過在堆棧中分配它們來獲得顯着的性能提升。現在,你是 在堆上分配它們。

  4. 通過使用template metaprogramming techniques可以在編譯時消除 許多臨時和不必要的循環要 這裏重複維基百科的例子:

    說你有Vec x = alpha*(u - v);其中alpha是標量和uvVecs

    如果 你在做它的方式實現它,它會花費你在 至少2個臨時向量(一個用於u-v和一個用於 乘以alpha 2通過內存 ( 2或3個循環:一個用於u-v,一個用於 乘以alpha,另外一個用於未指定優化的賦值)。

    如果你這樣做模板元編程,Vec x = alpha*(u - v);將歸結爲沒有臨時工單環和那就是你可以得到最好的。隨着更復雜的表達式,增益變得更大。

    在 時刻,你沒有這些操作,但我想這只是一個時間問題,你會需要它們 (weightValueVector()是一個跡象)。

當然,如果你使用了線性代數庫,你不必知道任何有關這些/憂慮,但你可以專注於應用程序,而不是和獲得超快的代碼。

+0

謝謝你,這裏有一些很棒的點子。現在測試! – joeButler

+0

@joeButler我很高興你覺得它很有用。我個人使用[Armadillo](http://arma.sourceforge.net/);該API是合理的直觀,這個庫帶有非常寬鬆的許可證。 – Ali

+0

啊,我一直在eigen擺弄,將調查兩個。可以肯定的是,這意味着在整個我的程序中使用庫矢量/矩陣類型替換std :: vector,然後使用庫對這些數據執行數學運算?有點像使用boost對象?到目前爲止,我已經有了一個很好的測試框架,所以對我來說應該很容易衡量改進:) – joeButler

1

嗯,我看到了一些改進,

  1. 的std ::向量應引用或引用傳遞。

  2. 您需要檢查inputs.size()的某些功能。

  3. 如果提供weightValueVector作爲參數參考並修改其值,將會有用且更快。

1

在已經提供了答案的頂部:
maxInVec功能 :
- 零intialize double max
- 我建議size_t varunsigned int var = 0
您還可以使用reserve爲您的載體,當你知道大小提前避免重新分配內存時做幾次push_back