IRC channel logs

2019-08-19.log

back to list of logs

<wingo>woo that declarative bindings optimization is fire, a very nice speed bump for lots of code
<lloda>wingo: excited to try it
<lloda>I had been grumping about having to use define-inlinable everywhere
<lloda>some places I couldn't
<wingo>the optimization still doesn't work cross-module, and we could provide a knob to prevent making private variables for unexported vars
<wingo>so there are some possible next steps. still tho, pretty good
<wingo>similarly: i am not sure why internal definitions must precede expressions. the letrec* transformation for the top-level works really well
<wingo>and i think it could work lexically, i.e. we could allow mixed internal definitions and expressions
<wingo>anyway, i think we have enough for a 3.0
<wingo>still need to look at mark's fixflo patches, gulp, dunno why i have been putting that off
<lloda>we have enough for a 4.0 :D
<wingo>:)
<lloda>master make check fails for me at test-out-of-memory
<lloda>Throw to key `encoding-error' with args `("scm_to_stringn" "cannot convert narrow string to output locale" 12 #f #f)'.
<lloda>hmm
<wingo>humm
<wingo>i also get an error there
<wingo>i was just running ./check-guile before
<wingo>interesting
***ng0_ is now known as ng0
<wingo>will have to look at that
<chrislck>letrectify sounds like electrify... an intentional pun?
<wingo>unintentional :)
<davexunit>wingo: this is cool! though I'm a little confused about what it means for hacking at the repl. seems like another thing that users will have to disable in order for their live coding session to work as expected?
<wingo>davexunit: unclear! i think there are some cases in which you'll want to disable it.
<davexunit>using the box module in the documentation as an example: if you wanted to redefine box-set!, that would be just fine, but since the original definition of box-set! was inlined in box-swap!, you'd have to re-evaluate it as well.
<wingo>if you build a program by entering expressions one by one at the repl, then you're mostly good -- your compilation unit never has more than one definition
<davexunit>and re-evaluating it this way would create a new box-swap! that does *not* inline box-set! you'd have to recompile the entire module for that. am I getting this right?
<wingo>mostly because a loop might tail-call itself directly instead of going through the module
<davexunit>okay, that makes sense.
<davexunit>I often load up entire programs and then tweak them via geiser and a repl server
<wingo>if you build a program by editing things in modules and then loading them from the repl, or reloading them, then there you're cool too
<davexunit>so this optimization has more of an impact there
<wingo>because you are usually ,reload'ing a module
<wingo>if you just want to reach into modules' unexported bindings -- there you are also good, all top-level definitions are in the module
<wingo>the problem comes in when you want to change a binding in a module that was compiled with the declarative flag on.
<wingo>if you just re-define things external (extra-module) uses are fine as they currently go through the module's variable
<wingo>but internal users won't see the new binding, probably. unless the binding wasn't declarative (it was the target of a set! or a redefinition within the compilation unit)
<davexunit>hmm, okay I'm still a tad unsure about something. thanks for explaining, though.
<davexunit>does my example using the box module make sense? am I misunderstanding something?
<davexunit>I guess I should add some additional context: you first load that module into a fresh repl, then do the edits I mentioned.
<wingo>so you are asking -- you load (boxes) from the repl.
<wingo>then you ,m boxes
<davexunit>yes
<wingo>then you (define (box-set! x y) (set-car! x (pk y)))
<davexunit>yes
<wingo>and then.. what exactly?
<dsmith-work>Monday Greetings, Guilers
<wingo>(at this point, box-swap! is unaffected)
<davexunit>wingo: okay, I'm clear on that part. now, if I call box-swap!, would that new definition of box-set! get used. the docs say that box-set! gets inlined in box-swap! so I would think that it wouldn't.
<davexunit>that second sentence was supposed to be a question.
<wingo>your intuition is correct: box-swap! inlined box-set! when it was compiled, so it does not reference the new box-set!.
<wingo>wdyt about the tradeoff? :)
<wingo>is it comprehensible, is (user-modules-declarative? #t) the right default?
<davexunit>wingo: okay, great. so at that point I have two choices: re-eval all call-sites of box-set! within the module, or just recompile the whole thing.
<wingo>davexunit: right.
<davexunit>thanks for walking through this with me.
<wingo>np, & likewise of course
<davexunit>I think it's a good tradeoff. I'm excited to see this top-level procedure problem chipped away at.
<wingo>strictly speaking i am not sure if it is standard scheme -- it corresponds with r6rs i think, haven't checked r7rs yet
<wingo>but the top-level remains a bit hopeless :)
<davexunit>for me, as long as it is fairly simple and clear to turn off some optimizations that interfere with live coding, I'm all for 'em.
<davexunit>so far I think the most difficult change has been non-redefinable goops classes, but I came up with a workable solution.
<davexunit>I use an env var to decide if the metaclass for my base classes should be <class> or <redefinable-class>. that was the only way I could think of to provide input to the module being loaded.
<davexunit>makes me wonder if, with all these optimizations, guile could benefit from some sort of "live hacking mode" flag that does all the right stuff.
<davexunit>anyway, thanks for all the help and all the awesome compiler work. graphics programming with guile has never been better.
<bandali>hi all, i’m looking for a breadcrumb implementation for haunt
<bandali>something like what’s at the very bottom of this page: https://sny.no/2019/08/log
<bandali>(it needs JS)
<bandali>i could probably write one myself, but since my guile-foo isn’t that great, i was wondering if anyone else had done something similar for themselves that i could have a look at
<rekado>bandali: what do you think of the breadcrumb thing at https://guix.gnu.org/blog/ ?
<rekado>(near the top)
<jonsger>wingo: compiling 2.9.3 fails on ppc64 and ppc64le due to following error: https://build.opensuse.org/package/live_build_log/home:jbrielmaier:guile-3.0/guile3.0/openSUSE_Factory_PowerPC/ppc64le `--enable-jit=no` doesn't makes a difference. I would say af72d01de8 is the bad commit
<bandali>rekado, oh cool! how did i not notice that before :p my only nit would be that it skips the ‘year’ part as a separate link; but perhaps that wouldn’t be too hard to add in
<bandali>i’ll have a look at its source a little later
<wingo>jonsger: ah interesting. i will see what i can do
<wingo>davexunit: did you get to try out the sqrt / abs things btw? :)
<jonsger>thx. Let me know if you have a patch or so. Then I can test :)
<wingo>jonsger: pushed a little patch
<wingo>davexunit: yeah it's hard to straddle that line between wanting the compiler to reason statically and allowing run-time changes. the best solution is adaptive compilation but i don't think we can afford it, for better or for worse
<jonsger>wingo: still getting /usr/lib64/gcc/powerpc64le-suse-linux/9/../../../../powerpc64le-suse-linux/bin/ld: ./.libs/libguile-3.0.so: undefined reference to `scm_jit_return_to_interpreter_trampoline' with patch applied
<jonsger>the `scm_jit_clear_mcode_return_addresses` error is gone
<wingo>hum
*wingo looks
<jonsger>it's strange. All occurences seem to be inside of a ENABLE_JIT def...
<wingo>jonsger: pushed another small fix
<wingo>because i am an idiot :)
<jonsger>oh, didn't saw that error :P
<davexunit>wingo: whoa what sqrt/abs things? I must have missed this.
<davexunit>is this in the latest pre-release or will I need to build from master?
<wingo>master
<wingo> http://git.savannah.gnu.org/cgit/guile.git/commit/?id=382cc5c246ccbe8dc1f6fa589f4fcf7f076fab69
<davexunit>wingo: thanks. do you think this same optimization could be applied to the trigonometric functions?
<wingo>davexunit: fyi i also pushed some commits to guile-opengl recently, to add the example from the old "compost" thing
<wingo>runs not quite as well as compost (no register allocation), but it's close, and general :)
<wingo>davexunit: yes certainly
<davexunit>I remember that old thing
<davexunit>neat
<davexunit>I do a lot of mainly sin, cos calls. rotation matrices and such.
*wingo nod
<wingo>we'd implement by calling out to the run-time. the goal would be to work with unboxed f64
<wingo>it depends on your code, but if you can somehow manage to avoid boxing entirely in certain code paths, the perf boost can be dramatic
<wingo>3x, 4x, more
<davexunit>yes, anywhere that I've been able to optimize like this has been a huge win.
<wingo>so, like, make a list
<davexunit>unboxed trig functions would enable me to render tons of dynamic sprites, for example.
<wingo>is it just sin and cos or is it other thigns too? etc
<davexunit>yeah I can take a look through my code. I think I also sometimes do floor/ceiling and those box IIRC
<wingo>yep
<wingo>those also can be optimized. i think it's a short list of things tbh
<wingo>maybe 5-10 primitives
<davexunit>yes I think so
<davexunit>I have considered writing my own sin/cos in the past but this would be much better.
<davexunit>for everyone.
<davexunit>wingo: sin, cos, tan, asin, acos, atan, floor, ceiling, min, max.
*wingo nod
<davexunit>min/max might be tricky because they allow arbitrary amounts of args?
<davexunit>I wrote my own inlined versions that operate on just 2 args
<wingo>min and max are macro-expressible
<wingo>i.e. (min a b c) = (min (min a b) c)
<davexunit>are they currently expressed this way?
<wingo>yes
<davexunit>okay great
<wingo>(i might punt on min/max fwiw)
<davexunit>ah okay
<wingo>but the other ones definitely need compiler support
<davexunit>I also seem to run into issues inexact->exact. it's pretty common to need to take a float and translate it to some index value
<davexunit>I don't know what can really be done there.
*davexunit afk for a bit, meeting
<wingo>that might be worth working on, yes
<jonsger>wingo: I have another build issue with 2.9.3. This time on armv7l https://build.opensuse.org/package/live_build_log/home:jbrielmaier:guile-3.0/guile3.0/openSUSE_Factory_ARM/armv7l I don't have a machine to investigate at the moment. But I think once could "emulate" armv7l on some armv8 aarch64 machines...
<wingo>illegal instruction! that's very exciting :)
<wingo>i wonder what instruction it is
<lloda>floor is stupid slow even in C for some reason
<lloda>ime
<jonsger>wingo: we built them on aarch64 machines and they "emulation" armv7l in some way. It could come from that
<wingo>lloda: why is that, i wonder?
<wingo>jonsger: apparently you can boot the machine into an armv7 mode somehow
<wingo>is that right?
<wingo>my understanding was that the emulation was a boot-time choice
<jonsger>could be. I have no idea about ARM
<davexunit>lloda: oh really? interesting. wonder why.
<lloda>wingo: davexunit: Not sure :-/ It was slower to floor a vector than to do a matrix vector product. Those are tuned to the hilt, but still the library functions were all really bad. I tried a couple of bit tricks and it was a small improvement. But I didn't go down to the assembly. It was for work. Maybe when we start shaving ms I can revisit.
<lloda>I saw many comments about IEEE conformance etc, but for our application I didn't really care
<lloda>the last bit was noise for us anyway
<wingo>davexunit: you really use asin??
<wingo>it is somewhat difficult to prove that the result of asin is a flonum
<daviid>wingo: in guile-gnome, you use g_hash_* functions, why did you not use scheme hash tables, was it for speed?
<davexunit>wingo: atan is the main one. I was just including all the trig functions for good measure. if any inverse trig functions are difficult then no pressure from me to make it happen
<daviid>to keep track of the correspondance between foreign pointers and goops instances ...
<davexunit>sin/cos/tan are by far the most important.
<davexunit>I use atan to find the angles of 2D vectors, but less frequently that sin/cos
<daviid>what would be the best hash function for a foreign pointer by the way? anyone?
<davexunit>eq?
<davexunit>eqv? wouldn't make sense. I don't know what equal? would even do.
<davexunit>maybe you could use pointer-address values as the keys
<davexunit>I guess I don't really know. I'll stop talking now. :)
<jcowan>wingo: The arcsine of a real number is always a real number; indeed, the real part of the complex arcsine is the arcsine of the real part.
<jcowan>Real arcsine of +0.inf, -0.inf, and +0.nan is +0.nan.
<lloda>jcowan: that cannot be, arcsin 2 cannot be real, since sin(x) in [-1 1] for any real x
<lloda>maybe you're thinking of atan
<davexunit>it was a mistake to list asin and acos earlier. Andy need not waste his time on those. I completely forgot about the complexities of them.
<jcowan>lloda: Yes, you're right
<daviid>have to go, bbl, will read the log ...
<lloda>it's great to have logs.