Re: memory usage issue for double-float operations
Vasily Postnicov <[email protected]> Sun, 29 Sep 2024 20:21:45 +0000
| Newsgroups | gmane.lisp.steel-bank.general |
|---|---|
| Message-ID | <CADnZ6B=2w_JoNLU1vJW-yLkEY55-SZJ8hELViYnSJRBj=93+4Q@mail.gmail.com> |
1. There are no blocks in that file. Check CMUCL manual about it: https://cmucl.org/docs/cmu-user/html/Block-Compilation.html FIXME: SBCL manual has little information about it (yet). To keep it short: you start a block with (DECLAIM (SB-EXT:START-BLOCK ...)) and end it with (DECLAIM SB-EXT:END-BLOCK) 2. There is no way you can avoid consing when returning a double precision floating point number. From what DISASSEMBLE tells me, SBCL returns the first value in RDX, and it's only 64 bits wide. It simply cannot hold a DOUBLE-FLOAT + tag. By inlining, though, you can avoid tagging (as long as you are inside an uninlined callee). 3. Your use of THE and DECLARE seems to be extremely redundant. SBCL already can guess types from FTYPE declarations. 4. If you can, stick to single precision. A single precision number can be stored in the upper half of RDX, and the lower half will contain the tag (#b11001 AFAIK) вс, 29 сент. 2024 г., 22:27 Matt Kaufmann <[email protected]>: > Regarding: > > > You might try block compilation instead. > > Thank you for the suggestion. I tried it with the attached file > bar.lsp, compiling as follows. > > (setq *block-compile-default* t) > (compile-file "bar.lsp") > > I didn't understand the warning shown below; I'd appreciate any help > eliminating it, or better yet, avoiding consing, because in a new > session, I still get "32,768 bytes consed:" with: > > (load "bar.fasl") > (time (f2 1.0d0)) > > Here's the compilation warning. > > ; in: DEFUN F1 > ; (DEFUN F1 (V) (DECLARE (TYPE DOUBLE-FLOAT V)) (THE DOUBLE-FLOAT (+ V > V))) > ; --> SB-IMPL::%DEFUN SB-IMPL::%DEFUN SB-INT:NAMED-LAMBDA > ; ==> > ; #'(SB-INT:NAMED-LAMBDA F1 > ; (V) > ; (DECLARE (SB-C::TOP-LEVEL-FORM)) > ; (DECLARE (TYPE DOUBLE-FLOAT V)) > ; (BLOCK F1 (THE DOUBLE-FLOAT (+ V V)))) > ; > ; note: doing float to pointer coercion (cost 13) to "<return value>" > > Thanks, > Matt > Stas Boukarev <[email protected]> writes: > > > [1:text/plain Hide] > > > > It could be improved in the future, but currently it's really not ready > for > > public use and may change at any time. > > You might try block compilation instead. > > > > On Sun, Sep 29, 2024 at 1:37 AM Matt Kaufmann <[email protected]> > > wrote: > > > >> I very much appreciate all the replies, and I think I understand. > >> Thank you, all who replied! > >> > >> > > That's not directly supported by SBCL's current calling conventions. > >> > > >> > It is actually supported, but we don't advertise it or make it > >> well-behaved > >> > when misused. > >> > >> In our application we can arrange for every function to have a > >> suitable ftype proclaimed before it is defined, so that double-floats > >> are passed and returned only as indicated by the function's ftype; > >> also, every function is defined before it is called. If these suffice > >> to guarantee no "misuse" of support for avoiding boxing, and if there > >> is a reasonably simple way to provide that support (like setting some > >> global), then I'd like to know how that can work, provided that such > >> support is likely to remain available in SBCL. > >> > >> Thanks, > >> Matt > >> Stas Boukarev <[email protected]> writes: > >> > >> > [1:multipart/alternative Hide] > >> > > >> > > >> > [1/1:text/plain Hide] > >> > > >> >> That's not directly supported by SBCL's current calling conventions. > >> > > >> > It is actually supported, but we don't advertise it or make it > >> well-behaved > >> > when misused. > >> > > >> > On Sun, Sep 29, 2024 at 12:30 AM Christophe Rhodes <[email protected]> > >> wrote: > >> > > >> >> Matt Kaufmann <[email protected]> writes: > >> >> > >> >> > I'd really like to avoid boxing of double-floats returned by > function > >> >> > calls. > >> >> > >> >> Avoiding boxing is, essentially, arranging that there be a known > >> >> location for the callee and the caller to cooperate in writing and > >> >> reading an unboxed return value, without risking that value being > >> >> accidentally interpreted as a tagged lisp object pointer. > >> >> > >> >> That's not directly supported by SBCL's current calling conventions. > >> >> But you can do it yourself: have your function, instead of returning > a > >> >> double-float, take as an argument a (simple-array double-float (1)), > and > >> >> write its result there; the caller can read the value from there, and > >> >> all should happen without consing: > >> >> > >> >> (defun f1 (v result) > >> >> (declare (type double-float v) > >> >> (type (simple-array double-float (1)) result)) > >> >> (setf (aref result 0) (+ v v)) > >> >> (values)) > >> >> > >> >> (defvar *ar* (make-array 1 :element-type 'double-float)) > >> >> (declaim (type (simple-array double-float (1)) *ar*)) > >> >> > >> >> (defun f2 (v) > >> >> (let ((f1r (make-array 1 :element-type 'double-float))) > >> >> (declare (dynamic-extent f1r)) > >> >> (loop repeat 1000 > >> >> do (setf (aref *ar* 0) (progn (f1 v f1r) (aref f1r 0)))))) > >> >> > >> >> Christophe > >> >> > >> >> > 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 > >> >> > >> >> > >> >> _______________________________________________ > >> >> Sbcl-help mailing list > >> >> [email protected] > >> >> https://lists.sourceforge.net/lists/listinfo/sbcl-help > >> >> > >> > > >> > [1/2:text/html Show Save:noname (38kB)] > >> > > >> > > >> > [2:text/plain Hide] > >> > > >> > > >> > [3:text/plain Hide] > >> > > >> > _______________________________________________ > >> > 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 > >> > > > > [2:text/html Show Save:noname (49kB)] > _______________________________________________ > 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