From: Daniel H. <dhe...@te...> - 2008-08-26 06:51:51
|
I'm having trouble getting FSet to run on SBCL. http://common-lisp.net/project/fset/ * (require :fset) ... WARNING: COMPILE-FILE warned while performing #<COMPILE-OP NIL {100254D381}> on #<CL-SOURCE-FILE "fset" {100308BCD1}>. debugger invoked on a ASDF:COMPILE-FAILED in thread #<THREAD "initial thread" RUNNING {100240ABE1}>: erred while invoking #<COMPILE-OP NIL {100254D381}> on #<CL-SOURCE-FILE "fset" {100308BCD1}> ... This originates in the following code snippet: <<<<< (defvar Tuple-Keys (vector K0 K1 K2 K3 K4 K5 K6 K7 K8 K9)) (defun Test-Tuple-Operations (i) (let ((tup (tuple)) (m (map)) (typ (type-of Tuple-Keys)) (nkeys (length Tuple-Keys))) ;; <- HERE (print typ) (dotimes (j 100) (let ((key (svref Tuple-Keys (random nkeys))) (val (Make-My-Integer (random 8)))) (setq tup (with tup key val)) (setq m (with m key val)) (unless (equal? m (convert 'map tup)) (error "Tuple `with' failed on iteration ~D" i)) (do-map (k v m) (unless (equal? v (lookup tup k)) (error "Tuple `lookup' failed on iteration ~D" i))))))) >>>>> Where LENGTH has been shadowed as <<<<< ;;; This little oddity exists because of a limitation in Python (that's the ;;; CMUCL compiler). Given a call to `length' on type `(or null simple-vector)', ;;; Python isn't quite smart enough to optimize the call unless we do the case ;;; breakdown for it like this. #+(or cmu scl) (defmacro length (x) (ext:once-only ((x x)) `(if (null ,x) 0 (cl:length ,x)))) #+sbcl (defmacro length (x) (sb-ext::once-only ((x x)) `(if (null ,x) 0 (cl:length ,x)))) >>>>> Questions: - Is this redefined LENGTH still necessary in SBCL? - Why did this pass for the author in SBCL 1.0.3 and 1.0.5, but not for me in 1.0.3, 1.0.5, 1.0.15, or 1.0.19.26 (x86-64) ? - Why does this go away (all versions?) if I insert (declare (optimize (debug 3))) as the first statement in Test-Tuple-Operations ? Any clues would be appreciated. Thanks, Daniel |
From: Paul K. <pk...@gm...> - 2008-08-26 16:55:40
|
On 26-Aug-08, at 2:51 AM, Daniel Herring wrote: > I'm having trouble getting FSet to run on SBCL. > http://common-lisp.net/project/fset/ That sounds like a topic for sbcl-help. > * (require :fset) > ... > WARNING: > COMPILE-FILE warned while performing #<COMPILE-OP NIL > {100254D381}> on > #<CL-SOURCE-FILE "fset" {100308BCD1}>. > > debugger invoked on a ASDF:COMPILE-FAILED in thread #<THREAD "initial > thread" RUNNING {100240ABE1}>: > erred while invoking #<COMPILE-OP NIL {100254D381}> on > #<CL-SOURCE-FILE "fset" {100308BCD1}> > ... The actual warning earlier in the compilation log. That's just ASDF telling you there was a warning, which isn't very useful to figure out *what* went wrong. > Where LENGTH has been shadowed as > <<<<< > ;;; This little oddity exists because of a limitation in Python > (that's the > ;;; CMUCL compiler). Given a call to `length' on type `(or null > simple-vector)', > ;;; Python isn't quite smart enough to optimize the call unless we > do the case > ;;; breakdown for it like this. > #+(or cmu scl) > (defmacro length (x) > (ext:once-only ((x x)) > `(if (null ,x) 0 (cl:length ,x)))) > > #+sbcl > (defmacro length (x) > (sb-ext::once-only ((x x)) > `(if (null ,x) 0 (cl:length ,x)))) >>>>>> > > Questions: > - Is this redefined LENGTH still necessary in SBCL? This isn't a redefinition. Attempting to redefine CL:LENGTH would signal a package lock error. And CL:LENGTH still doesn't do that FSET:LENGTH does. If we inline this type dispatch, where does it stop? We only have three sorts of sequences: vectors, lists and the new generic sequences. More inlining is mostly useful when it opens up new optimisations that hopefully bring the code size back down. Code bloat never is, and I'm not sure this particular case is very common. Moreover, the normal out of line definition doesn't do much more work than that. So inlining that test is mostly useful to save a call. Even if, for FSET, this does provide a sensible improvement, I'm not sure that's true for most code (that passes (or null vector) values around) out there. Either way, is it so hard to (defvar *empty-vector* #())? I don't see the point of using NIL instead of an empty vector; it doesn't even save space! I believe that special case is better asked for explicitly. The proper way to achieve the desired effect would be to shadow CL:LENGTH and define a new LENGTH *function* and declaim it inline or define a compiler macro. > - Why did this pass for the author in SBCL 1.0.3 and 1.0.5, > but not for me in 1.0.3, 1.0.5, 1.0.15, or 1.0.19.26 (x86-64) ? It's just a warning, although without the warning itself it's hard to tell how serious it is. Maybe the author just ignored it. > - Why does this go away (all versions?) if I insert > (declare (optimize (debug 3))) > as the first statement in Test-Tuple-Operations ? Again the actual warning would be useful. Paul Khuong |
From: Tobias C. R. <tc...@fr...> - 2008-08-26 17:00:39
|
Paul Khuong <pk...@gm...> writes: > Either way, is it so hard to (defvar *empty-vector* #())? I don't see > the point of using NIL instead of an empty vector; it doesn't even > save space! FWIW, I sometimes wish that NIL was not only the empty list, but also the empty sequence. This would enable you to write code similiarly to the Maybe Monad on more occasions. -T. |
From: Scott L. B. <Sc...@sy...> - 2008-08-26 21:34:32
|
Quoting Paul Khuong <pk...@gm...>: > On 26-Aug-08, at 2:51 AM, Daniel Herring wrote: > Even > if, for FSET, this does provide a sensible improvement, I'm not sure > that's true for most code (that passes (or null vector) values around) > out there. Agreed. > Either way, is it so hard to (defvar *empty-vector* #())? I don't see > the point of using NIL instead of an empty vector; it doesn't even > save space! It doesn't save space, but comparing against NIL is very fast in all implementations of which I am aware. Dereferencing a special is not, on the other hand, always fast. > I believe that special case is better asked for explicitly. The proper > way to achieve the desired effect would be to shadow CL:LENGTH and > define a new LENGTH *function* and declaim it inline or define a > compiler macro. FSet does in fact shadow CL:LENGTH, as Daniel said ("Where LENGTH has been shadowed as ..."). >> - Why does this go away (all versions?) if I insert >> (declare (optimize (debug 3))) >> as the first statement in Test-Tuple-Operations ? > > Again the actual warning would be useful. Whatever it is, I'm not seeing it in 1.0.15. Odd. -- Scott (the FSet author) |
From: Paul K. <pk...@gm...> - 2008-08-26 22:05:46
|
On 26-Aug-08, at 5:34 PM, Scott L. Burson wrote: > Quoting Paul Khuong <pk...@gm...>: >> >> Either way, is it so hard to (defvar *empty-vector* #())? I don't see >> the point of using NIL instead of an empty vector; it doesn't even >> save space! > > It doesn't save space, but comparing against NIL is very fast in all > implementations of which I am aware. Dereferencing a special is > not, on the other hand, always fast. Testing that a vector's length is zero should be pretty fast too, on any implementation that actually cares about execution speed. Especially these days, I'm fairly certain it's *at best* not a pessimisation to have a distinguished value instead of zero-length vectors. You're adding an, a priori, ill-predictable branch (unlike the type checks) to save a minuscule (nil?) amount of time. >> I believe that special case is better asked for explicitly. The >> proper >> way to achieve the desired effect would be to shadow CL:LENGTH and >> define a new LENGTH *function* and declaim it inline or define a >> compiler macro. > > FSet does in fact shadow CL:LENGTH, as Daniel said ("Where LENGTH > has been shadowed as ..."). The important point is to use a function, not a macro. If FSet did not shadow CL:LENGTH, asdf would have logged an ERROR, not a WARNING. Paul Khuong |
From: Scott L. B. <Sc...@sy...> - 2008-08-26 22:34:40
|
Quoting Paul Khuong <pk...@gm...>: > On 26-Aug-08, at 5:34 PM, Scott L. Burson wrote: >> [C]omparing against NIL is very fast in all implementations of >> which I am aware. Dereferencing a special is not, on the other >> hand, always fast. > > Testing that a vector's length is zero should be pretty fast too, on > any implementation that actually cares about execution speed. Could cause a cache miss, though. Does it really matter? Probably not. But I don't understand why you seem to think this is an important issue. What's wrong with the way I've done it? >> FSet does in fact shadow CL:LENGTH, as Daniel said ("Where LENGTH >> has been shadowed as ..."). > > The important point is to use a function, not a macro. If FSet did not > shadow CL:LENGTH, asdf would have logged an ERROR, not a WARNING. I'm not getting your point. If FSet did not shadow CL:LENGTH, either DEFUN or DEFMACRO would have gotten an error. -- Scott |