自修改代码与编译器优化与重复代码

时间:2013-11-24 01:47:21

标签: c++

我变得有点紧张,因为我无法在不妥协的情况下使我的C ++代码高效。我开始编写一些代码,如下所示

int foo(int a, int b, int c)
{
    int result;
    bool cond1 = bar1(a, b, c);
    bool cond2 = bar2(a, b, c);
    bool cond3 = bar3(a, b, c);
    for (int i = 0; i < 10000; i++)
    {
        int start = 0;
        int end = 10000;
        if (cond1)
            start = max(start, baz1(i));
        else
            start = max(start, baz2(i));
        if (cond2)
            end = min(end, baz1(i));
        else
            end = min(end, baz2(i));
        for (int j = start; j < end; j++)
        {
            if (cond3)
                result += baz3(i, j);
            else
                result -= baz3(i, j);
        }
    }
    return result;
}   

问题是,如何优化它以在循环的每次迭代中不检查条件“cond1,cond2,cond3”。我可以把内部循环写成

...
        if (cond3)
        for (int j = start; j < end; j++)
            result += baz3(i, j);
        else
        for (int j = start; j < end; j++)
            result -= baz3(i, j);

...

将“cond3”的检查次数从10000次降低到10000次检查。但是仍然有29997次冗余检查,为了优化它,我只看到复制循环2 ^ 3 = 8次的选项。由于#loops vs #conditions的这种指数增长,我有一些问题:

  1. 我可以依赖编译器优化器来展开循环吗?
  2. 反对自修改代码的论据是什么,因为在这种情况下不仅会减少程序大小,而且代码也更易于管理。我发现很难相信自C ++发明以来就没有遇到过如上所述的问题。

3 个答案:

答案 0 :(得分:3)

功能指针。使用函数指针 使用3个函数指针,每个条件对应一个。

例如:

  Function_Pointer_Type_Cond1 p_cond_1_function;
  Function_Pointer_Type_Cond2 p_cond_2_function;
  if (bar1(a, b, c))
  {
    p_cond_1_function = baz1;
  }
  else
  {
    p_cond_1_function = baz2;
  }
  if (bar2(a, b, c))
  {
    p_cond_2_function = baz1;
  }
  else
  {
    p_cond_2_function = baz2;
  }
  for (int i = 0; i < 10000; i++)
  {
    int start = 0;
    int end = 10000;
    start = max(start, (*p_cond_1_function)(i));
    end   = min(end,   (*p_cond_2_function)(i));
    // ...
  }

使用函数指针可以删除“if”语句。您可以在循环之前分配函数指针,因为函数在for循环内不会更改。

有关函数指针的更多信息,请在Web上搜索“C ++ FAQ函数指针”或在StackOverflow中搜索“C ++函数指针”。

答案 1 :(得分:2)

卸压。

做一些基准测试,但我的预测是你的代码很好,因为它是最优的,即使是最简单的分支预测形式,这将使所有这些测试几乎免费,当然比函数调用便宜,更不用说了间接函数调用。

如果baz1和baz2是微不足道的,请确保它们可以内联。如果它们不是微不足道的话,几乎总是成功预测的分支是无关紧要的。

答案 2 :(得分:0)

您可以轻松删除第三个if

只要总是在循环中添加,并在循环之后否定结果,在返回之前,如果cond3如此指示。