优化常数双指数的幂和
Optimize sum of powers with constant double exponent
我已经实现了一个算法,在某些时候需要计算向量元素的幂之和。功率是一个正双精度,在循环期间是恒定的。我发现,这个计算目前是我的程序的瓶颈,想知道是否有一种方法来加速以下代码片段:
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的自动向量化"了解更多讨论。在最坏的情况下,我认为,你可以手工实现向量化,我记得有这样的函数,参见英特尔的参考资料或"用c++实现SSE SIMD的实用指南"。
对于Visual Studio,首先添加/Qvec-report:2
选项以获得详细报告。以上所有的建议也适用,你只需要找到相应的MSVC选项。
另一种加速的方法是通过使用-ffast-math
选项来牺牲精度。据我所知,标准pow
函数使用一些高级逻辑来检查底数或指数是否真的接近于1,以避免那里的精度问题。如果这不是您的情况,您可能不需要这种逻辑。我想-ffast-math
会删除它,尽管您可能想要检查它。
无论如何,您可以将pow
替换为exp(log(...)*...)
以手动避免这些检查。这不会给您带来太多的加速,但您可能会注意到一些增益。此外,如果您经常将同一向量提高到不同的指数,您可以预先计算log
s。
不,常量指数不允许可行的优化,除非您的值经常重复(如果是的话:记住)。并行化是最好的选择(或者根本不使用pow
)
- 如何在 C# 中映射双 C 结构指针?
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 正在将csv文件读取为双精度矢量
- 使用简单类型列表实现的指数编译时间.为什么
- C++我需要了解在哪里使用指针和双指针
- C++中的双指针类型转换
- 如何将包含指数的 QString 转换为C++中的双倍?
- 使用双精度运算的快速 SSE 低精度指数
- 如何在C++中从尾数和指数转换为双倍
- 双到字符串用指数表示的大数字的转换
- 找到以 10 为底的双倍的指数和尾数
- 浮点和双常数比较
- 有什么方法可以用MSVS2015模拟编译时的双常数吗
- 如何在 openCv 中将常数双精度值与 GpuMat 相乘
- 阅读双科学记数法,'D'作为C++中的指数前缀
- 如何在 c++ 下对尾数和双精度或浮点数的指数部分进行操作(快速)
- 宏或函数,用于根据给定的符号、尾数和指数构造浮点(双精度)
- 便携式打印双倍到C++个 iostreams 的指数
- 常数表达式可以是双精度类型而不是只能是整型吗?
- 优化常数双指数的幂和