C++ 用stl算法计算绝对值之和
我想使用C++ 用stl算法计算绝对值之和,c++,stl,stl-algorithm,reduction,C++,Stl,Stl Algorithm,Reduction,我想使用std::numeric的算法来计算数组绝对值的总和,以便使用gnu并行扩展(数组大小>500000) 这是我目前的代码: double ret = 0; for (auto i = 0U; i < length; ++i) { ret += std::abs(tab[i]); } return ret; 但这是低效的,因为如果执行简化算法(为了快速计算,我真诚地希望如此!),std::abs将应用于已经>=0的值 那么有没有办法做到这一点?也许“用手”执行缩减的第一步,
std::numeric
的算法来计算数组绝对值的总和,以便使用gnu并行扩展(数组大小>500000)
这是我目前的代码:
double ret = 0;
for (auto i = 0U; i < length; ++i)
{
ret += std::abs(tab[i]);
}
return ret;
但这是低效的,因为如果执行简化算法(为了快速计算,我真诚地希望如此!),std::abs
将应用于已经>=0的值
那么有没有办法做到这一点?也许“用手”执行缩减的第一步,让
std::accumulate
在其余部分之间做一个简单的加法?但是会有一个拷贝和一个内存命中…您可以将一个函数传递给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);
这将使用对
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);
}
#包括
#包括
int main(){
静态常量auto abssum=[](auto x,auto y){return x+std::abs(y);};
浮动条目[4]={1.0f、2.0f、3.0f、4.0f};
自动求和=标准::累计(标准::开始(条目),标准::结束(条目),0.0f,绝对求和);
}
防抱死制动系统(abs)是否甚至很慢?如果它让你感到不舒服,为什么不写一个constexpr
呢?对于您的情况,实现一个简单的方法是非常容易的。顺便问一下,在C++11中,我们有std::begin(tab)
,std::end(tab)
。std::begin
和std::end
即使声明为double*tab
,也可以使用它吗?那太可笑了!我真的不明白。。。写一个constexpr abs?它能做什么?@aaronman这是ints,OP需要加倍。Double更简单-只需清除符号位,不进行分支。那么问题出在哪里?对于双人房来说,这绝对是一个没有分支的指示GMHH,好的,对我有用!我将尝试做一些基准来查看分支预测。这个解决方案没有意义,你仍然在调用它的ABS,你是分支,这从来都不是Goodii,假设你使用C++标准库,你需要移植性,并且希望避免编译器依赖的代码,特别是在处理时。使用非整数类型,如float和double。为什么不使用0.0f
,并完全避免条目[0]
?@DarkZeros是的,这更清楚。当时我太想变得聪明了。
#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);
}