我变得有点紧张,因为我无法在不妥协的情况下使我的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的这种指数增长,我有一些问题:
答案 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如此指示。