【问题标题】:Optimisation of float vector elements' comparison浮点向量元素比较优化
【发布时间】:2015-07-23 07:46:24
【问题描述】:

分析以下代码(更新):

struct myStruct {
    float a;
    float b;
};

int main()
{
    std::vector<myStruct> myVector;
    float tmp,tmp2,absVal;

    for(int i=0;i<100000;i++)
    {
        tmp2 = (i%10)/100.f;

        for(myStruct &s : boost::adaptors::reverse(myVector))
        {
            tmp = s.a;
            absVal = fabs(tmp-tmp2);

            if(absVal<0.0001f)
            {
                s.b = 1.5f;
            }
        }

        myStruct s;
        s.a = tmp2;
        myVector.push_back(s);

    }
}

我可以看到,它有 50% 的时间用于比较 absVal

代码是用 -O2 标志编译的,clang-602.0.53。分析是使用 Apple 的 Instruments with Time Profiler 完成的。

【问题讨论】:

  • 也许我们得到了不同的随机数或类似的随机数,但在我的构建中(大约两周前使用 clang-3.7),大部分时间都在 tmpAbs = fabs(tmp-i); 和循环迭代[尽管我使用rbeginrend 重写它,因为在这种情况下我懒得弄清楚如何使用 boost - 我怀疑这会产生很大的不同 - 我希望这就是 boost::adaptor::reverse 无论如何] - 使用 -O3 大约需要 1 秒的时间......
  • 再看一遍逻辑,第一个 if 永远不应该输入... [我刚刚通过在循环末尾添加 assert(0) 证明了这一点 - 编译器完成了整个事情通过删除循环中的一些代码来更快 - 不确定是什么,不在乎]
  • 换句话说,显示您在哪里花费了多少时间的工具无法正常工作。
  • 谢谢@MatsPetersson。上面的代码只是一个例子,实际应用要复杂得多,两个if都可以输入。我正在使用 Apple 的 Instruments with Time Profiler - 你使用哪个工具,所以我可以将结果与同一个工具进行比较?
  • 我使用 linux 的 perf - 我有一种感觉(或类似的东西)是 Apple 产品中 Time Profiler 的“下层”。我希望这更像是“调试信息所说的”的情况,而不是工具混淆哪条指令需要时间。不幸的是,如果您的代码不能真正反映真实的应用程序,那么根据其他代码提出建议是毫无意义的。

标签: c++ optimization vector floating-point comparison


【解决方案1】:

最明显的改进之一是将浮点数与浮点数进行比较,将双精度数与双精度数进行比较。 0.001double0.001f 是浮点数。

这是一个如此明显的改进,编译器可能会默默地为您完成。但分析结果表明它没有。

您确实到处都有类似的问题。 / (static_cast &lt;float&gt; (RAND_MAX/2.)) 看起来特别糟糕:将 RAND_MAX 转换为双精度,然后除以 2.0 并将结果转换回浮点数、浮点除法,所有这些都使用常量。

或者:

static const float scale = 2.f/RAND_MAX;
(float i=0.f;i<1000.f;i+=0.01f)
{
  // ...
  s.b = rand() * scale;

【讨论】:

  • @user2923525:那么编译器已经在编译时转换了值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-28
  • 1970-01-01
  • 1970-01-01
  • 2020-03-03
  • 2012-10-26
  • 1970-01-01
相关资源
最近更新 更多