Hello,

rif <[EMAIL PROTECTED]> writes:

> In a program I'm writing, the closure returned by the following
> function is taking essentially all the runtime:
> 
> (defun make-cg-multiplier (dataset pointset sigma)
>   (declare (type dataset dataset)
>            (type pointset pointset)
>            (type double-float sigma))
>   (let ((s^2 (the double-float (* sigma sigma)))
>         (n (the fixnum (veclen pointset))))
>     #'(lambda (x)
>         (declare (type df-vec x))
>         (unless (= (veclen x) n)
>           (error "The x vector and the dataset are not the same size."))
>         (let ((result-vec (df-array n))
>               (result-entry 0.0d0))
>           (declare (type double-float result-entry))
>           (fixtimes (i1 n)
>              (fixfor (i2 i1 n)
>                 (setf result-entry

CMUCL prefers bindings to assignments. Replace this SETF with LET.

>                       (the double-float
>                         (exp (- (/ (distance (datapoint dataset (aref pointset i1))
>                                              (datapoint dataset (aref pointset i2)))
>                                    s^2)))))
>                 (if (= i1 i2)
>                     (incf (aref result-vec i1) (* (aref x i1) result-entry))
>                     (progn
>                       (incf (aref result-vec i2) (* (aref x i1) result-entry))
>                       (incf (aref result-vec i1) (* (aref x i2) result-entry))))))
>           result-vec))))
> 
> 
> When I compile this function (speed 3, safety and debug 0), one of the
> compile-time notes is:
> 
> ;   #'(LAMBDA (X)
> ;       (DECLARE #)
> ;       (UNLESS # #)
> ;       (LET #
> ;         # ..))
> ; Note: Doing float to pointer coercion (cost 13), for:
> ;     The second argument of CLOSURE-INIT.
> 
> I don't know what this means.

The value of S^2 is boxed before putting into the closure.

> I'm vaguely guessing from the
> description that it's something that only happens once per call of the
> closure,

yes

> in which case it's fine.  But I'd like to know what it is,
> and also make 100% sure that it's not in the inner loop.

(compile-file "foo.lisp" :trace-file t) and look in foo.trace. The
first closure blocks looks similar to:

IR2 block start c183
0: XEP-ALLOCATE-FRAME {# NIL} 
1: SETUP-CLOSURE-ENVIRONMENT {#} => t36[EAX] 
2: CLOSURE-REF t36[EAX] {0} => t37[ECX] 
3: CLOSURE-REF t36[EAX] {1} => t38[EBX] 
4: CLOSURE-REF t36[EAX] {2} => t39[ESI] 
5: CLOSURE-REF t36[EAX] {3} => t40[EAX] 
6: MOVE t41[EDX] => #:G19!42[EDX] 
7: MOVE t43[S0]>t44[EDI] => t45[S0]<t46[EDI] 
8: SAP-MOVE t47[S1]>t48[EDI] => t49[S1]<t50[EDI] 
9: NOTE-ENVIRONMENT-START {#} 
10: MOVE #:G19!42[EDX] => X!51[S2]<t52[EDX] 
11: MOVE t37[ECX] => t53[S3]<t54[ECX] 
12: MOVE-TO-DOUBLE t38[EBX] => t55[S4]<t56[FR0] 
13: MOVE t39[ESI] => t57[S6]<t58[ESI] 
14: MOVE t40[EAX] => t59[S7]<t60[EAX] 
15: MOVE t45[S0]>t61[EAX] => t62[S0]<t63[EAX] 
16: SAP-MOVE t49[S1]>t64[EAX] => t65[S1]<t66[EAX] 

VOPs 3 and 12 unbox the value. This is done before the loop. [S4]<
means that the values is put into stack; on your machine it will
probably be in a register ([FRn]).

BTW, why are you writing so many type declarations? In CMUCL they are
needed in 3 cases:

- in communications with outer world (arguments and results of global
  functions without a proclamation);

- when taking values out of an untyped storage (the double-float (car
  list));

- for iteration variables.

Declaring result types of built-in functions is almost certainly
unnecessary.

-- 
Regards,
Alexey Dejneka

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

Reply via email to