Live data from Hacker News

Beating the Compiler

mattkeeter.com

71–78 of 78 posts

Re: Beating the Compiler

#71

I wish you wouldn't broadcast the sentiment contained in the first paragraph. Compilers lack the ability to consistently perform many basic optimizations to an embarrassing extent. Including even the ones you would think would be the first optimizations you'd implement when writing a compiler. Open up Godbolt and tell me if you still think the compiler knows best. I try to submit at least one issue to LLVM every time…

[deleted]

Re: Beating the Compiler

#72
post #69
post #56

Earlier quoted context omitted.

Ok, I spent quite a bit of time looking at performance counters, trying to understand what the M1's branch predictor was doing. The branch predictor is really accurate with a common dispatcher, it predicts those indirect branches correctly 99.25% of the time. Switching to threaded jumps improves this slightly to 99.75%, but not because the indirect branches are at different addresses. This improvement in accuracy is…

Very cool, thanks for digging into this!

The other thing I noticed while playing around; Performance absolutely falls off a cliff if your hot loop starts missing in the L1i cache.

This blog post [1] from CloudFlare has a few interesting hints about the M1's branch predictor. First, (in their testing) to get the one cycle predictions at all, your hot code needs to fit in just 4KB.

Second, if the brach target isn't in L1 cache, you don't get a prediction at all. The branch target prediction probably points directly at the cache line + way, so even if a cache line moves to a different way, the prediction will still fail.

Which means, I'm not sure this optimisation is worth while. It works for fibonacci and mandelbrot because they have reasonably tight loops, and adding a dispatcher to each instruction handler doesn't push the hot code over the limit. But when interpreting more generic code, you might be better off trying to minimise cache usage.

[1] https://blog.cloudflare.com/branch-predictor

Re: Beating the Compiler

#73
post #54
post #46

Earlier quoted context omitted.

It simply doesn’t scale. You can only superoptimize very short runs of code, nowhere anywhere close to even smaller code bases, let alone big ones.

It scales well enough. You can apparently run Souper on SQLite in 24 hours with a beefy machine, according to a talk I recently attended, by one of the developers.

That’s a cool data point, thanks! Though mind that it is a superoptimizer on LLVM bitcode, not on machine code itself, avoiding all the combinatorial explosion of register allocations and probably a bunch of more, but I don’t know enough about the program.

Re: Beating the Compiler

#74

I wish you wouldn't broadcast the sentiment contained in the first paragraph. Compilers lack the ability to consistently perform many basic optimizations to an embarrassing extent. Including even the ones you would think would be the first optimizations you'd implement when writing a compiler. Open up Godbolt and tell me if you still think the compiler knows best. I try to submit at least one issue to LLVM every time…

> Sorry for the rant

No problem here. I deleted a rant turning into a screed about blog articles superimposing "The Book of Dragon" and "The Dragon Book", but after some consideration found this link:

https://en.wikipedia.org/wiki/File:Graham%27s_Hierarchy_of_D...

With respect to "refuting the central point", if in the OP it is "Performance engineering should be about knowledge and science, not superstition and myth. (Godbolt not Godwin?)", then I agree. See:

https://ocw.mit.edu/courses/6-172-performance-engineering-of...

[I think Graham's hierarchy of disagreement ought to be used to color down votes, especially here.]

Re: Beating the Compiler

#75

Earlier quoted context omitted.

I am going to be the token programming language researcher and say that what you really want is a dependently typed assembly language that your dependently typed higher level language lowers to. One school of thought that has yet to bear fruit in “mainstream“ programming, but gives tantalizing hints of what is possible, is expressing increasing amounts of your programs constraints in the type system, thereby informin…

> want is a dependently typed assembly language Doesn't make any sense. The "type constraints" on assembly operands (registers and numbers) is the ISA and thus those constraints are combinatorial not logical

You misunderstand. If I, at the assembly level, could express things like "this register ranges from 0 to 4"—I might be able to provide ever-lower levels of the stack with more information about my intent. Maybe the ISA can now do something clever to further optimize my program. Now, there will likely always be a time when all types are erased, but if we can push that erasure lower and lower in the stack, then compilers have more and more information about what we actually want them to do, provided our type systems are rich enough to express that intent.

Re: Beating the Compiler

#76

Earlier quoted context omitted.

> want is a dependently typed assembly language Doesn't make any sense. The "type constraints" on assembly operands (registers and numbers) is the ISA and thus those constraints are combinatorial not logical

You misunderstand. If I, at the assembly level, could express things like "this register ranges from 0 to 4"—I might be able to provide ever-lower levels of the stack with more information about my intent. Maybe the ISA can now do something clever to further optimize my program. Now, there will likely always be a time when all types are erased, but if we can push that erasure lower and lower in the stack, then compil…

> "this register ranges from 0 to 4"

that's not a type system, that's an ILP. and we already have that in many compilers (bindings to ILP solvers).

> Maybe the ISA can now do something clever to further optimize my program.

this is a malformed sentence - the ISA is fixed and isn't making any gametime decisions about your code (modulo branch prediction/cache-fretching). it's all in the compiler and like i said we already have this in many many compilers and it's surfaced in various ways (eg trip count on loops).

Re: Beating the Compiler

#77

Earlier quoted context omitted.

You misunderstand. If I, at the assembly level, could express things like "this register ranges from 0 to 4"—I might be able to provide ever-lower levels of the stack with more information about my intent. Maybe the ISA can now do something clever to further optimize my program. Now, there will likely always be a time when all types are erased, but if we can push that erasure lower and lower in the stack, then compil…

> "this register ranges from 0 to 4" that's not a type system, that's an ILP. and we already have that in many compilers (bindings to ILP solvers). > Maybe the ISA can now do something clever to further optimize my program. this is a malformed sentence - the ISA is fixed and isn't making any gametime decisions about your code (modulo branch prediction/cache-fretching). it's all in the compiler and like i said we alre…

Those who say it cannot be done should not interrupt someone doing it.

https://www.cs.cmu.edu/~rwh/papers/dtal/OGI-CSE-99-008.pdf

It's not perfect, but dependently typed assembly languages isn't something I just made up. Maybe there's a mismatch between the terms we're using?

Re: Beating the Compiler

#78
post #12

Good article, brings the data to back it up. Unfortunately, it was hard to read with the monokai.css theme because comments were nearly invisible, and a lot of your information was in comments. Changing the color from #75715e to #95917e did the trick. I guess Monokai is for programmers who never read comments.

Thanks for the feedback; I tweaked the brightness and pushed the change.

Nicely done.
Post reply on HN