I'm still unconvinced this is fundamental. It certainly was flawed back then, but compiler theory has improved a LOT since then, we have polyhedral optimization, e.g. that we didn't have access to... You could probably optimize delay line technology that way.
If you don't know whether some value will hit in the L1 or the L3 cache there's wild variance on how long it'll take so you have to do something else in the meantime. On x64, that's the pipeline and speculation. On a GPU, you swap to another fibre/warp until the memory op finished.
Fundamentally the hardware knows how long the memory access took, the software can only guess how long it will take. That kills effective ahead of time scheduling on most architectures.
By the 2nd or 3rd generation, Intel had made some changes that really improved performance a lot. Was the final generation of Itanium the 4th generation?
Sure.
But it's very easy to level down. And almost impossible to level up.
You can find out by disabling the stride prefetcher and observing the 90+% performance regression in all your software!
On x86 SMT gets a bad rap because its never been tremendously effective. It's much more effective in IBM's implementation on Power. It wouldn't be hard to imagine some Itanium SMT monster.
With 2 unstalled threads you effectively halve it (in terms of throughput), 4 unstalled threads you effectively quarter it, etc.
Itanium did have SMT
Perhaps as part of the trend towards increasingly heterogeneous architectures, we'll see big VLIW coprocessors for power efficiency in certain serial workloads (GPUs are massively parallel but little VLIW coprocessors; however, they do have dynamic scheduling).
Which would be fine if there was a time machine available to send back what we know now to the past. But at the time having sucky compilers for what you want to (try to) accomplish was a bad idea.
The same decision now may be good, but then it was a mistake. It'd be like trying to have a Moon landing project in the 1920s: we got there eventually, but certain things are only possible when the time 'is right'.
Current way, while arguably pretty wasteful on all the micro-optimizing CPU does on incoming bytecode, allows designers to nearly freely expand hardware to meet the needs without having compilers to produce different code.
OoO execution does an end run around this by examining the program as it runs and adapting to the current reality rather than a simulated reality. This is the same reason a JIT can do optimizations that a compiler cannot do. The ability to look 500-700 instruction into the future to bundle them together into a kind of VLIW dynamically is a very powerful feature.
As to compiler theory, it really isn't that advanced. Our "cutting edge" compilers are doing glorified find-and-replace for their final optimizations (peephole optimization).
Look at SIMD and auto-vectorization. There are so many potential questions the compiler can't prove the answer to that even trivial vectorization that any programmer would identify can't be used by the compiler to the point where the entire area of research has resulted in basically zero improvements in real-world code.
The thing is, on regular, array-based codes, it's great. And it was then, too -- the polyhedral approach was all being developed at exactly that time, but maybe it's not clear in hindsight because the terminology hadn't settled yet. Ancourt and Irigoin's "Scanning Polyhedra With Do Loops" was published in 1991. Lots of the unification of loop optimization was labeled affine optimization or described as based on Presburger arithmetic. But that is the technology that they were depending on to make it work.
But most code we run is not Fortran in another guise. The dependences aren't known at compile time. That issue hasn't changed much.
The one change now is that workloads that were called "scientific computing" then are now being run for machine learning. But now it doesn't make sense to run regular, FP-intensive codes on a CPU at all, because of GPUs and ML accelerators. So what's left for CPUs that excel on that workload? I'm not sure there is a niche there.
One of the other problems with Itanium was that it was supposed to be an "industry standard" 64-bit processor. But Intel and HP were never quite able to square that with a situation where HP at least saw themselves as more equal than others given their role in the design.
I don't recall any issues with the ISA, and we really liked using its early container capabilities (HP Vault).
Perhaps, there was a belief back then that compilers could be easily optimised or uplifted to generate fast and efficient code, and that did not turn out to be the case. Project management and mismanagement certainly did not help either.
I wonder how a VLIW architecture would pan out today given advances in compilers in last three decades, and whether a ML assisted VLIW backend could deliver on the old dream.
The big problem is SMT, since it's hard to share a VLIW core between processes, while a superscalar core shares really well.
Older GPUs seemed more VLIW-like because they were descended from fixed-function rendering pipelines and essentially just exposed the control signals via instruction encodings. Over time, shader cores have become less VLIW-like, e.g. look at any reverse engineering of recent Nvidia architectures.
This makes sense for the same reason you give for SMT: if you're trying to execute from multiple instruction streams on the same execution units, it makes more sense to use small individual instructions rather than large puzzle pieces.
A modern CPU has the same goal of extracting ILP but accomplishes it in a very different way. The instruction stream is short instructions, each of which specifies a simple operation, and these are reassembled using sophisticated dynamic logic into micro-ops, which then get executed in a fairly similar fashion as a VLIW machine - there are a large number of ports (8 is fairly typical these days), each of which performs a separate operation such as arithmetic, load/store, branch, etc.
A GPU has a similar goal of extracting lots of parallelism but does it in a very different way to both VLIW and modern superscalar CPUs. Each instruction operates over a large SIMD vector - 32 is typical, but this varies from 8 (Intel SIMD-8) to 128 (Imagination & optionally Adreno). The instruction specifies many copies of the same operation, so doesn't have to be that big. On RDNA3 for example[1], the basic instruction size is 32 bits, but 64 bits is also common (see section 6.1 for a summary of scalar and 7.1 for a summary of vector encodings).
These instruction sizes are a bit bigger than typical for CPU, for two main reasons. First, there are a lot of registers (256 vector registers), so that needs a lot of bits to encode. Second, it's common to add extra operations such as negation or absolute value in the same operation. But these operations are generally fairly inexpensive modifications on existing data, not completely separate as in VLIW.
In general, execution on a GPU is in-order, so all the reorder buffers and other techniques of superscalar CPUs are not used. Instead of trying to extract as much parallelism as possible from a single thread, a GPU will use that transistor budget to splat more execution units (and thus more threads) on the chip.
[1]: https://developer.amd.com/wp-content/resources/RDNA3_Shader_...
[1] https://en.wikipedia.org/wiki/TeraScale_(microarchitecture)
[2] https://www.anandtech.com/show/4455/amds-graphics-core-next-...
It was trying to optimize for instruction-level parallelism when power efficiency and thread level parallelism were coming into vogue. Arguably companies like Sun overoptimized for the latter too soon but it was the direction things were going.
A senior exec at Intel told me at the time the focus on frequency in the case of Netburst was driven by Microsoft being uncomfortable with highly multi-core designs--and I have no reason to doubt that was one of the drivers. There was a lot of discussion around the challenges of parallelism, especially on the desktop, at the time. It generally wasn't the problem the hand wringing suggested it would be.
I always envisioned a day where we'd have devote the small cores to "parasitic load" tasks-- your media player, Slack/Discord/etc., and a thousand OS maintenance threads. They might run at 95% load to do not very much, but it's no big deal-- the actual software you cared about now has the big cores to itself, and context switching (along with cache and branch-prediction losses) are reduced. I could even imagine getting to the point where tasks could requisition cores on a "no disruptions until actually yielded by the main process" basis for real-time or maximum performance tasks.
Even on a modern ultralight laptop, I can run two chrome profiles, three instances of vscode running different projects, docker and a few other things and the CPU never gets pegged. There's a ton of memory pressure from a memory leak somewhere that I haven't bothered tracking down yet- I suspect the SWC compiler (thanks, rust) but haven't proven it yet. All that and I'm still getting 8+ hours of battery life.
I'm really tempted by the idea of a Framework style laptop with user serviceable parts, but my work style has me moving a fair amount, so not having battery or thermal issues is such a boon I don't know that I could make the switch. In the last 6 hours I've written and compiled code, run tests, attended video calls, streamed video from websites, browsed the internet for recipes for dinner, chatted on slack and am still on 46% battery remaining. I have yet to hear the fans turn on.
The two areas this thing will fall down on is music and gaming. The speakers are pretty bad, and though it can run light games off of steam, I doubt it would do well with anything super graphically intense (though I haven't actually tried much, to be honest). Also, the built-in webcam sucks, but decent webcams and headphones are cheap, so it's really only games that you'd want something else for.
I've looked at the LG gram before (the 2021 model [0]), but wasn't convinced. And now after seeing a friend's new Lenovo legion 5 I'm even more uncertain of which one should I pick. (That Lenovo has a handy button to set the power envelope, which seems to actually work.)
I also usually move a lot, but I don't want to optimize for that. It's easier to find a power outlet than to cool a throttled laptop.
I don't know if / how it runs linux, but I've got a friend with a legion, and was also happy with it.
If you'd rather have better graphical performance than battery life, definitely go with the legion. If you can't stand the thought of being tethered to a power cord every time you have to do something serious, then you might want to consider the gram.
I've had gaming laptops before, and after putting the battery through the ringer after awhile it was a struggle to get 4 hours unplugged, which I simply didn't want to deal with again.
My logic goes something like "why have 4 small cores and 4 big cores when you could have 8 big cores". Then the argument goes "yes but the small cores use less power", to which my replay is "true, but the big cores finish faster and can spend more time sleeping, I think the power argument evens out ether way". The real gain is to have better power management for the cores, not by having weird small cores.
One can really notice it on dual cores.
Also the Alpha was the utter opposite of design by committee. A quick skim of the alpha ISA would show you that.
And it wasn't like the Alpha was some embodiment of perfection either. E.g. that mindbogglingly crazy memory consistency model.
I don't at all believe this was true.
> that mindbogglingly crazy memory consistency model
I guess the utterly competent designers were actually stupid eejits then? The memory consistency was AFAI could determine to reduce to the utmost the hardware guarantees and therefore hardware complexity. It was done for speed.
I have the greatest respect for the Alpha design team, they designed a thing of elegance and even beauty. You could learn a lot from it - I did.
No, I don't think that. But I don't think they had some superhuman foresight either, and they made some decisions that in retrospect were not correct. And with the memory consistency model, they made the classic RISC mistake of encoding an idiosyncrasy of their early implementation into the ISA (similar to delay slots on many early RISC's).
> You could learn a lot from it - I did.
I used Alpha workstations, servers and supercomputers for my work for several years back in the day. They were good, but not magical, and even back then it was quite clear there was no long term future for Alpha.
I never suggested alphas were magical, but they did seem extremely good and they were designed for future expansion, it seemed to me they were killed off very much not by competitor supremacy.
Good answr, thanks
These barriers also meant that correct multi-threaded alpha code was no longer particularly fast, because you have to insert expensive memory barriers basically everywhere.
Had Alpha not died early, they would absolutely have eventually moved towards a more strict memory model. As it was, it was essentially an irrelevant architecture by the time people started really hitting all the pitfalls.
> These barriers also meant that correct multi-threaded alpha code was no longer particularly fast, because you have to insert expensive memory barriers basically everywhere.
I don't buy it. MBs are for multi-core code, and in such code you typically do much work on a single core then have a quick chat with another core. So the MBs are there for the inter-core chatter only. In that case having fast monocore code is a big win.
The various memory barriers and locking primitives are arch-specific code, and at least smp_read_barrier_depends() is a no-op on all architectures except Alpha. Apparently around the 4.15-4.16 kernels there was a bit of de-Alphafication going on which entailed removing much Alpha-specific code from core kernel code. Further in 5.9 {smp_,}read_barrier_depends() were removed from the core barriers, at the cost of making some of the remaining memory barriers on Alpha needlessly strong.
For more info, search for Alpha e.g. in
https://www.kernel.org/doc/Documentation/memory-barriers.txt
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/lin...
https://open-std.org/JTC1/SC22/WG21/docs/papers/2020/p0124r7...
https://mirrors.edge.kernel.org/pub/linux/kernel/people/paul...
The biggest reason Alpha was a "workstation" chip was margin and R&D issues. It was fast, but they couldn't manufacture in high volume which drove per-chip costs much higher than they could have been if paired with a company like Intel. Meanwhile, complete dependence on manual layout for everything pushed development cost and time to market too far out. Once again, Intel's design tools could have helped reduce this overhead.
Could this have worked better with JIT-compiled applications, e.g. Java given a sufficiently clever JVM, where assumptions can be dynamically adjusted at runtime?
The other point in favor of this approach now is that far more code is using high-level libraries. Back then there was still the assumption that distributing packages was hard and open source was distrusted in many organizations so you had many codebases with hand rolled or obsolete snapshots of things we’d get from a package manager now. It’s hard to imagine that wouldn’t make a difference now if Intel was smart enough to contribute optimizations upstream.
With respect to ARM, Intel pretty much blew it, especially on mobile. They were so determined to exploit their x86 beachhead. I remember at an IDF, they were even trying to make a case for how it was important to run x86 everywhere so that Flash would run consistently.
One concern I remember was correctness: one company I worked at didn’t find a benefit worth dealing with a second compiler’s quirks and IIRC some scientists I supported evaluated it but never used it because some of their model output varied (classic floating point drift).
With all due respect, this is simply not true. Especially for the time, GCC was the most sophisticated compiler out there, and the only one that could be easily retargeted to a new or another platform due to the use of the intermediate representation language (IRL). A new code generation backend could be boostrapped within days using the IRL. Cross-compilation for any supported target platform whilst running on the same host was also only possible with GCC. There were no other known precedents at the time (I am not counting pcc, the portable C compiler, due not being comparable to gcc).
In terms of the code generation, GCC was quite up there as well albeit performance and quality of the generated code varied across platforms, sometimes wildly. E.g. the native Sun C compiler generated consistently faster code for SPARC (although their C++ compiler that they had acquired from a third party was buggy as hell).
For Itanium, the GCC Itanium backend was not efficient, and it was a well known problem. On 32-bit x86, GCC generated faster and better code than most commercially available C/C++ compilers with a few exceptions being Intel and Metaware High C compilers (both of which not being widely available and being exorbitantly expensive for a average developer) and being comparable or faster to the Watcom C compiler (Watcom did have an edge over GCC on producing much faster floating point code and the default C struct alignment rules, and GCC had an edge due to allowing control over how many CPU registers could to pass input parameters into a function). Id Software, with the release of Quake 1, had ditched the Watcom C compiler and replaced it with GCC (DJGPP) due to GCC generating better code (I think John Carmack wrote about it at some point). GCC did not support Windows well, though.
GCC and LLVM have both been very sophisticated compilers albeit pursuing different objectives. LLVM appeared due to disagreements over the GCC licensing that RMS was insisting on – to preclude GCC from becoming extensible and allow 3rd parties to produce closed source plugins. So, LLVM was conceived as a modularised and extensible design being more conducive to research, experimentation and extensibility at the expense of supporting fewer platforms. GCC and LLVM have both eventually caught up and have now largely reached the feature parity with each other (with GCC still supporting a larger number of platforms and being a go to choice for embedded development).
I love monuments to hubris so I too have one in my garage-- a four-node SGI Altix 350.
So I don't really buy the "Itanium is bad architecture" story.
It's fate was probably decided around 1999-2000. At that point Itanium was still pretty good against Pentium 3 and Pentium 4. And name "IA-64" indicates Intel didn't plan to make 64-bit Pentiums. So eventually Pentiums would fill low-end segment while the rest would be occupied by 64-bit Itaniums.
AMD killed that plan by releasing AMD64 architecture. It was an obvious upgrade to x86, so it would clearly do better in the market than IA-64. So Intel decided to go for x86-64 too, and Itanium was doomed at that point. They didn't even bother making Itaniums with same clock speed as Xeons.
So it's definitely possible that if AMD decided to stick to 32 bits at that time, Intel would have pushed optimized IA-64. Also AMD64 could be worse than it is. E.g. if they decided to increase only register size but keep the number of registers the same, IA-64 could still come on top.
One of the best aspects of the Opteron was it also happened to be a fantastic 32-bit CPU in addition to AMD64. This was a period where a lot of software, even FOSS wasn't 64-bit clean. There was a lot of pointer arithmetic hiding deep in libraries that were assuming pointers would always be 32-bits.
The Opteron running a 32-bit OS at least as well as a 32-bit Athlon was a huge point in its favor. So your existing system running on new Opteron hardware ran fine and you could mix and match Xeon and Opterons in a fleet. Then switch over to 64-bit on the Opterons for (hopefully) better performance.
The other big problem was that the x86 compatibility story was worse than the earlier hopes. That meant that it not only wasn’t competitive with the current generation competition but often even the previous or worse - note losing to the original Pentium or even a 486 here:
https://tweakers.net/reviews/204/8/intel-itanium-sneak-previ...
Now, they could have improved that but statistically nobody was going to pay considerably more for lower performance in the hopes that a future update would improve matters.
The Athlon and Opteron weren’t just fast, they also had flawless 32-bit support so even if your 64-bit software update never happened you could justify the purchase based on their price/performance.
Intel kept the X86 price at a point where no bean counter would favor investing in new architectures. Fortunately AMD broke the headlock on x86.
I dunno about that.
My own personal opinion is that Intel has never been able to re-architect their way out of the fact that the cornerstone of their success is that they are selling x86, and their customers mostly don't care about the theoretical advantages of the bright shiny new thing. They just want to run their software just like they always have. There's a reason why IA-64 has joined iAPX432, i860, StrongARM and i960 as Intel footnotes (outside of the embedded market).
When they were philosophizing about what Itanic should look like, the only thing that x86 obviously needed from a market perspective was a bigger address space. And AMD was smart enough to deliver on that, and here we are.
Secondly, it's true that AMD hammered the nails in the coffin, but AMD wouldn't have mattered if Itanic had been faster, cheap, and on time. Itanic was a disaster partly because of overly complicated design by committee and partly because of the fundamentally flawed assumption (that you don't need dynamic scheduling, AKA OoO processing).
I have an Itanium in the garage, a monument to hubris.
UPDATE: I forgot to mention that from the outside it might seem that Intel had a singular vision, but the reality is that there were massive political battles internally and the company was largely split into IA-64 and x86 camps.
UPDATE2: Itanium was massively successful in one thing: it killed off Alpha and a few other cpus, just based on what Intel claimed.