Hi Matthew,<div><br></div><div>Thanks for your help. I really can't even pretend to understand the make-coroutine code but this is what I'm seeing:</div><div><br></div><div>Original make-coroutine, without stream-ref pre-call => out of memory (1GB) when running (prime-pi 500000)</div>
<div>Original make-coroutine, with stream-ref pre-call => runs (prime-pi 500000) in about .4 sec</div><div>Alternate make-coroutine, with or without stream-ref pre-call => runs (prime-pi 500000) in about 28 sec</div>
<div><br></div><div>All runs from "clean" state.</div><div><br></div><div>-joe</div><div><br><div class="gmail_quote">On Tue, Feb 21, 2012 at 10:25 AM, Matthew Flatt <span dir="ltr"><<a href="mailto:mflatt@cs.utah.edu">mflatt@cs.utah.edu</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I don't know the answer, but here's a piece of the puzzle that might be<br>
relevant.<br>
<br>
Try this alternate `make-coroutine':<br>
<br>
(define (make-coroutine fn)<br>
(let ([cont #f])<br>
(ë ()<br>
(call-with-continuation-prompt<br>
(lambda ()<br>
(if cont<br>
(cont)<br>
(fn (ë () (let/cc k<br>
(set! cont k)<br>
(abort-current-continuation<br>
(default-continuation-prompt-tag)<br>
void))))))))))<br>
<br>
The difference between this one and the one on the web page is that it<br>
uses a prompt to avoid capturing the continuation of the initial call<br>
to a coroutine (i.e., it uses a delimited continuation for the<br>
coroutine). For me, this variant makes `(prime-pi 500000)' work without<br>
``(stream-ref prime-stream (inexact->exact (* 0.1 n)))'.<br>
<br>
My guess is that avoiding capture of continuations converts O(N^2)<br>
space usage into O(N) space for some N-deep forcing of streams. Using<br>
`(stream-ref prime-stream (inexact->exact (* 0.1 n)))', meanwhile,<br>
might similarly avoid an N-deep nesting at the point where O(N^2)<br>
behavior would kick in.<br>
<br>
I haven't studied the code enough to be certain that my explanation is<br>
right, but when I see surprising space consumption with laziness and<br>
undelimited continuations, my first guess is that undelimited<br>
continuations are holding onto too much.<br>
<div><div class="h5"><br>
At Mon, 20 Feb 2012 17:19:02 -0800, Joe Gilray wrote:<br>
> Hi,<br>
><br>
> I created an infinite stream of primes (using this interesting article:<br>
> <a href="http://matthias.benkard.de/journal/116" target="_blank">http://matthias.benkard.de/journal/116</a>)<br>
><br>
> I tried to create a prime-pi function:<br>
><br>
> (define (prime-pi n)<br>
> (let loop-count ([candidate-stream prime-stream])<br>
> (if (> (stream-first candidate-stream) n)<br>
> 0<br>
> (+ (loop-count (stream-rest candidate-stream)) 1))))<br>
><br>
> (prime-pi 500000) grinds and runs out of memory<br>
><br>
> But this little cludge makes it run just fine:<br>
><br>
> (define (prime-pi n)<br>
> (stream-ref prime-stream (inexact->exact (* 0.1 n))) ; cludge added to<br>
> get the stream to pre-create enough primes<br>
> (let loop-count ([candidate-stream prime-stream])<br>
> (if (> (stream-first candidate-stream) n)<br>
> 0<br>
> (+ (loop-count (stream-rest candidate-stream)) 1))))<br>
><br>
> What am I not understanding?<br>
><br>
> Thanks,<br>
> -Joe<br>
</div></div>> ____________________<br>
> Racket Users list:<br>
> <a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/users</a><br>
</blockquote></div><br></div>