Optimization 在尾部呼叫优化(TCO)后衡量性能
我知道那是什么。我的问题是:- 1.)如果我编写的代码适合尾部调用优化(函数[recursive function]中的最后一条语句仅为函数调用,没有其他操作),那么我需要设置任何优化级别,以便编译器实现TCO。编译器将以何种优化模式执行TCO,空间或时间的优化器 2.)如何找出哪些编译器(MSVC、gcc、ARM-RVCT)支持TCO 3.)假设某个编译器执行了TCO,那么我们启用它,如何才能发现编译器实际执行了TCO?代码大小会告诉它还是执行它所花费的周期会告诉它,或者两者都会告诉它Optimization 在尾部呼叫优化(TCO)后衡量性能,optimization,Optimization,我知道那是什么。我的问题是:- 1.)如果我编写的代码适合尾部调用优化(函数[recursive function]中的最后一条语句仅为函数调用,没有其他操作),那么我需要设置任何优化级别,以便编译器实现TCO。编译器将以何种优化模式执行TCO,空间或时间的优化器 2.)如何找出哪些编译器(MSVC、gcc、ARM-RVCT)支持TCO 3.)假设某个编译器执行了TCO,那么我们启用它,如何才能发现编译器实际执行了TCO?代码大小会告诉它还是执行它所花费的周期会告诉它,或者两者都会告诉它 -AD
-AD如果您想让编译器进行尾部调用优化,只需检查 a) 将在哪个优化级别执行的编译器的文档;或 b) 检查asm,如果函数将调用自身(你甚至不需要大的asm知识来再次发现函数的符号) 如果你真的想要尾部递归,我的问题是:
你为什么不自己做尾部呼叫移除呢?它只意味着删除递归,如果它是可删除的,那么编译器不仅可以在低级别上,而且在算法级别上,您也可以将它直接编程到代码中(它只意味着进行循环,而不是调用自己)。如果您希望编译器进行尾部调用优化,检查一下 a) 将在哪个优化级别执行的编译器的文档;或 b) 检查asm,如果函数将调用自身(你甚至不需要大的asm知识来再次发现函数的符号) 如果你真的想要尾部递归,我的问题是:
你为什么不自己做尾部呼叫移除呢?它只意味着删除递归,如果它是可删除的,那么编译器不仅可以在低级别上删除它,还可以在算法级别上删除它,您可以将它直接编程到代码中(它只意味着进行循环而不是调用自己)。大多数编译器支持TCO,这是一种相对古老的技术。至于如何使用特定的编译器启用它,请查看编译器的文档。gcc将在除-O1之外的每个优化级别启用优化,我认为具体的选项是
-fooptimize sibling calls
。至于如何判断编译器是否在进行TCO,请查看汇编程序输出(gcc-S
)或反汇编目标代码。大多数编译器都支持TCO,这是一种相对较旧的技术。至于如何使用特定的编译器启用它,请查看编译器的文档。gcc将在除-O1之外的每个优化级别启用优化,我认为具体的选项是-fooptimize sibling calls
。至于如何判断编译器如何/是否在执行TCO,请查看汇编程序输出(gcc-S
)或反汇编目标代码
确定是否正在发生尾部调用的一种方法是查看是否可以强制堆栈溢出。使用VC++2005 Express Edition,以下程序不会产生堆栈溢出,即使其结果很快超过了long double的容量,您也可以看出,当发生TCO时,所有迭代都在处理中:
/* FibTail.c 0.00 UTF-8 dh:2008-11-23
* --|----1----|----2----|----3----|----4----|----5----|----6----|----*
*
* Demonstrate Fibonacci computation by tail call to see whether it is
* is eliminated through compiler optimization.
*/
#include <stdio.h>
long double fibcycle(long double f0, long double f1, unsigned i)
{ /* accumulate successive fib(n-i) values by tail calls */
if (i == 0) return f1;
return fibcycle(f1, f0+f1, --i);
}
long double fib(unsigned n)
{ /* the basic fib(n) setup and return. */
return fibcycle(1.0, 0.0, n);
}
int main(int argc, char* argv[ ])
{ /* compute some fibs until something breaks */
int i;
printf("\n i fib(i)\n\n");
for (i = 1; i > 0; i+=i)
{ /* Do for powers of 2 until i flips negative
or stack overflow, whichever comes first */
printf("%12d %30.20LG \n", i, fib((unsigned) i) );
}
printf("\n\n");
return 0;
}
/*FibTail.c 0.00UTF-8 dh:2008-11-23
* --|----1----|----2----|----3----|----4----|----5----|----6----|----*
*
*通过尾部调用演示斐波那契计算,看看它是否正确
*通过编译器优化消除了这一问题。
*/
#包括
长双周期(长双f0、长双f1、无符号i)
{/*通过尾部调用累积连续的fib(n-i)值*/
如果(i==0)返回f1;
返回周期(f1,f0+f1,--i);
}
长双fib(无符号n)
{/*基本fib(n)设置和返回*/
返回周期(1.0,0.0,n);
}
int main(int argc,char*argv[])
{/*计算一些谎言,直到有东西破裂*/
int i;
printf(“\n i fib(i)\n\n”);
对于(i=1;i>0;i+=i)
{/*对2的幂进行运算,直到我翻转负数为止
或堆栈溢出,以先到者为准*/
printf(“%12d%30.20LG\n”,i,fib((未签名)i));
}
printf(“\n\n”);
返回0;
}