Advent of Code 2024 and BQN

nrk.neocities.org

57 points

ingve

a day ago


7 comments

picardo a day ago

Discovering array languages in the last year was one of the great joys of my programming career. They've made me see my work differently and made me a better programmer in general. If only I could find good reasons to use them for more general programming tasks in my every day work!

truckerbill a day ago

Is it possible to use BQN in a high performance context? How much overhead does the runtime, and FFI have? Could it be used for graphics?

  • mlochbaum a day ago

    Regarding graphics, CBQN is not very suited to doing these natively as it runs on the CPU rather than GPU and has only double-precision and not single-precision floats. So, can you do some simple animation at 60FPS? Probably. Can you make a competitive game engine with it? Definitely not. A few programmers are doing games using Brian's FFI raylib bindings (https://github.com/Brian-ED/rayed-bqn), see in particular David Zwitser's videos on Astroids and Snake at https://www.youtube.com/@davidzwitser/videos. And we have nice FFI docs now: https://mlochbaum.github.io/BQN/doc/ffi.html!

    (Everybody seems to assume "high performance" automatically means in whatever domain they work in. Impossible to interpret these sorts of questions. Try "Will BQN have high performance for ...?" instead.)

    • truckerbill 13 hours ago

      Thanks. Yes I was thinking more about the (traditionally) CPU side of graphics or games, things like CPU skinning or skeletal animation.

      I was wondering mostly about the FFI overhead. So the question should really be, is it suitable for real-time low-latency contexts? But I have your answer :)

      I still would love to find a use for it one day. If there's ever a chance you could go the futhark route and allow for compilation of CPU/GPU routines I think it would be an ideal kind of syntax.

      • mlochbaum 10 hours ago

        There's also a GC pause issue: reference counts are the main method, but when those don't do the job we rely on stop-the-world mark and sweep. And we do very little analysis so it's easy for namespaces and closures to form reference loops. If you're careful about how you use those, it's possible to keep the reference counts working, but debugging when this fails is probably not such a nice experience. Running GC every frame might be acceptable if the stored state has few enough objects; it can be around 1ms if there's not much to do.

  • dzaima a day ago

    It depends on how high performance your high performance context requires. Being an array language, ideally traditional interpreter overhead doesn't matter if you write "array-y" code as most time would be spent in within-interpreter loops.

    But as currently there isn't any loop fusion in CBQN (though I'd definitely like to add such at some point), despite the native ops being all nice SIMD where possible, it can still lose to autovectorized C or similar, or even scalar code, due to memory overhead.

    FFI is libffi currently (with non-JITted preparation), so on the order of 100ns per call.