10 ms·
I also had the initial impression that the article is misleading, but later on the author made the point that the C compiler is doing significant work to reorde
by ge0rg 8y ago
I also had the initial impression that the article is misleading, but later on the author made the point that the C compiler is doing significant work to reorder / parallelize / optimize the code. I agree that x86/x64 is not a low-level language either, but even if it was, with the description the author provided, I'd agree with his point of C not being low-level.
Regarding cutting off backwards compatibility to improve the design, Intel's Itanium (affectionately called "Itanic") was a very progressive approach to shift the optimization work from the CPU (and the compiler) to just the compiler. I'm not sure what the reasons for its failing were, though.
- pcvarmint 8y agoItanic failed because Intel/HP initially still used a front side bus memory architecture, which could not support the bandwidth necessary for peak performance on anything but matrix multiplication and other computations where most of the work is done in-cache. Then Opteron came around, with its faster memory, and Intel was suddenly thrown back into reality. Itanic was also in-order (at least as far as dispatch), meaning anytime an instruction was stalled, so were all instructions in the same bundle or after it. One "non-low-level" idea on Itanic, which never really panned out in practice, was for the assembler to automatically insert stop bits ;; marking assembly code "sequence points", instead of the programmer having to do it manually. But in practice, everyone did it manually, because they'd rather know how well their bundles were being used, and whether they could move instructions around in order get the full 3 instructions / bundle (6 instructions / clock). And explicit stop bits did not provide any advantage to future hardware by marking explicit parallelism, because at every generation everyone was concerned about obtaining maximum performance on the current machine, which involved shuffling instructions into 6-instruction double-bundles, often at the expense of parallelism on future implementations (which never went beyond two bundles / clock).
- Avshalom 8y agoPart of it was the sort of giant blind spot that "C is a low level language" creates that made even Intel forget how many man-years of optimization were actually in C compilers and the attendant hubris that "oh we can whip up something that'll beat it between now and when we start shipping the chips"
- mattnewport 8y agoI think you can make a good case that the failure of the Itanium (and other similar attempts to un-hide some of this stuff like the IBM/Sony Cell used in the PlayStation 3) was precisely because they tried to shift optimization work from the CPU to the compiler / programmer.
- greglindahl 8y agoFunny, the compiler people I've worked with complain that Itanium tried to do too much in hardware, like the hw support for loop unrolling, which made superpipelining optimizations in existing compilers much more complicated.
- mattnewport 8y agoLoop unrolling is one of those optimizations that actually highlights the need for dynamic CPU optimizations like out of order execution and speculative execution. It's very difficult to statically make a good decision about the optimal amount of loop unrolling to do, especially if you want to generate code that will continue to perform well on future CPUs using the same ISA. Even when targeting a specific CPU model it's difficult however since you don't know statically how many iterations of the loop you're expecting, what's currently in cache, what other code might be running immediately before or after the loop, what's running at the same time on other threads, etc.
- greglindahl 8y agoItanium's hardware did not make any of these things easier.
- wbl 8y agoThe compiler wasn't smart enough. There is information available only at runtime that can be used to get out of order execution and superscalar execution, and the compiler doesn't see any of it. More effort on standard architectures paid off.
- PersistentCough 8y ago> the C compiler You mean C compiler X has the feature of Y. There are lots of compilers and that's not part of the language.
- umanwizard 8y agoTheir comment makes sense if you interpret "the C compiler" to mean "mainstream C compilers that 99% people use in production" or even just "gcc and clang". We're talking about concrete things in the real world here, not philosophizing about the language spec.
- PersistentCough 8y ago> not philosophizing about the language spec. That's exactly what's going on.
- Avshalom 8y agoAnd yet small device C and Gcc/clang are onky kissing cousins and we (well people that aren't me: ustedes) still rhetorically lump them together as a single language.
- deleted 8y ago[deleted]
- SolarNet 8y agoNot sure if facetious, but it failed because shifting that work caused it to be slow and not backwards compatible.
- pera 8y agoI'm not an expert, but I don't think the optimization phase should be really considered here: the same kind of pattern matching used by (e.g.) LLVM to find optimizable sequence of statements also could be used by any assembler. NASM for instance offer some level of optimizations, so I think optimization should only be considered when it's part of the language specification itself, like in Scheme. IMO C is close to low-level because it's relatively easy to imagine the resulting unoptimized assembly given some piece of code (which is why some people jokes about C being a macro assembly). Maybe this old debate should get an slight update... and this could be the starting point: Is modern x86 assembly still "low-level"? :)
- munificent 8y ago> the same kind of pattern matching used by (e.g.) LLVM to find optimizable sequence of statements also could be used by any assembler. Some of the simpler optimizations, sure. But modern backends do many incredibly sophisticated optimizations that are way beyond any kind of simple pattern-matching-and-substitution model. Even fundamental "optimizations" like register allocation use quite sophisticated algorithms. Optimal register allocation is NP-complete, so compilers use heuristics on top of graph coloring algorithms to do their best. Most other optimizations rely on type analysis, data flow analysis, liveness analysis, etc.
- vvanders 8y agoIt would be interesting to revisit a world where languages/compilers were built explicitly with common memory access semantics/out of order op/etc in mind. One of the things that really excites me about Rust is that it's single mutable reference enforcement means you can run run `restrict` 100% of the time if you wanted which is a non-trivial performance boost. I think it's not enabled today but from previous discussions it sounds like that's just a matter of plumbing through the right things to LLVM. Every time I've seen that rolled out in a C/C++ codebase someone invariably forgets about pointer aliasing and you spend a week tracking down some non-deterministic behavior.
- pera 8y agoMy point was that since optimization is also possible in assembly, and since assembly is considered low-level, then optimization per se shouldn't be used as something that characterize high-level languages exclusively. But it is true that some abstractions used by high-level languages enable quite complex optimization techniques, so there is a clear correlation between the level of a language and the ability of its compiler to analyze and optimize programs.
- skywhopper 8y agoThere was an article on Hacker News recently that covered some of the reasons for Itanium's failure to realize its theoretical benefits. I'm not finding it now, but IIRC, the argument made was that predicting likely-parallelizable code is actually a lot harder to do at compile time, and that, like so many ultra-optimized systems, the real world works much differently and a messier, more random approach ultimately yields far better performance.
- drbawb 8y ago>the argument made was that predicting likely-parallelizable code is actually a lot harder to do at compile time So don't do it at compile time? That's really a very weak argument against the Itanium ISA, and honestly more of an argument against the AOT complication model. Take a runtime with a great JIT, like the JVM or V8, and teach it to emit instructions for the Itanium ISA. (As an added advantage these runtimes are extremely portable and can be run, with less optimizations, on other ISAs without issue.) The problem, as always, is that nobody with money to spend ever wants to part with their existing software. (Likely written in C.) In 2001 Clang/LLVM didn't even exist, and I'm not familiar with any C compilers of the era that had so much as a rudimentary JIT.
- marshray 8y agoThis argument has been made since the introduction of the JVM in the early mid-90's. Seems to me like if, in practice, JIT provided better performance then by now people would be rewriting their C/C++ code in Java and C# for speed.
- lmm 8y ago> Seems to me like if, in practice, JIT provided better performance then by now people would be rewriting their C/C++ code in Java and C# for speed. It's a little bit faster, not faster by enough to matter. If you're going to rewrite C/C++ code for speed you'd go to Fortran or assembler, and even then you're unlikely to get enough of a speedup to be worth a rewrite. New projects do use Java or C# rather than C/C++ though.
- colin_mccabe 8y agoI think people often overestimate how smart the compiler is. DJB had a slide deck about this: http://cr.yp.to/talks/2015.04.16/slides-djb-20150416-a4.pdf http://cr.yp.to/talks/2015.04.16/slides-djb-20150416-a4.pdf Compilers are really useful... but, if it really has to be fast, you still need to have a human in the loop. I was also under the impression that there hasn't been much improvement in compiling C/C++ in a long time. It would be interesting to compare the performance of gcc from 15 years ago versus gcc today, on a real world piece of code. I suspect you wouldn't see much difference (aside from the changes in C dialect over time), and some added features in the new version. Has anyone run this experiment?