编码实践使编译器/优化器能够制作更快的程序
很多年前,C编译器并不特别聪明。 作为一种解决方法,K&R发明了register关键字,向编译器暗示,将这个变量保存在内部寄存器中可能是一个好主意。 他们还让高等运营商帮助生成更好的代码。
随着时间的推移,编译器逐渐成熟。 他们变得非常聪明,因为他们的流程分析使他们能够更好地决定登记在寄存器中的值,而不是你可能做的。 register关键字变得不重要。
由于别名问题,FORTRAN对于某些操作可能比C更快。 理论上仔细编码,可以绕过这个限制,使优化器能够生成更快的代码。
哪些编码实践可以使编译器/优化器生成更快的代码?
这是一个相关的问题
[编辑]这个问题不是关于整个过程的简介和优化。 假设程序已经正确编写,编译完全优化,测试并投入使用。 您的代码中可能存在一些构造,禁止优化器尽其所能地完成最好的工作。 你可以做什么重构,将删除这些禁令,并允许优化器生成更快的代码?
[编辑]偏移相关链接
写入局部变量而不输出参数! 这对于解决锯齿减速有很大的帮助。 例如,如果你的代码看起来像
void DoSomething(const Foo& foo1, const Foo* foo2, int numFoo, Foo& barOut)
{
for (int i=0; i<numFoo, i++)
{
barOut.munge(foo1, foo2[i]);
}
}
编译器不知道foo1!= barOut,因此每次都必须在循环中重新加载foo1。 直到写入barOut完成,它也不能读取foo2 [i]。 你可以开始讨论有限的指针,但它同样有效(并且更清晰):
void DoSomethingFaster(const Foo& foo1, const Foo* foo2, int numFoo, Foo& barOut)
{
Foo barTemp = barOut;
for (int i=0; i<numFoo, i++)
{
barTemp.munge(foo1, foo2[i]);
}
barOut = barTemp;
}
这听起来很愚蠢,但编译器可以更聪明地处理局部变量,因为它不可能与任何参数在内存中重叠。 这可以帮助您避免可怕的load-hit-store(在此主题中由Francis Boivin提及)。
这里有一个编程实践来帮助编译器创建快速代码 - 任何语言,任何平台,任何编译器,任何问题:
不要使用任何强制甚至鼓励编译器将变量放在内存中的巧妙技巧(包括缓存和寄存器)。 首先编写一个正确和可维护的程序。
接下来,剖析你的代码。
然后,只有这样,您才可能要开始调查告诉编译器如何使用内存的影响。 每次进行1次更改并测量其影响。
预计会感到失望,并且为了小幅的性能改进而必须非常努力地工作。 用于Fortran和C等成熟语言的现代编译器非常非常好。 如果您阅读了一个“技巧”的账户以获得更好的代码性能,请记住,编译器编写者也阅读了它,如果值得这样做,可能会实现它。 他们可能写了你读到的第一个地方。
你通过内存的顺序可能会对性能产生深远的影响,编译器并不擅长弄清楚并修复它。 如果您关心性能,您在编写代码时必须认真考虑缓存区域问题。 例如,C中的二维数组以行优先格式分配。 以列主要格式遍历数组往往会让你有更多的缓存未命中,并使你的程序比处理器绑定更受内存限制:
#define N 1000000;
int matrix[N][N] = { ... };
//awesomely fast
long sum = 0;
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
sum += matrix[i][j];
}
}
//painfully slow
long sum = 0;
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
sum += matrix[j][i];
}
}
链接地址: http://www.djcxy.com/p/86747.html
上一篇: Coding Practices which enable the compiler/optimizer to make a faster program
下一篇: Is inline assembly language slower than native C++ code?