Why is billions calculated so slowly in lisp?

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

I have the code above Lisp which is just one billion. The problem is that it is really slow. Slower than any trivial program I've ever written. This is the time it took me to work with intepreters (gcl and clisp).

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

I used this Python code for Clisp time time and approximated using system time
with gcl , since you cannot start it from the command line.

 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) 

Here is a comparison with loops from other languages:

 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 

My guess is that loop while <condition> do is equivalent to Lisp a while
a loop. I have some doubts about these 1647s(25+ min) , I watched something in this and it could slow down the execution, but almost 800s ? I dont know.
These results are hard to believe. According to Norvig Lisp
3 to 85 times faster than Python . Judging by what I got, the most logical
the explanation for such slow execution is that Clisp and gcl on Windows have some kind of error that slows down large iterations. How, you ask, I don’t know? Sooo, my question is: why so slow ?
Does anyone else get something like this?

UPDATE 1:
I launched the Joswigs program and got the following results:

  compiled uncompiled gcl 0.8s 12mins clisp 5mins 18mins 

gcl compiled the program perfectly, Clisp however gave this warning:

 ;; 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 

Guess that this could be the reason why more than a minute has passed.

UPDATE 2:
I thought I would give another try with a different implementation to confirm that this is really a bignum comparison that slows it down. I got sbcl
for windows and run the program again:

  * (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") 

I would like to tell you how much time has passed, but I have never seen the end of this. I was waiting
2 hours, watched the episode "The Vampire Diaries" (hehe), and he has not finished yet.
I expected it to be faster than Clisp , since its MOST-POSITIVE-FIXNUM , well, is even more positive. I vouch for the slow point of implementation, because only gcl can pull from less than one minute.

Running RΓΆrd code with gcl :

 (time (loop with i = 0 while (< i 1000000000) do (incf i))) gcl with Rords 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 

UPDATE 3:

This is the last, I promise. I tried another Rords code:

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

and, oddly enough, it runs as fast as Joswig, the difference in the keywords fixnum and with :

gcl output:

 real time : 0.850 secs run time : 0.850 secs 

sbcl (ran for about a second and a half and spat it out):

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

Clisp output:

 Real time: 302.82532 sec. Run time: 286.35544 sec. Space: 11798673420 Bytes GC: 21413, GC time: 64.47521 sec. NIL 
+6
source share
1 answer
  • start time
  • undeclared variable
  • global variable
  • type ads
  • the compiler did not say optimize
  • on 32-bit machines / implementations, 1,000,000,000 may not be fixnum, see MOST-POSITIVE-FIXNUM
  • maybe < comparison with bignum on 32-bit machines β†’ better count to 0
  • slow implementation

The 64-bit Common Lisp needs to have larger fixes, and we can use simple fixnum calculations.

On 64-bit LispWorks on a MacBook Air laptop with 2 GHz Intel i7, I get non-optimized code to work for a little less than 2 seconds. If we add ads, it will be a little faster.

 (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 

A 64-bit SBCL requires 0.3 seconds. . It is even faster.

With GCL, you can get the best results on a 32-bit machine. Here I use GCL on a 32-bit ARM processor (Samsung Exynos 5410). A billion with GCL on an ARM machine is still fixed.

 >(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 

Now you can see that the GCL is also pretty fast, even on a slower ARM processor:

 >(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 
+12
source

Source: https://habr.com/ru/post/955511/


All Articles