windows – 为什么在lisp中计算到10亿这么慢?

前端之家收集整理的这篇文章主要介绍了windows – 为什么在lisp中计算到10亿这么慢?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
  1. (defun billion-test ()
  2. (setq i 0)
  3. (loop while (< i 100) do
  4. (setq i (+ i 1))))
  5. (billion-test)
  6. (print "done")

我有上面的Lisp代码,简单地循环到十亿.问题是它确实存在
慢.比我写过的任何琐碎程序都要慢.这是它所花费的时间
运行我有的解释器(gcl和clisp).

  1. Compiled Uncompiled
  2. GNU Common Lisp(gcl) 270-300s 900-960s
  3. Clisp 280-300s 960-1647s

我使用这个Python代码来计算Clisp的时间并使用系统时间进行近似
使用gcl,因为您无法从命令提示符运行它.

  1. import sys
  2. import time
  3. import os
  4.  
  5. start=time.time()
  6. os.system(" ".join(sys.argv[1:]))
  7. stop=time.time()
  8.  
  9. print "\n%.4f seconds\n"%(stop-start)

以下是与其他语言的while循环的比较:

  1. Kawa scheme 220.3350s
  2. Petite chez 112.827s
  3. C# 1.9130s
  4. Ruby 31.045s
  5. Python 116.8600s 113.7090s(optimized)
  6. C 2.8240s 0.0150s(optimized)
  7. lua 84.6970s

我的假设是循环而< condition>做的是Lisp相当于一段时间
环.我对那些1647(25分钟)有些怀疑,我正在看那些东西
时间,它可能会减慢执行速度,但差不多800s?我不知道.
这些结果很难相信.根据Norvig Lisp
比Python快3到85倍.从我得到的东西来看,最合乎逻辑的
这种缓慢执行的解释是Windows中的Clisp和gcl有某种
减慢大迭代的bug.怎么,你问,我不知道?
那么,我的问题是,为什么这么慢?
有没有人得到这样的东西?

更新1:
我运行了Joswigs的程序,得到了这些结果:

  1. compiled uncompiled
  2. gcl 0.8s 12mins
  3. clisp 5mins 18mins

gcl编译程序很好,但clisp给出了这个警告:

  1. ;; Compiling file C:\mine\.cl\test.cl ...
  2. WARNING: in BILLION-TEST in lines 1..8 : FIXNUM-SAFETY is not a
  3. valid OPTIMIZE quality.
  4. 0 errors,1 warning
  5. ;; Wrote file C:\mine\.cl\test.fas
  6.  
  7. ;; clisp
  8. [2]> (type-of 1000000000)
  9. (INTEGER (16777215))
  10.  
  11. ;;gcl
  12. (type-of 1000000000)
  13. FIXNUM

猜猜这可能是花了一分多钟的原因.

更新2:
我以为我会再次尝试另一个实现来确认
它真的是减缓它的bignum比较.我获得了sbcl
对于Windows并再次运行该程序:

  1. * (print most-positive-fixnum)
  2. 536870911
  3.  
  4. * (compile-file "count-to-billion.cl")
  5. ; compiling file "C:/mine/.cl/count-to-billion.cl"
  6. (written 09 OCT 2013 04:28:24 PM):
  7. ; compiling (DEFUN BILLION-TEST ...)
  8. ; file: C:/mine/.cl/count-to-billion.cl
  9. ; in: DEFUN BILLION-TEST
  10. ; (OPTIMIZE (SPEED 3) (SAFETY 0) (DEBUG 0) (FIXNUM-SAFETY 0))
  11. ;
  12. ; caught WARNING:
  13. ; Ignoring unknown optimization quality FIXNUM-SAFETY in:
  14. ; (OPTIMIZE (SPEED 3) (SAFETY 0) (DEBUG 0) (FIXNUM-SAFETY 0))
  15.  
  16. * (load "count-to-billion")

我希望我可以告诉你需要多长时间,但我从来没有看到它的结束.我等了
2个小时,观看了一集吸血鬼日记(呵呵),但还没有结束.
我期待它比Clisp更快,因为它的MOST-POSITIVE-FIXNUM更好
正.我正在保证缓慢的实施点,因为只有gcl可以拉动
跑了不到一分钟.

