(defun billion-test ()
  (setq i 0)
  (loop while (< i 100) do
    (setq i (+ i 1))))
(billion-test)
(print "done")

我有上面的Lisp代码,可以循环到十亿。问题是真的
慢的。比我写过的任何琐碎程序都要慢。这些是花了很多时间
用我有的解释器(gcl和clisp)运行。
                       Compiled  Uncompiled
GNU Common Lisp(gcl)    270-300s  900-960s
Clisp                   280-300s  960-1647s

我使用此Python代码为Clisp设置了时间,并以系统时间作为近似时间
使用gcl,因为您无法从命令提示符下运行它。
import sys
import time
import os

start=time.time()
os.system(" ".join(sys.argv[1:]))
stop=time.time()

print "\n%.4f seconds\n"%(stop-start)

这是与其他语言的while循环的比较:
Kawa scheme     220.3350s
Petite chez     112.827s
C#              1.9130s
Ruby            31.045s
Python          116.8600s        113.7090s(optimized)
C               2.8240s          0.0150s(optimized)
lua             84.6970s

我的假设是loop while <condition> doLispwhile等效项
环形。我对那些1647s(25+ min)有疑问,我当时在看一些东西
时间,这可能会减慢执行速度,但是几乎是800s吗?我不知道。
这些结果令人难以置信。根据Norvig LispPython快3到85倍。从我得到的结果来看,最合乎逻辑的
这种缓慢执行的原因是Clisp中的gclWindows有某种
导致大型迭代速度减慢的错误。你怎么问,我不知道?
太好了,我的问题是为什么这么慢?
还有其他人得到这样的东西吗?

更新1:
我运行了Joswigs的程序,并得到了以下结果:
      compiled   uncompiled
gcl    0.8s       12mins
clisp  5mins      18mins
gcl可以很好地编译程序,但是clisp给出了以下警告:
;; Compiling file C:\mine\.cl\test.cl ...
WARNING: in BILLION-TEST in lines 1..8 : FIXNUM-SAFETY is not a
valid OPTIMIZE quality.
 0 errors, 1 warning
;; Wrote file C:\mine\.cl\test.fas

     ;; clisp
     [2]> (type-of 1000000000)
     (INTEGER (16777215))

     ;;gcl
     (type-of 1000000000)
      FIXNUM

猜猜这可能是花了超过一分钟的时间的原因。

更新2:
我以为我会再尝试一下另一种实现,只是为了确认
确实是bignum比较会减慢速度。我获得了sbcl对于Windows,然后再次运行该程序:
 * (print most-positive-fixnum)
   536870911

 * (compile-file "count-to-billion.cl")
   ; compiling file "C:/mine/.cl/count-to-billion.cl"
   (written 09 OCT 2013 04:28:24 PM):
   ; compiling (DEFUN BILLION-TEST ...)
   ; file: C:/mine/.cl/count-to-billion.cl
   ; in: DEFUN BILLION-TEST
   ;     (OPTIMIZE (SPEED 3) (SAFETY 0) (DEBUG 0) (FIXNUM-SAFETY 0))
   ;
   ; caught WARNING:
   ;   Ignoring unknown optimization quality FIXNUM-SAFETY in:
   ;    (OPTIMIZE (SPEED 3) (SAFETY 0) (DEBUG 0) (FIXNUM-SAFETY 0))

 * (load "count-to-billion")

我希望我能告诉您花费了多长时间,但我从未看到结局。我等着
2小时,观看了《吸血鬼日记》(呵呵)的一集,但还没有结束。
我期望它比Clisp更快,因为它的MOST-POSITIVE-FIXNUM更好
积极的。我保证缓慢的实现点,因为只有gcl可以拉
不到一分钟的运行时间。

使用gcl运行Rörd的代码:
(time (loop with i = 0 while (< i 1000000000) do (incf i)))

gcl with Rords's code:
>(load "count-to-billion.cl")
Loading count-to-billion.cl
real-time : 595.667 secs
run time : 595.667 secs

