Ya that's a hilariously naive take (the quoted line not your response) given PGO, to say nothing of MLGO.
Though, of course, in practice you can use pseudo-random bits and fix the seed.
It's bit of a stretch, sure, but I don't expect my performance problems to go away by recompiling stuff over and over again without changing either the code or flags and expecting the optimizer to make a better decision next time. It doesn't work that way.
But in practice it does work exactly that way because of PGO and if we're precluding PGO then the observation is as banal as "programs that have no side-effects are pure". Like I get that the post is trying to paint some beautiful picture about how compiler passes are abstract beautiful transformations of representations of programs but it's not a useful picture at all.
It is actually a very useful picture especially to a beginner.
PGO is an edge case and not used a whole lot in practice. Many compilers do not support it at all, even production compilers. Someone learning to write a compiler does not need to think about PGO. And besides, a compiler with PGO is still a pure function of source + flags + profile.
Both clang and gcc support `-fprofile-generate`. Beyond that generic infrastructure, in my area (DL compilers) if you're not doing PGO/autotuning you're not serious.
>Someone learning to write a compiler does not need to think about PGO.
That's like saying someone learning to write a compiler doesn't need to think about optimization at all - sure maybe the first time. But then every time after that it should be at the forefront of your mind.
How many binaries in a typical Linux distro are built with PGO for example? The answer is approximately zero.
Congratulations on your recent PhD in quantum machine learning or whatever -- I hope you find some way to speed up FB/G's ad serving algorithms by 1% and land that promotion. I'm sure you're very smart.
Your point in bringing up Linux was to reiterate your original point? Interesting.
> I hope you find some way to speed up FB/G's ad serving algorithms by 1% and land that promotion. I'm sure you're very smart.
lol
It is pretty useful picture in my eyes, because that's what I've been observing since like forever. Non-deterministic compiler would be pretty hard to test or reason about.
It might be a banal observation, but an important one if you want to contrast a compiler with something like an OS kernel or most modern programming projects that interact heavily with outside world. When you throw hardware, network traffic, or users into the mix, it gets crazy.
- Bug in your program? Could be a dependency of a dependency built wrong, better do a full clean and rebuild.
- All of your pre-release tests passed? The code you shipped doesn't work, because you hit that unlucky 1%. Imagine how bad this would be back when software was released on CDs...
- Have 70 dependencies which are like this (not hard in the webscale era)? Now your CI needs to retry every build up to 10 times, because every build has a ~63.4% chance of failing. And there's still ~1% chance your CI fails anyways because you got 10 unlucky builds in a row.
I'm sure there are more stories of these kinds of issues...
That's not the only kind of non-determinism, you know?
Lots of algorithms benefits from access to random bits, too.
> for each input, there is one and only output
A randomized algorithm which uses non-determinism but produces the same output is OK.
Also, psuedo-randomness is OK as long as the same program compiled in the same version of the compiler always gets the same seed.
But if the algorithm can produce different output causing the same program to compile to different assembly, that's a problem. Unless you can formally prove that every possible variation will have the same behavior, but formal methods + non-determinism is hard, so it usually isn't worth it.
Even random hash order in hashmaps can create problems: see https://github.com/rust-lang/rust/issues/84447 and https://github.com/rust-lang/rust/pull/82272#issuecomment-82..., though this is a very small issue in the diagnostic reporter and not a case of 2 valid programs with different semantics.
Or anything that compiles a corpus into a model, though we typically call that training rather than compilation :).
Having said that, most people are not careful, and most languages make it very hard to be careful.
The keyword is 'deterministic parallelism', if you want to look into the research. See eg https://www.well-typed.com/blog/2012/12/deterministic-parall...
Nondeterministic doesn’t mean random. Consider how NFAs relate to DFAs and then realize the same applies to nondeterministic TMs.
I support deterministic compilers due to deterministic builds. For a given input source code, compiler executable, and command-line flags, it should always produce the same binary, regardless of the time of day, random number generator, I/O, threading, environment, etc.
My refutation of the article is that he made it sound like a compiler is like computing Fibonacci numbers - here are all the valid inputs, here is how each one maps to its one and only correct output answer, so fill in the code to accomplish that.
Also in the previous paragraph he wrote:
> Because the most basic compiler architecture is standard, you have limited boundaries and degrees of freedom when designing one. This might sound restricting, but actually, it's freeing because you get to play in a predictable sandbox.
Not even close! Optimization and code generation is a fantastically hard problem full of heuristics and tradeoffs.
There is definitely more than one way to compile C source code to x86 binary code. There is even more than one way to compile TypeScript to JavaScript if you consider things like whitespace, indentation, and constant folding.
The rest of the article is alright.