[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: speed up for array ops

bright@ENH.NIST.GOV writes:
> Hello out there!                                                          
>Anyone have any ideas, declarations, etc.  that will speed up the likes of 
>this?  For a 256x256 element array, with complex values, this takes about 7
>scs on my IIfx, MCL2.0.  For real elements (without the absolute value
>function ***) it takes about 5 secs.  I have not had too much luck with
>various declarations (specifing fixnum array elements and indices, speed 3,
>safety 0) but then I don't know exactly what I am doing yet.      
>(defmethod climits ((ara array))
>  "Returns the maximum and minimum values of elements of an array."
>  (let* ((asiz (array-total-size ara))          
>         (av (make-array asiz
>                         :displaced-to ara      
>                         :element-type (array-element-type ara)))
>         (amax (aref av 1))
>         (amin (aref av 1)))
>    (dotimes (i asiz)
>      (setq amax (max amax (abs (aref av i))))  ;  ***
>      (setq amin (min amin (abs (aref av i)))))    ; ***
>    `((min ,amin)(max ,amax))))

Some minor problems. Somebody pointed out that aref can be slow
and svref should be used. However, this is not possible in your case
as displaced arrays are not considered simple-vectors (WHY?). Since you
iterate over a large number of items its important to clean out some
stuff in your dotimes. First, there is no need to access the array twice and
to call abs twice. Secondly, you can do better than MIN, MAX using IF because
the way things are initialized changes to amax and amin are exclusive:

(defmethod climits ((ara array))
  "Returns the maximum and minimum values of elements of an array."
  (declare (optimize (speed 3) (safety 0)))
  (let* ((asiz (array-total-size ara))          
         (av (make-array asiz
                         :displaced-to ara   
                         :element-type (array-element-type ara)))
         (amax (aref av 0)) ;; the array starts with 0 not 1!
         (amin (aref av 0)))
    (dotimes (i asiz)
      (let ((value (abs (aref av i))))
        (if (> value amax)
          (setq amax value) ; no need to update amin
          (when (< value amin) (setq amin value)))))
    `((min ,amin)(max ,amax))))

On my MacII this reduced the time from about 11 secs to 4.2 secs. The no ABS
versions took only 2.5 secs, i.e., ABS is expensive (about 13 us).
(declare (optimize (speed 3) (safety 0))) had almost no influence, it would
have with svref.

I've tried a version using vector-pop which was disapointingly slow. What
good are fill pointers (besided keeping track of the pointer) when VECTOR-POP
is not any faster than AREF?

I'm sure there are better solutions to this using some low-level MCL stuff, 
oh well..

  Alex Repenning