2013-08-05 39 views
1

我想使用std::numeric的算法來計算數組的絕對值之和,以便使用gnu並行擴展(數組大小> 500000)。使用stl算法計算絕對值的總和

這裏是我當前的代碼:

double ret = 0; 
for (auto i = 0U; i < length; ++i) 
{ 
    ret += std::abs(tab[i]); 
} 
return ret; 

所以我想這樣做:

auto sumabs = [] (double a, double b) 
{ 
    return std::abs(a) + std::abs(b); 
} 

std::accumulate(tab, tab + length, 0, sumabs); 

但因爲如果進行還原算法的效率不高(我真誠地希望爲求快速計算!),std::abs將應用於已經> = 0的值。

那麼有什麼辦法可以做到這一點?也許是「手工」執行減少的第一步,並讓其餘的做一個簡單的加法?但會有一個副本和一個內存命中......

+0

是'abs'甚至慢?你爲什麼不寫一個「constexpr」呢?針對您的情況實施一個天真的工具很容易。順便說一下,在C++ 11中,我們有'std :: begin(tab)','std :: end(tab)'。 – Rapptz

+0

是否使用'std :: begin'和'std :: end'即使它被聲明爲'double * tab'?這將是可笑的! 而且我不太明白...寫一個constexpr abs?它會做什麼? –

+0

@aaronman這是整數,OP需要雙倍。 Double更簡單 - 只需清除符號位,不分支。 – dasblinkenlight

回答

2

您可以將函數傳遞給accumlate方法並在函數內部執行「手動」評估。順便說一句,在你的代碼中,你可以將abs方法應用到第一個參數上,這是不必要的。

int fAccumulate (int accumulated, int accumulateIncrement) 
    { 
int retValue = 0; 
if (accumulateIncrement >= 0) 
{ 
    retValue = accumulated + accumulateIncrement; 
} 
else 
{ 
    retValue = accumulated + std::abs(accumulateIncrement); 
} 
return retValue; 

}

使用這種代碼可以是:

int init = 0; 
int numbers[] = {10,20,-30}; 
int a = std::accumulate (numbers, numbers+3, init, fAccumulate); 
+0

Mhh,好吧,適合我!我會嘗試做一些基準來看看分支預測的結果。 –

+1

這個解決方案沒有任何意義,你仍然在調用abs並且你支持從不好 – aaronman

+0

我假設你基於你使用C++標準庫你需要可移植性並且希望避免依賴於編譯器的代碼,尤其是在處理非整型類型如float和double。 – rv2300