Re: memory usage issue for double-float operations
Matt Kaufmann <[email protected]>
| Newsgroups | gmane.lisp.steel-bank.general |
|---|---|
| Message-ID | <[email protected]> |
I'd really like to avoid boxing of double-floats returned by function
calls. Below is a small example that boxes unless the function is
made inline. Is there, or could there be, a way to avoid boxing the
double-float result, other than inlining? Or should I just accept
that this is somehow not possible? (Thanks again, Michał "phoe"
Herda, for the reply; note that I've done all I could below to avoid
boxing inputs.)
(declaim (optimize (compilation-speed 0) (debug 0) (speed 3) (space 0)
(safety 0)))
(declaim (type (simple-array double-float (1)) *ar*))
(defvar *ar* (make-array '(1)
:element-type 'double-float
:initial-element 0.0d0))
(declaim (ftype (function (double-float) double-float)
f1))
; (declaim (inline f1)) ; eliminates consing for (time (f2 1.0d0)) below
(defun f1 (v)
(declare (type double-float v))
(the double-float (+ v v)))
(declaim (ftype (function (double-float) *)
f2))
(defun f2 (v)
(declare (type double-float v))
(loop for i from 1 to 1000
do
(setf (aref (the (simple-array double-float (1))
*ar*)
0)
(the double-float (f1 v)))))
; 32,768 bytes consed, except 0 if f1 calls are inlined:
(time (f2 1.0d0))
Matt Kaufmann <[email protected]> writes:
> Very interesting. I expected the declare form in the defun of
> my-update --
>
> (declare (type (simple-array double-float (*)) ar)
> (type double-float v))
>
> -- to avoid boxing. As another experiment I added the following just
> before the defun of my-update -- but consing still occurred.
>
> (declaim (ftype (function ((simple-array double-float (*)) t double-float)
> double-float)
> my-update))
>
> Apparently those extra efforts don't change your point about boxing,
> which contradicts what I thought I understood. I appreciate the help!
>
> Thanks,
> Matt
> Michał "phoe" Herda <[email protected]> writes:
>
>> Converting a double float to a function argument requires boxing, which
>> allocates memory. If the function is inlined, there are no arguments to
>> pass, so there can be no consing.
>>
>> On 26.09.2024 01:55, Matt Kaufmann wrote:
>>> Thanks so much!
>>>
>>> I see that suitable THE declarations also avoid consing. But
>>> inserting a function call can cause consing, whether using THE or your
>>> declaim form, as illustrated below. I'd be interested in any insights
>>> about why that function call causes consing.
>>>
>>> (declaim (optimize (compilation-speed 0) (debug 0) (speed 3) (space 0)
>>> (safety 0)))
>>>
>>> ; Optional:
>>> ; (declaim (type (simple-array double-float (5000)) *ar*))
>>>
>>> (defvar *ar* (make-array '(5000)
>>> :element-type 'double-float
>>> :initial-element 0.0d0))
>>>
>>> (loop with i of-type (integer 0 *) = 0 do
>>> (cond ((>= i 5000)
>>> (return))
>>> (t (progn (setf (aref *ar* i)
>>> (float i 0.0d0))
>>> (setq i (1+ i))))))
>>>
>>> (defun foo (ar)
>>> (loop with i = 0 do
>>> (cond
>>> ((>= i 4999) ; <-- for i from 0 to 4999 ...
>>> (return))
>>> (t (setf (aref (the (simple-array double-float (*)) ar)
>>> i)
>>> (the double-float
>>> (+ 1.0d0
>>> (the double-float
>>> (aref (the (simple-array double-float *) ar)
>>> i)))))
>>> (setq i (1+ i))))))
>>>
>>> (time (foo *ar*)) ; 0 bytes consed
>>>
>>> ; Optional:
>>> (declaim (inline my-update))
>>>
>>> (defun my-update (ar i v)
>>> (declare (type (simple-array double-float (*)) ar)
>>> (type double-float v))
>>> (setf (aref (the (simple-array double-float (*)) ar)
>>> i)
>>> v))
>>>
>>> (defun foo2 (ar)
>>> (loop with i = 0 do
>>> (cond
>>> ((>= i 4999) ; <-- for i from 0 to 4999 ...
>>> (return))
>>> (t (my-update ar
>>> i
>>> (the double-float
>>> (+ 1.0d0
>>> (the double-float
>>> (aref (the (simple-array double-float *)
>>> ar)
>>> i)))))
>>> (setq i (1+ i))))))
>>>
>>> (time (foo2 *ar*)) ; 65,536 bytes consed if not inlined, 0 otherwise
>>>
>>> Thanks,
>>> Matt
>>> Michał "phoe" Herda <[email protected]> writes:
>>>
>>>> (declaim (type (simple-array double-float (5000)) *ar*))
>>>>
>>>> On 25.09.2024 21:44, Matt Kaufmann wrote:
>>>>> Hi,
>>>>>
>>>>> Is there a way to modify the example below so that the final form does
>>>>> not allocate memory in SBCL? (To be fair, I tried several other Lisps
>>>>> as well, and all of them allocated memory.)
>>>>>
>>>>> (declaim (optimize (compilation-speed 0) (debug 0) (speed 3) (space 0)
>>>>> (safety 0)))
>>>>>
>>>>> (defvar *ar* (make-array '(5000)
>>>>> :element-type 'double-float
>>>>> :initial-element 0.0d0))
>>>>>
>>>>> (loop with i of-type (integer 0 *) = 0 do
>>>>> (cond ((>= i 5000)
>>>>> (return))
>>>>> (t (progn (setf (aref *ar* i)
>>>>> (float i 0.0d0))
>>>>> (setq i (1+ i))))))
>>>>>
>>>>> (defun foo ()
>>>>> (loop with i of-type fixnum = 0 do
>>>>> (cond
>>>>> ((>= i 4999) ; <-- for i from 0 to 4999 ...
>>>>> (return))
>>>>> (t (setf (aref *ar* i)
>>>>> (the double-float
>>>>> (+ 1.0d0
>>>>> (the double-float (aref *ar* i)))))
>>>>> (setq i (the fixnum (1+ i)))))))
>>>>>
>>>>> (time (foo))
>>>>>
>>>>> Thanks,
>>>>> Matt
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> Sbcl-help mailing list
>>>>> [email protected]
>>>>> https://lists.sourceforge.net/lists/listinfo/sbcl-help
>
>
> _______________________________________________
> Sbcl-help mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/sbcl-help
_______________________________________________
Sbcl-help mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/sbcl-help