2012-07-21 44 views
3

到目前为止,在测试写入相同功能的不同方法的速度时,我一直在使用time函数,通常它可以很好地指示不同函数的相对速度(因为它们通常相差约100k周期)。Lisp:测量功能的性能

虽然试图找到factorial函数的最快方法,但是,time一直缺乏。这些方法似乎不仅仅相差10k-30k周期,而且它们的总体时间也相差大约一半(我猜想这是预期的)。

三个factorial功能:

(defun factorial-recusion (n) ; 1st  
    (if (equal n 1) 
     1 
     (* n (factorial (- n 1))))) 

(defun factorial-loop (n) ; 2nd 
    (let ((solution 1)) 
    (loop for x from n downto 2 
     do (setf solution (* solution x)) 
     finally (return solution)))) 

(defun factorial-do (n)  ; 3rd 
    (let ((solution 1)) 
    (do ((x n (1- x))) 
    ((< x 2) (return solution)) 
     (setf solution (* solution x))))) 

所以,我想我有两个问题:

1)哪些方法factorial应该是最快的(如果有的话实际上是),为什么? 2)如果我想通过一般方法找出更快的功能,那么最好的方法是什么(出于某种原因,我认为LOC是速度的一个不好的指标)?也许有一种方法可以查看Lisp字节码的反汇编?或者,也许有更好,更严格的方式?

我目前在Ubuntu 12.04 x86-64上运行Linux 3.2.0-26,SBCL。

+0

您使用的CL的实现是什么? – JasonFruit 2012-07-21 11:48:15

+0

我正在使用SBCL,对不起! – Soyuz 2012-07-21 11:54:44

回答

5

SBCL不会编译为'字节码'。它编译为本机机器码。

您可以使用DISASSEMBLE反汇编Lisp函数。

一旦数字进入高频范围,您的阶乘函数中的速度就会以数字算术乘法为主。

为了让它更清楚:您使用哪种迭代构造,DO或LOOP,并不重要。大部分时间都花费了倍增。递归版本也没有太大区别。这是一个典型的基准测试问题:很多简单的数字基准测试都是由几个算术运算的运行时间(比如倍数)来决定的。他们不会测量一般语言操作的速度差异(如各种控制流程)。

带有快速bignum库的缓慢Lisp可能会比使用Lisp编写Bignum代码的优化Lisp编译器更快。

+0

哦,哎呀,我把它留在那里。起初,我写了(和......)(返回解决方案),但后来我意识到这是多么愚蠢,反汇编似乎是我需要的,所以我认为这也是测量性能的最好方法吗?回答我的第一个问题?谢谢! – Soyuz 2012-07-21 12:34:26