Re: memory usage issue for double-float operations
Stas Boukarev <[email protected]> Wed, 16 Oct 2024 19:30:43 +0300
| Newsgroups | gmane.lisp.steel-bank.general |
|---|---|
| Message-ID | <CAF63=11Q=gTBZ5+P+UeZem41=u0wiV6h07VM-ZbSgu-Eo4hE6w@mail.gmail.com> |
Thanks for testing. On Wed, Oct 16, 2024 at 7:27 PM Matt Kaufmann <[email protected]> wrote: > Aha! Thanks so much -- my actual application (from which that email > and the two bug reports were distilled) is now performing as hoped. > > Gratefully, > Matt > Stas Boukarev <[email protected]> writes: > > > [1:text/plain Hide] > > > > It has to be > > (declaim (ftype (function (t) > > (values double-float &optional)) > > aref0)) > > > > i.e. a fixed number of return values. > > > > On Wed, Oct 16, 2024 at 6:54 PM Matt Kaufmann <[email protected]> > > wrote: > > > >> Hi, > >> > >> I appreciate being able to avoid memory usage when passing > >> double-floats through function calls. But I'm still running into an > >> issue with that, even with fixes to recent SBCL bugs 2084209 and > >> 2084398. Using SBCL downloaded and built this morning on my Mac (SBCL > >> 2.4.9.52-28385348a), the simple script below results in memory usage > >> that surprises me, and shows that this usage disappears with inlining: > >> > >> * (load "sbcl-script.lsp") > >> Bytes used for 10000 iterations of (foo *my-ar*): 163840 > >> Bytes used for 10000 iterations of (foo-inline *my-ar*): 0 > >> T > >> * > >> > >> Am I doing something wrong? > >> > >> Thanks, > >> Matt [script is below] > >> (defvar *my-ar* > >> (make-array 3 > >> :element-type 'double-float > >> :initial-contents '(3.0d0 4.0d0 5.0d0))) > >> > >> (declaim (ftype (function (t) > >> double-float) ; or (values double-float) > >> aref0)) > >> > >> (declaim (inline aref0-inline)) > >> > >> (defun aref0 (ar) > >> (the double-float > >> (aref (the (simple-array double-float (*)) > >> ar) > >> 0))) > >> > >> (defun aref0-inline (ar) > >> (the double-float > >> (aref (the (simple-array double-float (*)) > >> ar) > >> 0))) > >> > >> (defun foo (ar) > >> (= (the double-float > >> (* 2.0d0 > >> (the double-float > >> (aref0 ar)))) > >> 5.0d0)) > >> > >> (defun foo-inline (ar) > >> (= (the double-float > >> (* 2.0d0 > >> (the double-float > >> (aref0-inline ar)))) > >> 5.0d0)) > >> > >> ; Bytes used = 163840 > >> (let ((start (sb-ext:get-bytes-consed))) > >> (loop for i from 1 to 10000 do (foo *my-ar*)) > >> (format t "Bytes used for 10000 iterations of (foo *my-ar*): ~s~%" > >> (- (sb-ext:get-bytes-consed) start))) > >> > >> ; Bytes used = 0 > >> (let ((start (sb-ext:get-bytes-consed))) > >> (loop for i from 1 to 10000 do (foo-inline *my-ar*)) > >> (format t "Bytes used for 10000 iterations of (foo-inline *my-ar*): > ~s" > >> (- (sb-ext:get-bytes-consed) start))) > >> > >> Stas Boukarev <[email protected]> writes: > >> > >> > [1:text/plain Hide] > >> > > >> > It could be made to work without any intervention at all, but it's > >> probably > >> > not a good idea to automatically generate extra entry points when not > >> > needed. > >> > ftype seems reasonable and standard, for now. > >> > > >> > On Tue, Oct 8, 2024 at 6:19 PM Michał Herda | Keepit <[email protected]> > >> wrote: > >> > > >> >> Thanks for that optimization. One more question from me: is this > going > >> to > >> >> work automatically with *DERIVE-FUNCTION-TYPES*, or are manual ftype > >> >> proclamations still necessary in that case? > >> >> ------------------------------ > >> >> *From:* Stas Boukarev <[email protected]> > >> >> *Sent:* Tuesday, October 8, 2024 5:17 PM > >> >> *To:* Matt Kaufmann <[email protected]> > >> >> *Cc:* [email protected] <[email protected]>; > >> >> [email protected] <[email protected]> > >> >> *Subject:* Re: [Sbcl-help] memory usage issue for double-float > >> operations > >> >> > >> >> No block compilation is needed, or any other non-standard feature. > >> >> > >> >> On Tue, Oct 8, 2024 at 6:15 PM Matt Kaufmann <[email protected] > > > >> >> wrote: > >> >> > >> >> Thank you so much; very cool! Is block compilation necessary for > this > >> >> to work? > >> >> > >> >> Stas Boukarev <[email protected]> writes: > >> >> > >> >> > [1:text/plain Hide] > >> >> > > >> >> > Now unboxed returns also work. Trace works as well. The following > no > >> >> longer > >> >> > conses: > >> >> > > >> >> > (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) (values double-float > >> &optional)) > >> >> > f1)) > >> >> > > >> >> > (defun f1 (v) > >> >> > (+ v v)) > >> >> > > >> >> > (declaim (ftype (function (double-float) *) f2)) > >> >> > > >> >> > (defun f2 (v) > >> >> > (loop for i from 1 to 1000 > >> >> > do > >> >> > (setf (aref *ar* 0) (f1 v)))) > >> >> > > >> >> > > >> >> > On Tue, Oct 8, 2024 at 12:17 AM Stas Boukarev <[email protected]> > >> >> wrote: > >> >> > > >> >> >> I just pushed the initial attempt for unboxed arguments, so the > >> >> following > >> >> >> doesn't cons anymore: > >> >> >> > >> >> >> (declaim (ftype (function (double-float double-float) (values t > >> >> >> &optional)) f)) > >> >> >> > >> >> >> (defun f (a b) > >> >> >> (> (+ a b) 3d0)) > >> >> >> > >> >> >> (defun bar (n) > >> >> >> (declare (fixnum n)) > >> >> >> (f (* pi n) (* pi (1+ n)))) > >> >> >> > >> >> >> > >> >> >> Not consing the return value will come in the near future. #'f > works > >> as > >> >> >> expected, and incompatible redefinitions behave reasonably. trace > >> >> doesn't > >> >> >> yet work. > >> >> >> > >> >> >> On Sun, Sep 29, 2024 at 1:46 AM Stas Boukarev <[email protected] > > > >> >> wrote: > >> >> >> > >> >> >>> 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 (54kB)] > >> >> > >> >> > >> >> > >> >> > >> >> This e-mail is sent to you from Keepit A/S. Dedicated SaaS Data > >> Protection. > >> >> VAT: DK30806883, Per Henrik Lings Allé 4, 7., DK-2100 Copenhagen Ø, > >> >> Denmark. > >> >> > >> >> This e-mail is sent to you directly and is meant for nobody else. If > the > >> >> e-mail contains personal data that Keepit is responsible for and the > >> e-mail > >> >> was not meant for you, please do not forward, distribute, or copy, > i.e. > >> but > >> >> return the e-mail to sender. Also, do not send the e-mail to a third > >> party > >> >> without making sure that you have our prior consent. Distribution of > >> this > >> >> e-mail to unauthorized receivers may have legal consequences. > >> >> If you have received an e-mail from us and you don’t know why, then > >> please > >> >> refer to our Privacy Policy <https://www.keepit.com/privacy-policy/ > >. > >> >> If you do not want to receive more e-mails from us, please contact > >> >> [email protected]. > >> >> > >> > > >> > [2:text/html Show Save:noname (75kB)] > >> > > > > [2:text/html Show Save:noname (91kB)] > _______________________________________________ Sbcl-help mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/sbcl-help