Re: LW compiler optimizations

"David McClain (as dbm at refined-audiometrics dot com)" <[email protected]>
Newsgroups gmane.lisp.lispworks.general
Message-ID <[email protected]>
… however, still 3x slower than using FLI to call vDSP. 

But in fairness, had I initially achieved this level of speed from Lisp, then I probably wouldn’t have bothered with the FLI to vDSP, and just stayed in Lisp.

I should try to examine vDSP dotprD() and see what they are doing. They claim that it is single-threaded, but a case could be made for parallelizing this code, especially given the large size of the FIR vector. 

These timings hint that they may be using some low-grade SIMD instructions. But I am thoroughly ignorant of the capabilities of the M1 architecture. Do they even have low-grade SIMD like the Intel MMX engine?



> On Jan 14, 2025, at 15:21, David McClain (as dbm at refined-audiometrics dot com) <[email protected]> wrote:
> 
> If I rewrite without the displaced array:
> 
> (defun fir-dotpr-loop (fir vec &key (start2 0))
>  ;; Fastest so far - 335 μs
>  ;; #F
>  (declare (optimize (speed 3) (safety 0) (float 0)))
>  (declare ((simple-array double-float (*)) fir vec)
>           (fixnum start2))
>  (let* ((sum   0d0)
>         (nel   (length fir)))
>    (declare (double-float sum)
>             (fixnum nel))
>    (dotimes (ix nel)
>      (declare (fixnum ix))
>      (setq sum
>            (+ sum
>               (* (aref fir ix)
>                  (aref vec (+ ix start2))))
>            ))
>    sum))
> 
> Then my timing drops to 63 μs per iteration, or 1.4 ns/pair. Now we are getting respectably close to C performance. But this indicates that using a displaced array costs me nearly 5x performance degradation, as opposed to your claim of 1% penalty.
> 
> 
>> On Jan 14, 2025, at 15:04, David McClain <[email protected]> wrote:
>> 
>> Just to remove any doubt, perhaps #F isn’t expanding the way I think it is (although I have looked at the expansion), but let’s redo with explicit OPTIMIZE:
>> 
>> (defun fir-dotpr-loop (fir vec &key (start2 0))
>> ;; Fastest so far - 335 μs
>> ;; #F
>> (declare (optimize (speed 3) (safety 0) (float 0)))
>> (declare ((simple-array double-float (*)) fir vec)
>>          (fixnum start2))
>> (let* ((sum   0d0)
>>        (nel   (length fir))
>>        (v     (make-array nel
>>                           :element-type 'double-float
>>                           :displaced-to vec
>>                           :displaced-index-offset start2)))
>>   (declare (double-float sum)
>>            (fixnum nel)
>>            ((vector double-float *) v)
>>            (dynamic-extent v))
>>   (dotimes (ix nel)
>>     (declare (fixnum ix))
>>     (setq sum
>>           (+ sum
>>              (* (aref fir ix)
>>                 (aref v ix)))))
>>   sum))
>> 
>> Same timing results, 300 μs per iteration of the 1000 TIME test => 45,064 MAC pairs => 6.7 ns/pair
>> 
>>> On Jan 14, 2025, at 14:52, David McClain (as dbm at refined-audiometrics dot com) <[email protected]> wrote:
>>> 
>>> Thank you for sharing that. I tried the DOTIMES with a displaced array. And I incorporated your declare types. My timing is still > 15x slower than the vDSP called from Lisp.
>>> 
>>> Per MAC-pair, my timing shows 6.7 ns/pair, on a 2021 M1 iMac.
>>> 
>>> Specifically:
>>> 
>>> (defun fir-dotpr-loop (fir vec &key (start2 0))
>>> ;; Fastest so far - 335 μs
>>> #F
>>> (declare ((simple-array double-float (*)) fir vec)
>>>         (fixnum start2))
>>> (let* ((sum   0d0)
>>>       (nel   (length fir))
>>>       (v     (make-array nel
>>>                          :element-type 'double-float
>>>                          :displaced-to vec
>>>                          :displaced-index-offset start2)))
>>>  (declare (double-float sum)
>>>           (fixnum nel)
>>>           ((vector double-float *) v)
>>>           (dynamic-extent v))
>>>  (dotimes (ix nel)
>>>    (declare (fixnum ix))
>>>    (setq sum
>>>          (+ sum
>>>             (* (aref fir ix)
>>>                (aref v ix)))))
>>>  sum))
>>> 
>>> ;; ——————————————
>>> 
>>> (defparameter *nel*   5633) ;; * 2 arrays, * 4 steps = 45,064 MAC ops/test
>>> (defparameter *tst-fir* (make-array *nel*
>>>                                  :allocation :pinnable
>>>                                  :element-type 'double-float
>>>                                  :initial-contents (map 'vector 'dfloat (vm:unoise *nel*))))
>>> (defparameter *tst-arr* (make-array (+ *nel* 1024)
>>>                                  :allocation :pinnable
>>>                                  :element-type 'double-float
>>>                                  :initial-contents (map 'vector 'dfloat (vm:unoise (+ *nel* 1024)))))
>>> 
>>> (defun test-lisp-fir-dotpr-loop ()
>>> ;; 300 μs
>>> (dotimes (ix 4)
>>>  (declare (fixnum ix))
>>>  (let* ((start (* ix 256)))
>>>    (declare (fixnum start))
>>>    (fir-dotpr-loop *tst-fir* *tst-arr* :start2 start)    ;; simulate real part
>>>    (fir-dotpr-loop *tst-fir* *tst-arr* :start2 start))))
>>> 
>>> (time
>>> ;; 300 μs/iter, 37.5 μs/vdot, 6.7 ns/MAC
>>> ;; alloc 1,050 bytes/iter, 131 bytes/vdot
>>> (loop repeat 1000 do (test-lisp-fir-dotpr-loop)))
>>> 
>>> 
>>>> On Jan 14, 2025, at 10:47, Tim Bradshaw (as tfb at tfeb dot org) <[email protected]> wrote:
>>>> 
>>>> https://github.com/tfeb/bench-df-aref
>>>> 
>>>> I added some more variants since yesterday, and with the best of them LW is not slower than SBCL and neither is slower than C (or than my C): both are about 0.94ns/step on my M1 machine
>>>> 
>>>> --tim
>>>> 
>>>> _______________________________________________
>>>> Lisp Hug - the mailing list for LispWorks users
>>>> [email protected]
>>>> http://www.lispworks.com/support/lisp-hug.html
>>> 
>>> 
>>> _______________________________________________
>>> Lisp Hug - the mailing list for LispWorks users
>>> [email protected]
>>> http://www.lispworks.com/support/lisp-hug.html
>> 
> 
> 
> _______________________________________________
> Lisp Hug - the mailing list for LispWorks users
> [email protected]
> http://www.lispworks.com/support/lisp-hug.html


_______________________________________________
Lisp Hug - the mailing list for LispWorks users
[email protected]
http://www.lispworks.com/support/lisp-hug.html
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.