2

我想使用算法std::numeric来计算数组的绝对值之和,以便使用 gnu 并行扩展(数组大小> 500000)。

这是我当前的代码:

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的值。

那么有没有办法做到这一点?也许“手动”执行减少的第一步,然后std::accumulate在其余部分之间做一个简单的加法?但是会有副本和内存命中...

4

2 回答 2

1

您可以将函数传递给 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);
于 2013-08-05T04:24:50.797 回答
1

std::abs这将使用必要的最少调用次数:

#include <algorithm>
#include <cmath>

int main() {
    static const auto abssum = [] (auto x, auto y) {return x + std::abs(y);};
    
    float entries[4] = {1.0f, 2.0f, 3.0f, 4.0f};

    auto sum = std::accumulate(std::begin(entries), std::end(entries), 0.0f, abssum);
}
于 2018-08-04T00:29:21.253 回答