Chisheng Huang <[EMAIL PROTECTED]> writes:

> Thanks a lot for pointing this out.  The original TEST1 did not mimic
> the original situation as well as I thought.  Here is another try without
> using RANDOM:
> 
> (defun test11 (xmin)
>   (declare (single-float xmin)
>          (optimize (safety 0) (speed 3)))
>   (let ((x-ht (make-hash-table))
>       (input (make-array 5
>                          :element-type 'single-float
>                          :initial-contents '(1.0 2.0 3.0 4.0 5.0))))
>     (declare (hash-table x-ht)
>            (type (simple-array single-float 1) input))
>     (flet ((get-x-index (x)
>            (declare (single-float x))
>            (let ((index (gethash x x-ht nil)))
>              (unless index
>                (setf index
>                      (setf (gethash x x-ht)
>                            (the fixnum (truncate (- x xmin))))))
>              index)))
>       (loop for x of-type single-float across input
>           do (print (get-x-index x))))))
> 
> Compiling TEST11 generated the following note:
> 
> ; In: LAMBDA (XMIN)
> 
> ;   (LOOP FOR X OF-TYPE SINGLE-FLOAT ...)
> ; --> BLOCK LET ANSI-LOOP::LOOP-BODY TAGBODY ANSI-LOOP::LOOP-REALLY-DESETQ 
> ; ==>
> ;   (SETQ X (AREF #:G4 #:G5))
> ; Note: Doing float to pointer coercion (cost 13) to X.
> ; 
> ; Compiling Top-Level Form: 
> 
> ; Compilation unit finished.
> ;   1 note
> 
> Looks like the compiler doesn't trust my declaratioin?

SINGLE-FLOAT numbers have two internal representations: boxed and
unboxed; the type declaration does not differ them. If the compiler
passes a number to an external function (with a full call), or
stores/takes it to/from a non-specialized location (a list, a vector,
not specialized for storing SINGLE-FLOATs, or a variable, which might
contain objects of other types), it must box the number; if it stores
the number in a specialized array -- the number must be unboxed; in
other cases it is free to select the most efficient representation. In
TEST111 you take a value out of a specialized vector -- this produces
an unboxed result, then there are two calls of GETHASH, requiring
boxed argument, and a simple arithmetic operation -, which may work
with an unboxed number. So: two uses of boxed numbers, and two of
unboxed. Nothing strange, that the compiler selects the boxed
representation for X, and unboxes it when necessary; and because
there is a boxing operation between taking an element out from INPUT
and calling GETHASH, it emits a note.

> Yet another try is TEST111, using MAP, instead of LOOP, at the end:
> 
> (defun test111 (xmin)
>   (declare (single-float xmin)
>          (optimize (safety 0) (speed 3)))
>   (let ((x-ht (make-hash-table))
>       (input (make-array 5
>                          :element-type 'single-float
>                          :initial-contents '(1.0 2.0 3.0 4.0 5.0))))
>     (declare (hash-table x-ht)
>            (type (Simple-Array Single-Float 1) input))
>     (flet ((get-x-index (x)
>            (declare (single-float x))
>            (let ((index (gethash x x-ht nil)))
>              (unless index
>                (setf index
>                      (setf (gethash x x-ht)
>                            (the fixnum (truncate (- x xmin))))))
>              index)))
>       (map nil
>          #'(lambda (x)
>              (declare (single-float x))
>              (print (get-x-index x)))
>          input))))
>
> Compiling TEST111 does not generate any efficiency note!  I have
> absolutely no idea why.

Looks like CMUCL does not open-code MAP, so there is a hidden boxing
inside MAP. Under SBCL this code causes the same note as above. BTW,
TEST111 will be more efficient, if you use (SIMPLE-ARRAY T 1) for
INPUT :-).

I'd recommend you to use profiler to measure efficiency of your code,
instead of just relying compiler notes. The code, being compiled
silently, might be the least efficient.

-- 
Regards,
Alexey Dejneka

"Alas, the spheres of truth are less transparent than those of
illusion." -- L.E.J. Brouwer

Reply via email to