Like can you be really good with Assembly and still not be certain your effort is actually worth not doing it in a higher language?
Like can you be really good with Assembly and still not be certain your effort is actually worth not doing it in a higher language?
If you’re going to take the trouble of writing assembly, you should do it right; figure out the fastest you can theoretically go, and see if you can get within a few percent of that without using assembly. If you can, stop. If not, figure out why you can’t, file compiler bugs as applicable, and then write assembly where it’s necessary. Re-measure, and if you aren’t within a few percent, figure out why not, then go back to step 1.
The thing is, optimizing compilers don't actually do any optimization in the classical sense. They don't do run-measure-modify loop as programmers do so all they can apply to the code is the heuristics some other programmers taught them. Some things are trivial like loop unrolling or function inlining. Some are not, like trigonometric approximations.
In the long run, when a compiler stops, a person goes further. That's why empirically, hand-made code is still faster than the compiled one. Of course you can write slow code in Assembly, but if you already decided to go low, you'll optimize your thing until satisfied with the result.
One particular thing comes to mind, C is ridiculously bad with automatic superscalarization (try VTune's HPC characterization on any code you like and see). Sure, you can use intrinsics and implement things manually, but that would be essentially the same as writing in assembly.
There is another contender though. Spiral (https://spiral.net/) that actually do solve the optimization problem can in fact be as effective as a human programmer and at a fraction of the cost. Spiral is overly specialized, so it's not a threat to all the HPC, but a more generic thing may indeed become a gamechanger.
This optimization is so old, I'm not even sure if it's still worth the effort. It definitely worked in the 90s.
What you do here is you save on division, and lose on instruction cache. This might look good on a benchmark when all your code fits the cache nicely, but bite back in-vivo. You should try it out in an actual problem and see how it goes.
Division is really really slow in CPUs, as I understand it. Like, CPUs are just awful at it.
It being an old opt doesn't mean it is invalid. I'm not aware of CPUs getting meaningfully better at division.
CPUs are not getting better at division per se, but they are getting better at all the ALU operations compared to the memory latency. You can add more transistors on a chip, but you can't cheat the light speed and make signal travel 30 cm in less than a nanosecond. So you need to bring your data closer, you need caches. Code, unsurprisingly, is also data, and it also goes through the instruction cache.
This optimization is instruction latency vs. cache intake. It may or may not be beneficial depending on the rest of the program. I've already seen both Clang and GCC produce faster code with -Os rather than with -O3.
https://github.com/ArmageddonGames/ZQuestClassic/commit/0a78...