使用常数双指数优化幂的和
我已经实现了一种算法,在某些时候需要计算矢量元素的功率总和。 权力是一个积极的双重,在循环过程中不变。 我想通了,这个计算是目前我的程序的瓶颈,并想知道是否有办法加快下面的代码片段:
double SumOfPowers(std::vector<double>& aVector,double exponent)
{
double help = 0;
size_t sizeOfaVector = aVector.size();
for (size_t k = 0; k < sizeOfaVector; k++)
{
help += std::pow(aVector[k], exponent);
}
return help;
}
我有一种感觉,就好像可以利用指数在循环期间不变的事实并减少昂贵的std :: pow调用。 有没有人知道更好的实现方式,或者是否有可以使用的库函数来完成这项工作?
首先,检查循环是否是向量化的。 为此,使用-O3
编译你的程序(这里和下面我假设gcc编译器;我不太了解其他编译器,但我希望他们有类似的选项)。 添加-ftree-vectorizer-verbose=2
选项以获取关于哪些循环被矢量化的详细输出。 你可能想玩弄选项来获得你想要的输出。
如果循环没有矢量化,那么你可以使它矢量化。 您可能需要更改循环结构(例如,首先将所有权限计算为单独的数组,然后才计算总和),或者使用某种方式告知编译器的更多信息,如restrict
声明,请参阅“使用gcc 4.7进行矢量化“以获得更多讨论。 在最糟糕的情况下,我认为,您可以手动实现矢量化,我记得有这样的功能,请参阅Intel的参考资料或“用C ++实现SSE SIMD的实用指南”。
对于Visual Studio,首先添加/Qvec-report:2
选项以获得详细报告。 以上所有其他建议也适用,您只需要找到相应的MSVC选项。
另一种加快速度的方法是使用-ffast-math
选项来牺牲精度。 AFAIK,标准的pow
函数使用一些先进的逻辑来检查基数或指数是否真的接近1以避免精度问题。 如果这不是你的情况,你可能不需要这个逻辑。 我认为,尽管你可能想要检查它,但是-ffast-math
会降低它。
无论如何,你可以用exp(log(...)*...)
替换pow
来避免手动检查。 这不会给你提速,但你可能会注意到一些收获。 另外,如果您经常将相同的向量提升为不同的指数,则可以预先计算log
。
不,恒指数不允许进行可行的优化,除非您的值经常重复(如果是这样的话:memoize)。 并行是你最好的选择在这里(或不pow
在所有)