Bob Koutsky <[EMAIL PROTECTED]> writes:

> Hello,
> 
> I am rather new to lisp, I'm still learning the basics, but I hit on a 
> suprising behaviour of cmucl - I hope that somebody will explain what's 
> the problem and how to avoid it.
> I wrote a simple program to calculate probabilities of various results 
> of dice roll in a RPG game. It is pure brute force - it just checks all 
> possible combinations of number of dies and records what result given 
> combination represents (I know that it is not the most effective 
> method, not even  effective implementation, but that's not the 
> problem). It worked fine, on my machine completes in about eight 
> seconds. Then I tried to improve it a bit, and added element type 
> declarations to the make-array statements, hoping that it will allow 
> the compiler to generate more effective code. However, to my suprise, 
> runtime increased to almost 11 seconds. What is the problems?
> 
> Another problem I have with cmucl: I tried to install it on another 
> machine - PIII, 384MB RAM, 512MB swap, Linux 2.4.19 with some patches 
> (but almost same as the other machine, except for some drivers), same 
> distribution (Gentoo Linux), same version of cmucl (18d, binaries from 
> distribution site) - and it simply does not works. Few moments after 
> startup it says "Segmentation fault" and crashes back to the command 
> line without any more messages. I tried "echo 1 > 
> /proc/sys/vm/overcommit_memory" suggested in the faq, but without 
> success...
> 
> I hope these questions are not too stupid and that somebody will help 
> me :-)
> 
> regards,
> Bob Koutsky
> 
> follows my dice-rolling program with :element-type declarations added:
> 
> (defconstant *sides* 10)
> 
> (let ((r (make-array *sides* :element-type 'fixnum)))
>   (defun check (dice num succ fail botch)
>     ; reset counters
>     (dotimes (i *sides*)
>       (setf (aref r i) 0))
>     ; scan dices
>     (let ((ones 0))
>       (dotimes (i num)
>         (if (= (aref dice i) 0)
>          (incf ones)
>        (progn
>          (loop for j from (aref dice i) downto 1
>                do (incf (aref r j))))))
>       ; record results
>       (dotimes (i *sides*)
>         (cond
>       ((> (aref r i) ones) (incf (aref succ i)))
>       ((and (> ones 0) (= (aref r i) 0)) (incf (aref botch i)))
>       (t (incf (aref fail i))))))))
> 
> (defun increment (dice num)
>    (loop for i from 0 below num
>       do (incf (aref dice i))
>       when (>= (aref dice i) *sides*) do (setf (aref dice i) 0)
>       else do (return-from increment nil)
>       finally (return-from increment t)))
>         (let* ((num 6)
>         (dice  (make-array num :initial-element 0 :element-type 
> 'fixnum))
>         (succ  (make-array *sides* :initial-element 0 :element-type 
> 'fixnum))
>         (fail  (make-array *sides* :initial-element 0 :element-type 
> 'fixnum))
>         (botch (make-array *sides* :initial-element 0 :element-type 
> 'fixnum)))
>    (format t "Start...~%")
>    (loop
>     do (check dice num succ fail botch)
>     until (increment dice num))
>    (princ succ) (princ #\Newline)
>    (princ fail) (princ #\Newline)
>    (princ botch) (princ #\Newline)
>    (quit))

If you replace all occurences of AREF with SVREF you should see a
significant performance increase. With AREFs you must be more specific
in declaring their type in order to help the compiler. I think it can
only optimize access to certain types like

  (SIMPLE-ARRAY (UNSIGNED-BYTE 4) (*)).

You might want to place something like

  (eval-when (:compile-toplevel :execute :load-toplevel)
    (proclaim '(optimize (speed 3)
                         (safety 0)
                         (space 0)
                         (debug 0)
                         (compilation-speed 0))))

at the top of your file (after you've debugged your code). If you do
that CMUCL will help you with lots of hints about why it can't
optimize certain forms and what you can do to help it.

You should also consider using a decent editor which'll help you to
indent your code properly so it's easier to read. Load your code into
Emacs and invoke MARK-WHOLE-BUFFER and INDENT-REGION to see how it
should look like.

Cheers,
Edi.

Reply via email to