>(compile-file "count-to-billion.cl")
OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, Speed=3
Finished compiling count-to-billion.cl.
#p"count-to-billion.o"

>(load "count-to-billion")
Loading count-to-billion.o
real time : 575.567 secs
run time  : 575.567 secs
start address -T 1020e400 Finished loading count-to-billion.o
48

更新3:

我保证这是最后一个。我尝试了Rords其他代码:
(defun billion-test ()
  (loop with i fixnum = 0
        while (< i 1000000000) do (incf i)))

令人惊讶的是,它的运行速度与Joswig一样快,不同之处在于关键字fixnumwith:
gcl的输出:
real time : 0.850 secs
run time  : 0.850 secs
sbcl的输出(运行了大约半秒钟,然后吐了出来):
debugger invoked on a TYPE-ERROR in thread
#<THREAD "main thread" RUNNING {23FC3A39}>:
  The value 536870912 is not of type FIXNUM.
clisp的输出:
Real time: 302.82532 sec.
Run time: 286.35544 sec.
Space: 11798673420 Bytes
GC: 21413, GC time: 64.47521 sec.
NIL

最佳答案

  • 启动时间
  • 未声明的变量
  • 全局变量
  • 没有类型声明
  • 编译器未告知要优化
  • 在32位机器/实现上的
  • 1000000000可能不是fixnum,请参见变量MOST-POSITIVE-FIXNUM
  • 可能与32位机器上的bignum进行<比较->更好地将其计数为0
  • 执行缓慢

  • 64位Common Lisp应该具有更大的fixnum,我们可以使用简单的fixnum计算。

    在具有2 GHz Intel i7的MacBook Air笔记本电脑上的64位LispWorks上,我获得了未经优化的代码,可在不到2秒的时间内运行。如果添加声明,它会更快一些。
    (defun billion-test ()
      (let ((i 0))
        (declare (fixnum i)
                 (optimize (speed 3) (safety 0) (debug 0))
                 (inline +))
        (loop while (< i 1000000000) do
              (setq i (+ i 1)))))
    
    
    CL-USER 7 > (time (billion-test))
    Timing the evaluation of (BILLION-TEST)
    
    User time    =        0.973
    System time  =        0.002
    Elapsed time =        0.958
    Allocation   = 154384 bytes
    0 Page faults
    NIL
    

    64位SBCL需要0.3秒。 所以它甚至更快。

    使用GCL,您应该能够在32位计算机上获得更好的结果。在这里,我在32位ARM处理器(Samsung Exynos 5410)上使用GCL。 ARM机器上的GCL十亿仍然是一个固定数字。
    >(type-of 1000000000)
    
    FIXNUM
    
    >(defun billion-test ()
      (let ((i 0))
        (declare (fixnum i)
                 (optimize (speed 3) (safety 0) (debug 0))
                 (inline +))
        (loop while (< i 1000000000) do
              (setq i (+ i 1)))))
    
    BILLION-TEST
    
    >(compile *)
    
    Compiling /tmp/gazonk_23351_0.lsp.
    Warning:
    The OPTIMIZE quality DEBUG is unknown.
    End of Pass 1.
    End of Pass 2.
    OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, Speed=3
    Finished compiling /tmp/gazonk_23351_0.lsp.
    Loading /tmp/gazonk_23351_0.o
    start address -T 0x7a36f0 Finished loading /tmp/gazonk_23351_0.o
    #<compiled-function BILLION-TEST>
    NIL
    NIL
    

    现在您可以看到,即使在较慢的ARM处理器上,GCL的速度也相当快:
    >(time (billion-test))
    
    real time       :      0.639 secs
    run-gbc time    :      0.639 secs
    child run time  :      0.000 secs
    gbc time        :      0.000 secs
    NIL
    

    关于windows - 为什么计数到十亿卢比这么慢?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19252947/

    10-11 01:18