<mathrick>
smlckz: this won't make it faster, but SETF is preferable to SETQ in CL. There's never really a situation in which you need to use SETQ directly, SETF will expand to it as appropriate, but the reverse is not true
nij- has quit [Ping timeout: 255 seconds]
<smlckz>
okay
<aeth>
SETQ means one of two things, generally. One, the code is old. Two, the coder is old. :-p
<aeth>
It's bordering on archaic but some people still do it
<mathrick>
it doesn't help that the spec uses SETQ a lot in the examples
<mathrick>
making it look like it has more of a place in the language than one of the primitives SETF expands into
<aeth>
smlckz: are you using SBCL? Because if you (declare (optimize (speed 3))) at the start of a function it will give you optimization notes in SBCL (although a few of them are bordering on nonsensical... especially the one telling you to divide by a nicer number, as if that's somehow OK and wouldn't just change the whole result)
<aeth>
and if you're only using double floats then you can fill the loop with `of-type double-float` for each variable
<aeth>
as well as (declare (type double-float lower-limit upper-limit maximum-relative-error)) at the start of the function
<Bike>
yeah, declaring things double would be the main thing here, i would think
<aeth>
basically, make the compiler remove the genericness of arithmetic and AREFs if you want to (potentially) make things fast. You can get more involved, but that's 90% of it
waleee has quit [Ping timeout: 260 seconds]
<aeth>
(and if you do need it to be generic, but only for single-float and double-float, you might consider writing two versions, and generating the two versions with a macro)
<Bike>
mathrick: ah, so it the method combination doesn't rely on CL's and just does its own thing entirely. i guess that works?
eddof13 has joined #commonlisp
<mathrick>
Bike: I haven't read through how it's done fully yet, but I didn't think it would work, since AFAIUI, the method combination must have at least one group?
<mathrick>
maybe not
<aeth>
smlckz: and if you're willing to use a library, pull in float-features. Then you can wrap your main (or wherever you enter the relevant part) with (float-features:with-float-traps-masked t ...)
<aeth>
smlckz: this will give you +/- inf and NaN instead of erroring on inf and NaN, which should speed up the float arithmetic too afaik
<Bike>
mathrick: it has one group, which it just puts everything into
<Bike>
i haven't looked at this in detail
<smlckz>
inf and nan causes errors by default? hmm...
<mathrick>
Bike: right, but then I'd expect SBCL to complain. I need to run that code and see if it works
dim has quit [Ping timeout: 255 seconds]
<aeth>
It's basically: (1) mask float traps, (2) declare types (as specific as possible) for floats and simple-arrays (nothing else really matters), (3) (declaim (inline foo)) before the definition of any trivially short DEFUN (e.g. if you had a 2+ function that behaves like 1+), (4) in SBCL maybe pay attention to optimization notes unless it has some ridiculous request
<smlckz>
what does this mean: ''doing float to pointer coercion (cost 13) to SLICE-LENGTH''?
dim has joined #commonlisp
<aeth>
that it's boxing the double-float on the heap?
<aeth>
I think
<aeth>
I don't see why it would be doing that. It doesn't look like it's leaving the scope of the function
<aeth>
but anything that doesn't fit 64 bits (with the type tag!) is going to have to get boxed on the heap to add a type tag so the dynamic type system knows what's going on (technically, an implementation can use "NaN boxing" to avoid boxing double floats, at the cost of the maximum number of integers it can store, by storing the integers inside of NaNs; I don't think any does)
bitblit has quit [Ping timeout: 248 seconds]
jryans has quit [Ping timeout: 248 seconds]
kakuhen has quit [Ping timeout: 248 seconds]
<aeth>
But this happens if you call into a function that's not inlined or if you return it as a result. You can avoid this with double-float arrays and maybe (in SBCL anyway) structs with :type slots. If you want to avoid it. It can make your code messier. You don't have to listen to every note.
hayley has joined #commonlisp
hayley has quit [Changing host]
hayley has joined #commonlisp
<aeth>
If it stays inside of the function, it doesn't get boxed.
notzmv has quit [Ping timeout: 244 seconds]
<aeth>
So (funcall f some-double-float) will box it.
<smlckz>
can i declare types of the variables used in the loop?
<aeth>
of-type
<smlckz>
and the function f?
torhex-pasmul[m4 has quit [Ping timeout: 268 seconds]
dieggsy has quit [Ping timeout: 268 seconds]
Duuqnd has quit [Ping timeout: 268 seconds]
yitzi has quit [Ping timeout: 268 seconds]
iceman[m] has quit [Ping timeout: 268 seconds]
<aeth>
`for x = (+ lower-limit (/ slice-length 2)) then (+ x slice-length)` becomes `for x = (+ lower-limit (/ slice-length 2)) of-type double-float then (+ x slice-length)`
<aeth>
for the function, I don't think you can declare the ftype of it
<aeth>
you could wrap it in (the double-float (f ...))
hayley has quit [Ping timeout: 248 seconds]
ecocode[m] has joined #commonlisp
<aeth>
once you start getting into optimizing it, it becomes a tradeoff of how fast do you want to make it vs how clean do you want to make it because some of the things you can do are kind of ugly/messy
AadVersteden[m] has quit [Ping timeout: 268 seconds]
infra_red[m] has quit [Ping timeout: 264 seconds]
dirtcastle has quit [Ping timeout: 268 seconds]
<aeth>
e.g. You could change the higher order function to do (setf (aref a 0) ...) on a 1-length array of :element-type 'double-float and then return a (because just SETFing will still box it because it will implicitly return the double-float) instead of having it return a double-float. This should be faster. But do you really want to uglify the API like that?
<aeth>
Once you get past the low-hanging fruits in optimization, fast and nice APIs are opposing goals.
Mrtn[m] has joined #commonlisp
razetime has joined #commonlisp
dirtcastle has joined #commonlisp
<smlckz>
it says: ''unknown LOOP keyword: OF-TYPE''
<aeth>
hmm, maybe it's in the wrong place
<aeth>
maybe it goes before the =
<aeth>
I think that's it
<Bike>
yeah, you put the of-type after the variable.
<aeth>
e.g. (loop for i of-type double-float from 0d0 below 10d0 collect i)
<smlckz>
how can i measure the time it takes to run a function?
<aeth>
(time)
cross_ has quit [Ping timeout: 252 seconds]
fourier has quit [Ping timeout: 268 seconds]
<aeth>
(time (your-function ...))
NotThatRPG has joined #commonlisp
<smlckz>
okay
fourier has joined #commonlisp
cross has joined #commonlisp
<smlckz>
what does this mean? ''536,870,896 bytes consed''
<aeth>
(Implementations usually have their own way to profile, too, e.g. sb-profile:profile and sb-profile:report in SBCL. There are some portable attempts at this as well.)
<jcowan>
consed = allocated
<jcowan>
Is there a modern convention for writing class names?
eddof13 has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
<mathrick>
jcowan: you mean like (defclass my-class () ...)?
<jcowan>
yes
<jcowan>
do people generally suffix them with -class?
<mathrick>
oh, no
<aeth>
It's a Lisp-3, they don't need to
<jcowan>
Well, I know that, but you don't *need* to use earmuffs either, it's just a convention
<mathrick>
jcowan: it's gonna be something like (defclass audio-buffer () ...)
<mathrick>
so just the thing it is, with words separated by dashes
<mathrick>
and lowercase
<mathrick>
much like everything else in modern CL
<jcowan>
oh, have people stopped using +foo+ for constant names?
<mathrick>
+foo+ for constant is still pretty common
<mathrick>
only things that carry an implicit global declamation get special markers
<jcowan>
Makes sense, thanks
<mathrick>
ie. constants (DEFCONSTANT) and special variables (DEFVAR / DEFPARAMETER)
<aeth>
it's because they can mess with the lexical scope of internal variables
<mathrick>
indeed
eddof13 has joined #commonlisp
eddof13 has quit [Client Quit]
<jcowan>
Another convention question: suppose I want to write a generic function to return the lengths of various things. Would it be better to shadow CL:LENGTH and call it LENGTH, or call it something like LENGTH* or LENGTH+?
<aeth>
My guess is length*
<mathrick>
jcowan: you're not allowed to shadow CL:LENGTH, at least not portably
<mathrick>
I mean
<smlckz>
half a gigabyte allocated to run a function?
<mathrick>
you can SHADOW-IMPORT MYPKG:LENGTH
<mathrick>
but you're not allowed to define an accessor called CL:LENGTH
<jcowan>
No, it would be MYPKG:LENGTH
<aeth>
smlckz: with enough iterations, probably? It has to allocate every call of F
<mathrick>
smlckz: it doesn't mean it used half a gig of memory at any point in time, it just means the total amount of things allocated (and usually GC'd immediately thereafter) added up to half a gig
nij- has left #commonlisp [#commonlisp]
<jcowan>
I don't much like LENGTH* because * means "arbitrary variant", like ' in Haskell
<smlckz>
mathrick: oh
<jcowan>
+ could be understood as "does what CL:LENGTH does but more too"
<jcowan>
s/+/LENGTH+
<mathrick>
jcowan: the workaround I use in those situation is often LENGTH-OF
<jcowan>
ah
<mathrick>
smlckz: in general, how slow your function is is directly proportional to how much it conses. If you can reduce consing, you'll almost always also speed it up
tasty has quit [Ping timeout: 252 seconds]
<mathrick>
jcowan: if you intend it to be a fully-compatible drop-in for LENGTH, then shadowing would be appropriate
<mathrick>
but if it's the length of a specific thing, then name it something else
<smlckz>
hmm ~8 million times the function f is called for that half a gigabyte total allocation..
<mathrick>
smlckz: it will allocate all the local variables you declare. 512MB for 8 million calls means 64 bytes per call
<aeth>
smlckz: some ways around that are to either mutate instead of returning or to turn the whole thing into a macro instead of a higher order function, if that's what you want to do.
<mathrick>
you have 6 locals, + 3 arguments
tasty has joined #commonlisp
tasty has joined #commonlisp
tasty has quit [Changing host]
<mathrick>
which is ~7 bytes per local, and that's not counting whatever the general stack frame overhead is
<mathrick>
if you're on a 64-bit CPU, which I assume you are, that's less than single full-width machine word per local
<mathrick>
that's not too bad :)
karlosz has quit [Ping timeout: 244 seconds]
karlosz_ has joined #commonlisp
<smlckz>
interesting, using single-floats, ''0 bytes consed''!
<aeth>
yes
<aeth>
it conses when it can't fit the type tag and the thing itself (combined) inside of 64 bits
<aeth>
single floats leave 32 bits for a tag while double floats have no room
<smlckz>
on aarch64, there's 32 128-bit registers, Q0 to Q31; it could've used those..
<aeth>
are those for SIMD?
<aeth>
I suppose it could take two registers, one saying "goto larger register" and then one larger register, but maybe someone knows why that can't work
<fiddlerwoaroof>
It's just sort of hanging out in the bug tracker
<fiddlerwoaroof>
Wasn't exactly rejected
<mathrick>
SBCL-bugs has a lot of issues that have been there for many years, including some that have in fact been fixed or worked on since, but no activity in the bug of any sort
<mathrick>
and by that I mean the official launchpad bug tracker, not the mailing list
<fiddlerwoaroof>
Yeah
<fiddlerwoaroof>
The good news, though, is this behavior of * means we can fix this with something like c2mop
Gnuxie_ has quit [Quit: Leaving]
tyson2 has quit [Remote host closed the connection]
causal has joined #commonlisp
causal has quit [Client Quit]
irc_user has quit [Quit: Connection closed for inactivity]
cosimone has quit [Quit: ERC 5.4 (IRC client for GNU Emacs 28.1)]
random-nick has quit [Ping timeout: 248 seconds]
mrcom__ has joined #commonlisp
azimut has quit [Ping timeout: 258 seconds]
mrcom_ has quit [Read error: Connection reset by peer]
azimut has joined #commonlisp
<NotThatRPG>
fiddlerwoaroof mathrick Having a bug tracker that is not connected to the corresponding repo does not, IMO, work well.