I'm attempting to write a lisp version of the partial sums
benchmark for the Great Computer Langauge Shootout (
http://shootout.alioth.debian.org/debian/benchmark.php?test=partialsums&lang=all
), and I've come across a snag when it comes to floating point types
and/or rounding modes. The code below gives the correct results with
GCL, but incorrect results for CMUCL. I'm assuming this is because GCL
defaults to selecting the native double precision floating point
numbers for its floating point computations, while CMUCL might be using
single precision numbers, or somesuch. What's the idiomatic lisp way
to get a consistant behavior? Is there a global variable I should
diddle? I suppose using "declare" is the right answer, but it isn't
obvious to me how to decorate the variables inside of a "do" macro.
Thanks,
Greg Buchholz
(defmacro psum (name f)
`(format t "~,9F~A~A~%"
(do ((k 1.0 (+ k 1.0))
(sum 0.0 (+ sum ,f)))
((> k n) sum))
#\tab ,name))
(defun main ()
(let* ((args #+sbcl sb-ext:*posix-argv*
#+cmu extensions:*command-line-strings*
#+gcl si::*command-args*)
(n (parse-integer (car (last args)))))
(psum "(2/3)^k" (expt (/ 2.0 3.0) (- k 1.0)))
(psum "k^-0.5" (/ 1.0 (sqrt k)))
(psum "1/k(k+1)" (/ 1.0 (* k (+ 1.0 k))))
(psum "Flint Hills" (let ((s (sin k)))
(/ 1.0 (* (* k k k) (* s s)))))
(psum "Cookson Hills" (let ((c (cos k)))
(/ 1.0 (* (* k k k) (* c c)))))
(psum "Harmonic" (/ 1.0 k))
(psum "Riemann Zeta" (/ 1.0 (* k k)))
(let ((a -1.0))
(psum "Alternating Harmonic"
(progn (setf a (- a))
(/ a k))))
(let ((a -1.0))
(psum "Gregory"
(progn (setf a (- a))
(/ a (1- (* 2.0 k))))))))
Wade Humeniuk wrote:
> The simplest thing I can think of is to do
Ah. That does it.
Thanks,
Greg Buchholz
From: Pierpaolo BERNARDI
Subject: Re: default float point types (GCL vs CMUCL)
Date:
Message-ID: <op.s99yzag8xbm8ci@eraora>
On Sun, 28 May 2006 20:05:12 +0200, Greg Buchholz <················@yahoo.com> wrote:
> Is there a global variable I should diddle?
*READ-DEFAULT-FLOAT-FORMAT*
--
Anything below this line is being added by the newsserver
Inviato da X-Privat.Org - Registrazione gratuita http://www.x-privat.org/join.php
>>>>> "Greg" == Greg Buchholz <················@yahoo.com> writes:
Greg> I'm attempting to write a lisp version of the partial sums
Greg> benchmark for the Great Computer Langauge Shootout (
Greg> http://shootout.alioth.debian.org/debian/benchmark.php?test=partialsums&lang=all
Greg> ), and I've come across a snag when it comes to floating point types
Greg> and/or rounding modes. The code below gives the correct results with
Greg> GCL, but incorrect results for CMUCL. I'm assuming this is because GCL
Greg> defaults to selecting the native double precision floating point
Greg> numbers for its floating point computations, while CMUCL might be using
Greg> single precision numbers, or somesuch. What's the idiomatic lisp way
Greg> to get a consistant behavior? Is there a global variable I should
Greg> diddle? I suppose using "declare" is the right answer, but it isn't
Greg> obvious to me how to decorate the variables inside of a "do" macro.
GCL uses the following formats for floating point numbers:
GCL Machine
long-float double precision
double-float double precision
single-float double precision
short-float single precision
CMUCL Machine
long-float double precision
double-float double precision
single-float single precision
short-float single precision
Your code has lots of single-float numbers (if you didn't change
*read-default-float-format*, as mentioned elsewhere), so you'll get
different results.
Ray
To add to the other replies, you can put 'declare' into 'do' this way:
(do ((k 1.0d0 (+ k 1.0d0))
(sum 0.0d0 (+ sum (the double-float ,f))))
((> k n) sum))
(declare (double-float k sum))
[body])
Don't forget to declare n [maybe coerce it to double-float?].
Wrap (the double-float ...) around (sqrt k),
because Lisp can't assume the return type of sqrt is
more precise than 'complex': Lisp doesn't "know" your k
is always non-negative. For the same reason,
wrap (the double-float ...) around the expt example,
put (declare (double-float s)) after the line where s is defined,
and similarly for c.
Finally, put
(declaim (optimize speed))
at the top of the file.
···············@yahoo.com <···············@yahoo.com> wrote:
> To add to the other replies, you can put 'declare' into 'do' this way:
>
> (do ((k 1.0d0 (+ k 1.0d0))
> (sum 0.0d0 (+ sum (the double-float ,f))))
> ((> k n) sum))
> (declare (double-float k sum))
> [body])
>
> Don't forget to declare n [maybe coerce it to double-float?].
> Wrap (the double-float ...) around (sqrt k),
> because Lisp can't assume the return type of sqrt is
> more precise than 'complex': Lisp doesn't "know" your k
> is always non-negative.
An implementation can reasonably infer that K is always a positive
double-float without the added declarations, since it's one at the
start of the loop, and is only incremented (by a positive d-f) on
further iterations. (At least SBCL does this. CMUCL might not, since
has some trouble dealing with non-integer induction variables).
--
Juho Snellman
From: Shyamal Prasad
Subject: [OT] Re: default float point types (GCL vs CMUCL)
Date:
Message-ID: <87pshvl3to.fsf@turtle.local>
>>>>> "Greg" == Greg Buchholz <················@yahoo.com> writes:
Greg> I'm attempting to write a lisp version of the partial
Greg> sums benchmark for the Great Computer Langauge Shootout (
Greg> http://shootout.alioth.debian.org/debian/benchmark.php?test=partialsums&lang=all
Co-incidentally, I made a contribution Sunday morning myself for
exactly the same problem. (a jet lag thing :-)
I see you've solved your problem with double-floats, but I'm curious
if you are attempting any more of the open Lisp benchmarks.
My contribution was not nearly as succint as yours because I wrote
each loop one at a time and optimized to match the gcc version's
performance (I'm within a few percent on my old Pentium 600 Mhz
laptop, but on my powerpc G4 desktop SBCL simply doesn't seem to cut
it).
Cheers!
Shyamal
Shyamal Prasad wrote:
> I see you've solved your problem with double-floats, but I'm curious
> if you are attempting any more of the open Lisp benchmarks.
I don't have any immediate plans to. Looks like there's a few
tests that are already written, but just need some tweaking to work
correctly on the Shootout's machines (both "partial-sums" an
"recursive" fail with CMUCL on the Debian machine, while
"cheap-concurrency" and "mandelbrot" fail on SBCL). And we'd need to
convince management to install something like CL-PPCRE to do the regex
benchmark.
> My contribution was not nearly as succint as yours because I wrote
> each loop one at a time and optimized to match the gcc version's
> performance
Yeah, I just copied the C++ version, including the ugly scope
breaking macros. But, the shootout is about speed, not elegance,
right?
Greg
From: ··············@ericsson.com
Subject: Re: default float point types (GCL vs CMUCL)
Date:
Message-ID: <zmgxvbgz.fsf@ericsson.com>
"Greg" == Greg Buchholz <················@yahoo.com> writes:
Greg> to work correctly on the Shootout's machines (both
Greg> "partial-sums" an "recursive" fail with CMUCL on the Debian
Greg> machine, while "cheap-concurrency" and "mandelbrot" fail on
Greg> SBCL).
Hmmm...it seems CMUCL is broken in some way on those machines. I tend
to use SBCL so I'm not sure what that error means.
The SBCL lisp failures seem to be coding faults. I'm guessing from a
very cursory look that mandelbrot fails because of formatting the
fixnum to a char stream. cheap-concurrency might be running into a
thread limit as far as I recall; I could swear I read someplace that
SBCL can only do 500 or some such number of thread allocs at a
time by default.....
Greg> And we'd need to convince management to install
Greg> something like CL-PPCRE to do the regex benchmark.
It's a debian machine. apt-get install cl-ppcre :-)
Greg> But, the shootout is about speed, not elegance, right?
I hope so :) But its vaguely entertaining just looking at all the code
there.
Cheers!
Shyamal