5 ms·
I don't think it's even possible any more. Haswell and later are 8-wide designs, but can only fetch+decode and retire 4 instructions per cycle (peak). So one wo
by dom0 10y ago
I don't think it's even possible any more. Haswell and later are 8-wide designs, but can only fetch+decode and retire 4 instructions per cycle (peak). So one would need ops that decode to 2+ execution-unit independent µops.
Linear data-dependent algorithms are also such a huge pain: "Why does that only shovel 500 MB/s?" Well... five instructions long dependency chain, that's why!
(Yes, the last bit may be a bit unrelated to the discussion at hand)
- kbwt 10y ago> 8-wide designs, but can only fetch+decode and retire 4 instructions per cycle That's where the Trace Cache helps in tight loops.
- dom0 10y agoThe µop cache (trace cache went out the window) doesn't help with fetching instructions AIUI, but accelerates decoding them. So the 4 insns/cycle fetch bandwidth is not changed by that.
- ant6n 10y ago> five instructions long dependency chain, what's why! Skylake apparently has up to 224 instructions in flight. So during those dependent 5 instructions, theoretically it could be doing some of the next hundred. Or the previous hundred. I simply find it hard to believe that Intel would design monsters with so many out-of-order instructions, but still every random bit of software will constantly get completely stalled by dependent instructions.
- dom0 10y ago> So during those 5 instructions, theoretically it could be doing some of the next hundred. Not if the next iteration of the loop not only branches on the previous result (okay, that one's easy on the predictors), but also depends on the previous iteration :) -- The basic idea behind these designs is that a) most software is a fat, ugly blob of shit which sometimes calls into b) specific functions implementing high-performance algorithms (be it compression, encryption, hashing, ..., image manipulation, ...) So for b) you want a capable design to have high throughput, and that also plays well with a) because it means that the core can spend most of it's time blocking on memory or executing an instruction or two every couple cycles. It also means that SMT works very, very well, since now you got two fat blobs smearing their shit around, but the core has more than enough resources to deal with that. That's why SMT gives 50++ % speed-ups for many applications. Because they're fat blobs.
- ant6n 10y agoThat doesn't strike me as true. It appears more likely that these cpu monsters with OOE and register renaming are like just-in-time trace optimizers that can use run-time values to improve the optimization. That is, take shitty code, and try to run it as fast as possible, and try to squeeze multiple instructions per cycle out of it, by optimizing over hundreds of instructions in real time. If the intention was just to speed up hand-tuned library functions, it would be much easier to ask the library-hand-tuners to figure out instruction dependencies ahead of time (instead of doing re-ordering) and to provide a lot of registers (instead of doing renaming).
- dom0 10y ago> If the intention was just to speed up hand-tuned library functions, it would be much easier to ask the library-hand-tuners to figure out instruction dependencies ahead of time (instead of doing re-ordering) and to provide a lot of registers (instead of doing renaming). That's not a scaleable approach, i.e. only works for some set of parameters that are then set in stone after that. Changing the parameters means changing the ISA. An ISA that did something similar was Itanium and it failed spectacularly. On the other hand, the idea to offload these optimizations to the CPU is quite old. E.g. "SPARC" is for "scaleable processor architecture" -- the scaleable part mostly refers to the number of register windows the CPUs have. On the other hand, other processors do this with great success. Examples here are the extremely primitive cores used in HPC accelerators for the TOP500, or those used in GPUs. There this works since code can be hand-tailored to a specific computer, or because the problem itself and algorithmic approaches ensure that a compiler can generate good SIMT code (in the case of GPUs). > are like just-in-time trace optimizers that can use run-time values to improve the optimization. Practically no optimizations found in CPUs do that (looking at "run-time values"). Or I'm misreading you here.
- ant6n 10y ago> Changing the parameters means changing the ISA. That's not true. One just needs to _add_ to the ISA. That's exactly what SSE and AVX do: oodles of registers, oodles of compute power. Apparently those are to be used by those specialized libraries you mention. OOO, register-renaming, and having the ability of hundreds of instruction in flight (!) seem more about improving general computing performance. > Practically no optimizations found in CPUs do that (looking at "run-time values"). Or I'm misreading you here. Modern CPUs are like essentially like trace optimizers that do depend on run-time values. For one, there's the branch predictor. Secondly, instructions may execute as soon as the dependent data becomes available. So it's possible that some memory load happens quickly because data is in L1, compared to another independent instruction doing a memory load from main memory. Since the data from one instruction arrived earlier, it can get scheduled ahead of the other -- in real time.