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
