自修改代码vs编译器优化vs重复代码 我变得有点紧张,因为我不能使我的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; } intfoo(inta,intb,intc) { int结果; bool cond1=bar1(a,b,c); bool cond2=bar2(a,b,c); bool cond3=bar3(a,b,c); 对于(int i=0;i
问题是,如何优化它,以避免在循环的每次迭代中检查条件“cond1,cond2,cond3”。我可以把内部循环写成自修改代码vs编译器优化vs重复代码 我变得有点紧张,因为我不能使我的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; } intfoo(inta,intb,intc) { int结果; bool cond1=bar1(a,b,c); bool cond2=bar2(a,b,c); bool cond3=bar3(a,b,c); 对于(int i=0;i,c++,C++,问题是,如何优化它,以避免在循环的每次迭代中检查条件“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);
...
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);
...
。。。
如果(第3条)
对于(int j=开始;j<结束;j++)
结果+=baz3(i,j);
其他的
对于(int j=开始;j<结束;j++)
结果-=baz3(i,j);
...
这将“cond3”的检查次数从10000次减少到10000次。但是仍然有29997个冗余检查,为了优化它,我只看到复制循环2^3=8次的选项。由于循环与条件的指数增长,我有一些问题:
函数指针。使用函数指针。
使用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));
// ...
}
Function\u Pointer\u Type\u Cond1 p\u Cond1\u Function;
函数(指针)类型(Cond2 p)Cond2(函数);;
if(bar1(a,b,c))
{
p_cond_1_函数=baz1;
}
其他的
{
p_cond_1_函数=baz2;
}
if(bar2(a,b,c))
{
p_cond_2_函数=baz1;
}
其他的
{
p_cond_2_函数=baz2;
}
对于(int i=0;i<10000;i++)
{
int start=0;
int end=10000;
开始=最大值(开始,(*p_cond_1_函数)(i));
end=min(end,(*p_cond_2_函数)(i));
// ...
}
使用函数指针可以删除“if”语句。由于函数在for
循环中不会更改,因此可以在循环之前指定函数指针
有关函数指针的详细信息,请在web上搜索“C++常见问题解答函数指针”,或在StackOverflow中搜索“C++函数指针” 释放压力
做一些基准测试,但我的预测是,您的代码很好,因为即使是最简单的分支预测形式,它也会使所有这些测试几乎免费,而且肯定比函数调用便宜,更不用说间接函数调用了
如果baz1和baz2很简单,请确保它们可以内联。如果它们不是微不足道的,那么几乎总是成功预测的分支是无关紧要的。如果,您可以轻松删除第三个
只要总是在循环内做加法,在循环结束后,在返回之前,对结果求反,如果cond3是这样指出的。你看过任何编译器的输出代码吗?反对自修改代码的论点大概在40年前就有了很好的阐述——这使得代码有缺陷且效率低下。如果编译器能够确定cond1
,cond2
和cond3
在循环体中是不变的,它可能会在高优化级别上优化它的垃圾。但目前的代码设计得很糟糕。您需要性能、可移植性还是可维护性?选择任意两个。您最多有8个变体。如果您非常担心性能,您可以编写整个例程的8个独立版本,并选择执行哪个版本。在某种程度上,它比所有的if测试都不那么晦涩。不,我没有看编译器的输出代码。我已经读到过级别-O3展开循环,但我对此表示怀疑,因为在这个例子中,版本的数量是指数级的。代码如何变得有缺陷和低效?我只看到更多可维护和小规模的代码,并在必要时编写8个不同版本的例程。至于性能、可移植性和可维护性,Java在运行时不是或者应该能够获得这样的效率吗?嗯,也许我没有告诉你,“baz”函数也可以是内联的,它们是三个算术运算,因此完整的调用过程比“if”更低效检查。@user2275809如果不进行测量,很难明确指出函数调用比测试和分支更昂贵。@user2275809 lambda不是有效的本地内联函数吗(如果编译器认为它们符合条件)?