优化循环的性能

Inv*_*rse 10 c++ performance c++11

我一直在描述我的代码(下面显示的函数)中的一个瓶颈,它被称为数百万次.我可以使用提示来提高性能.这些XXXs数字来自Sleepy.

使用visual studio 2013 /O2和其他典型版本设置进行编译.

indicies通常为0到20个值,其他参数大小相同(b.size() == indicies.size() == temps.size() == temps[k].size()).

1:          double Object::gradient(const size_t j, 
2:                                  const std::vector<double>& b, 
3:                                  const std::vector<size_t>& indices, 
4:                                  const std::vector<std::vector<double>>& temps) const
5:  23.27s  {
6:              double sum = 0;
7:  192.16s     for (size_t k : indices)
8:  32.05s          if (k != j)
9:  219.53s             sum += temps[k][j]*b[k];
10:      
11: 320.21s     return boost::math::isfinite(sum) ? sum : 0;
13: 22.86s  }
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

谢谢提醒伙计.以下是我从建议中得到的结果:

在此输入图像描述

我发现切换到cbegin()cend()产生如此大的影响很有意思.我想编译器并不像那里那么聪明.我对这个凹凸感到满意,但是如果通过展开或矢量化在这里有更多的空间,我仍然很好奇.

对于那些感兴趣的人,我的基准是isfinite(x):

boost::isfinite(x):
------------------------
SPEED: 761.164 per ms
TIME:  0.001314 ms
   +/- 0.000023 ms

std::isfinite(x):
------------------------
SPEED: 266.835 per ms
TIME:  0.003748 ms
   +/- 0.000065 ms
Run Code Online (Sandbox Code Playgroud)

kfs*_*one 5

如果您知道将满足条件(在每次迭代中都会满足k == j),请消除条件并用简单的条件存储替换返回条件。

double sum = -(temps[j][j]*b[j]);
for (size_t k : indices)
     sum += temps[k][j]*b[k];
if (!std::isfinite(sum))
     sum = 0.0;
return sum;
Run Code Online (Sandbox Code Playgroud)

基于范围的 for 仍然很新,并不总是能得到很好的优化。您可能还想尝试:

const auto it = cend(indices);
for (auto it = cbegin(indices); it != end; ++it) {
    sum += temps[*it][j]*b[*it];
}
Run Code Online (Sandbox Code Playgroud)

看看性能是否有所不同。