Hacker News new | ask | show | jobs
by lostcolony 2233 days ago
You are correct.

It's actually worse than that; as I recall, the internal numerical representations of numbers do not necessarily map to the CPU's (for instance, there is no byte sizing; you have integers and floats, and they can be arbitrarily large). The work to perform that conversion, do the math, and convert back, would almost assuredly make it so that a single calculation takes more time than just doing it within the BEAM. The only way to save time would be to convert once, do a bunch of math, and convert back. Which would, yes, prevent pre-emption, AND require indication of intent (so brand new language constructs, minimally).

That's a lot to expect of the user, and a lot to implement in the language...all to avoid just writing a NIF.

2 comments

Well pre-emption only happens at function call or return, or when a NIF calls the special function to allow for it; if all the math was in a single function, with no interleaved function calls (possibly after inlining?), unbox, math away, and rebox could work.

There wouldn't need to be an indication of intent, other than writing the math separate from any function calls. I don't know how much code fits this pattern, but it's an idea that could be explored. I think that's part of what hipe is supposed to do, but I haven't looked into hipe in a long time.

> Which would, yes, prevent pre-emption, AND require indication of intent

I don't understand why. If you have a maths-intensive operation like matrix-multiplication using untagged maths, why does that prevent pre-emption? Why does it require indication of intent?

And there's already a basically zero-overhead way to implement pre-emption - safepoints - that's what the JVM does when it wants to pre-empt in user-space.

Uh...no. A safepoint is when all threads in the JVM have blocked (which is purely cooperative, and happens during thread transitions), and, importantly, when OS threads running native code still are running, but can't return/respond to the JVM. The JVM doesn't pause those threads.

Which is the point. You can't preempt crunching those numbers if it's not within the BEAM. Which might be fine. Or it might not. Making it invisible to the user is not really a good idea when going for soft realtime properties; at least with a NIF and dirty scheduler you're being explicit about it.

> A safepoint is when all threads in the JVM have blocked

And having blocked them, you can then pre-empt them.

> You can't preempt crunching those numbers if it's not within the BEAM.

I still don't see why sorry. If you had a JIT and you compiled maths intensive code to native code, it could run efficiently in BEAM and still be pre-emptible by having a safepoint in the generated code.

How do you think Java is doing optimised numerical code that is pre-emptible from user-space? Safepoints! BEAM could do the same thing.

You, uh, realize that's not actually preemptive right? Like, having to thread in checks, that are cooperative, is by definition not preemptive?
Yes I think that's a reasonable definition of pre-emption because they don't interrupt the numerical pipeline. They cause zero data or control dependencies. But even if you don't think it fits the definition, what do you think the practical difference is when you argue about this terminology?

What did we want to achieve? We wanted to be able to run a tight loop of highly optimised, untagged numerical code but still be able interrupt it to switch threads on demand from user-space if needed.

Safepoints let us do that.

What else did we need that this doesn't cover?