[comp.sys.xerox] Xerox Quintus Prolog

eric%vax.nr.uninett@TOR.NTA.NO (Eric Monteiro) (01/25/88)

Hello,
I have a problem with Xerox Quintus Prolog :
   I cannot do DEEP recursion.
I've partitioned the disk such that I have maximum space - 65000 pages,
but cannot do deeper than 5-10000 levels of recursion on a clean 
sysout. This is interpreted code, compiled code is of 
magnitude 10 better. (The twoliner test program is :
  addone(I, Max) :- I<Max, J is I+1, addone(J,Max).
  addone(_,_).

  ?- addone(1, 10000).     )

IS THIS A REASONABLE RESULT ?! (or are there ways around).

                                    Grateful for any advice,

                                    Eric Monteiro
                                    eric@vax.nr.uninett
                                       or
                                    Norwegian Computing Center
                                    Forskningsvn. 1B,
                                    Boks 114 Blindern,
                                    N-0314 Oslo 3, 
                                    Norway
         

ok@quintus.UUCP (Richard A. O'Keefe) (01/27/88)

In article <101*eric@vax.nr.uninett>,
eric%vax.nr.uninett@TOR.NTA.NO (Eric Monteiro) writes:
> I have a problem with Xerox Quintus Prolog :
>    I cannot do DEEP recursion.
> I've partitioned the disk such that I have maximum space - 65000 pages,
> but cannot do deeper than 5-10000 levels of recursion on a clean 
> sysout. This is interpreted code, compiled code is of 
> magnitude 10 better. (The twoliner test program is :
>   addone(I, Max) :- I<Max, J is I+1, addone(J,Max).
>   addone(_,_).
> 
>   ?- addone(1, 10000).     )
> 
> IS THIS A REASONABLE RESULT ?! (or are there ways around).
> 
There are several points.
(1) Try writing a recursive function in interpreted Lisp, and see how
    far you get.

(2) In Xerox Quintus Prolog, the interpreter is best regarded as a
    debugging aid.  The recommended approach is to develop code with
    the compiler, falling back on the interpreter when things go
    wrong.  (You can set spy-points on compiled code, so you should
    be able to isolate the problem moderately well before switching
    over to interpreted code.)

(3) Repartitioning the disc isn't going to buy you anything.
    Basically, Lisp and Prolog both want to rule the world.  The
    compromise which was reached is that when you load Prolog it
    grabs 4 Mbytes from Lisp.  When this happens you see a
    message in the Prompt Window that looks something like
    "Grabbing 4Mb from Lisp, this will take a while".  It does.

(4) Of the 4Mb, the first release allocated 1Mb permanently to stack
    frames, and 3Mb to heap and trail.  I am not sure what the 2.0
    release does.  Compiled and interpreted clauses and so on are
    held as normal Lisp objects.

(5) Most interpreters take several stack frames for each interpreted
    procedure call, and the Prolog interpreter is no exception.  Now
    a stack frame is going to take a minimum of 12 bytes (never mind
    why), so if the overhead is N stack frames per interpreted goal,
    the absolute maximum interpreted depth would be about 88,000/N.
    So a ceiling of 10,000 levels of interpreted execution is not
    all that far from the theoretical bound.

(6) Note that the addone/2 predicate is a very very strange one.
    It is not determinate:  *each* invocation of it forces the
    creation of a choice point and the retention of a stack frame.
    If instead one wrote

	addone(I, Max) :- I >= Max.
	addone(I, Max) :- I <  Max, J is I+1, addone(J, Max).

    one would find *no* recursion limit in compiled code because
    this version is tail recursive.

There are three things going on here:
   - Prolog specific: addone/2 is so written that it MUST use up
     stack space rapidly in ANY Prolog system.
   - Quintus specific: we chose to allocate a fixed 1Mbyte stack
     in the 1.5 release (Lisp has a 128kbyte stack).
   - Xerox integration: the problem of integrating another paradigm
     into an open operating system.  For example, we couldn't keep
     on grabbing pages from Lisp, for two reasons:  we want to have
     them contiguous, and we don't want to wipe out Lisp.

I think what we came up with was a reasonable engineering compromise.

The coding style can make an immense difference to the efficiency of
Prolog programs.  I have often found that rewriting a Prolog program
to make it more beautiful and better structured can produce ten-fold
speed-ups and large space savings.   The Prolog Digest might perhaps
be a better forum for questions about Prolog coding style.