用gcl运行Rörd的代码

  1. (time (loop with i = 0 while (< i 1000000000) do (incf i)))
  2.  
  3. gcl with Rords's code:
  4. >(load "count-to-billion.cl")
  5. Loading count-to-billion.cl
  6. real-time : 595.667 secs
  7. run time : 595.667 secs
  8.  
  9. >(compile-file "count-to-billion.cl")
  10. OPTIMIZE levels: Safety=0 (No runtime error checking),Space=0,Speed=3
  11. Finished compiling count-to-billion.cl.
  12. #p"count-to-billion.o"
  13.  
  14. >(load "count-to-billion")
  15. Loading count-to-billion.o
  16. real time : 575.567 secs
  17. run time : 575.567 secs
  18. start address -T 1020e400 Finished loading count-to-billion.o
  19. 48

更新3:

这是最后一个,我保证.我试过Rords其他代码

  1. (defun billion-test ()
  2. (loop with i fixnum = 0
  3. while (< i 1000000000) do (incf i)))

令人惊讶的是,它的运行速度与Joswig一样快,不同之处在于关键字fixnum和
有:

gcl的输出

  1. real time : 0.850 secs
  2. run time : 0.850 secs

sbcl的输出(运行大约半秒钟然后吐出来):

  1. debugger invoked on a TYPE-ERROR in thread
  2. #<THREAD "main thread" RUNNING {23FC3A39}>:
  3. The value 536870912 is not of type FIXNUM.

clisp的输出

  1. Real time: 302.82532 sec.
  2. Run time: 286.35544 sec.
  3. Space: 11798673420 Bytes
  4. GC: 21413,GC time: 64.47521 sec.
  5. NIL
>启动时间
>未声明的变量
>全局变量
>没有类型声明
>编译器没有告诉优化
>在32位机器/实现上1000000000可能不是fixnum,请参见变量MOST-POSITIVE-FIXNUM
>可能<与32位机器上的bignum比较 - >最好数到0
>执行缓慢

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

在配备2 Ghz Intel i7的MacBook Air笔记本电脑上的64位LispWorks上,我获得了未经优化的代码,可在2秒内完成.如果我们添加声明,它会更快一些.

  1. (defun billion-test ()
  2. (let ((i 0))
  3. (declare (fixnum i)
  4. (optimize (speed 3) (safety 0) (debug 0))
  5. (inline +))
  6. (loop while (< i 1000000000) do
  7. (setq i (+ i 1)))))
  8.  
  9.  
  10. CL-USER 7 > (time (billion-test))
  11. Timing the evaluation of (BILLION-TEST)
  12.  
  13. User time = 0.973
  14. System time = 0.002
  15. Elapsed time = 0.958
  16. Allocation = 154384 bytes
  17. 0 Page faults
  18. NIL

64位SBCL需要0.3秒.所以它更快.

使用GCL,您应该能够在32位机器上获得更好的结果.在这里,我在32位ARM处理器(Samsung Exynos 5410)上使用GCL.在ARM机器上使用GCL的十亿仍然是一个固定的.

  1. >(type-of 1000000000)
  2.  
  3. FIXNUM
  4.  
  5. >(defun billion-test ()
  6. (let ((i 0))
  7. (declare (fixnum i)
  8. (optimize (speed 3) (safety 0) (debug 0))
  9. (inline +))
  10. (loop while (< i 1000000000) do
  11. (setq i (+ i 1)))))
  12.  
  13. BILLION-TEST
  14.  
  15. >(compile *)
  16.  
  17. Compiling /tmp/gazonk_23351_0.lsp.
  18. Warning:
  19. The OPTIMIZE quality DEBUG is unknown.
  20. End of Pass 1.
  21. End of Pass 2.
  22. OPTIMIZE levels: Safety=0 (No runtime error checking),Speed=3
  23. Finished compiling /tmp/gazonk_23351_0.lsp.
  24. Loading /tmp/gazonk_23351_0.o
  25. start address -T 0x7a36f0 Finished loading /tmp/gazonk_23351_0.o
  26. #<compiled-function BILLION-TEST>
  27. NIL
  28. NIL

现在您可以看到GCL也非常快,即使在较慢的ARM处理器上:

  1. >(time (billion-test))
  2.  
  3. real time : 0.639 secs
  4. run-gbc time : 0.639 secs
  5. child run time : 0.000 secs
  6. gbc time : 0.000 secs
  7. NIL

猜你在找的Windows相关文章