Live data from Hacker News

Execution units are often pipelined

blog.xoria.org

81–90 of 102 posts

Re: Execution units are often pipelined

#81
post #57

Earlier quoted context omitted.

Right; it's easy to forget that superscalar CPU cores don't actually have to be in-order, but most of them are out-of-order because that's usually necessary to make good use of a wide superscalar core. (What's the best-performing in-order general purpose CPU core? POWER6 was notably in-order and ran at quite high clock speeds for the time. Intel's first-gen Atom cores were in-order and around the same time as POWER6…

POWER6 might indeed have been the last In-Order speed demon.

The IBM Z10 came out a year later. It was co-designed with POWER6 as part of IBM's eClipz project, and shared a number of features / design choices, including in-order execution.

Re: Execution units are often pipelined

#82
post #17

Earlier quoted context omitted.

FWIW, there are two ideas of parallelism being conflated here. One is the parallel execution of the different sequential steps of an instruction (e.g. fetch, decode, operate, retire). That's "pipelining", and it's a different idea than decoding multiple instructions in a cycle and sending them to one of many execution units (which is usually just called "dispatch", though "out of order execution" tends to connote the…

> Also IIRC there are still some non-pipelined units in Intel chips, like the division engine, which show latency numbers ~= to their execution time I don't think that's accurate. That latency exists because the execution unit is pipelined. If it were not pipelined, there would be no latency. The latency corresponds to the fact that "doing division" is distributed across multiple clock cycles.

Sorry, correcting myself here: it's cut across multiple cycles but not pipelined. Maybe I confused this with multiplication?

If it were pipelined, you'd expect to be able to schedule DIV every cycle, but I don't think that's the case. Plus, 99% of the time the pipeline would just be doing nothing because normal programs aren't doing 18 DIV instructions in a row :^)

Re: Execution units are often pipelined

#83

Earlier quoted context omitted.

We are interested in the software visible performance effects of pipelining. For small benchmarks that don't miss in the predictors or icache, this mostly means execution pipelining. That's the type of pipelining the article is discussing and the type of pipelining considered in instruction performance breakdowns considered by Agner, uops.info, simulated by LLVM-MCA, etc. I.e., a lot of what you need to model for tig…

Adding to this: the distinction is that an entire "instruction pipeline" can be [and often is ] decomposed into many different pipelined circuits. This article is specifically describing the fact that some execution units are pipelined. Those are different notions of pipelining with different motivations: one is motivated by "instruction-level parallelism," and the other is motivated by "achieving higher clock rates.…

[deleted]

Re: Execution units are often pipelined

#84
post #52

Earlier quoted context omitted.

> and it's a different idea than decoding multiple instructions in a cycle and sending them to one of many execution units (which is usually just called "dispatch", though "out of order execution Being able to execute multiple instructions is more properly superscalar execution, right? In-order designs are also capable of doing it and the separate execution unit do not even need to run in lockstep (consider the origi…

In-order parallel designs are "VLIW". The jargon indeed gets thick. :) But as to OO: the whole idea of issuing sequential instructions in parallel means that the hardware needs to track dependencies between them so they can't race ahead of their inputs. And if you're going to do that anyway, allowing them to retire out of order is a big performance/transistor-count win as it allows the pipeline lengths to be differen…

VLIW means Very Large Instruction Word. It is a property of the instruction set, not of the processor that implements it.

You could have a VLIW ISA that is implemented by a processor that "unrolls" each instruction word and mostly executes the constituent instructions serially.

Re: Execution units are often pipelined

#85

Earlier quoted context omitted.

The first link is very nice, worth of a submission of its own.

It was very good, I learned a lot. Actually more high-quality info than I can absorb in one sitting, but I bookmarked it to come back to. I'd love to see an updated version. The article talks about how out-of-order execution has a high power overhead and produces relatively small performance gains, but the M-series chips from Apple have deep OOO and low power consumption; I'm curious to learn what they did differentl…

> I'm curious to learn what they did differently.

Being 20 years later than the original version of that article.

Silicon process improvements since then have been wild.

Re: Execution units are often pipelined

#86
post #48
post #43

Pipelining is the direct reason behind 1996 Quake running 30 fps on Intel Pentium 133 but requiring 233MHz from Cyrix and 166MHz from AMD K6 to reach same result. 20 fps needed 75MHz Intel Pentium, 133MHz Cyrix and 100MHz AMD K5.

Specifically, Carmack exploited the fact that on the Pentium, integer instructions could run in parallel with floating-point division[0]. This goes to show that an optimization that usually gets you ~10% might get you 200% depending on what software you're running. And that no implementation detail is safe from an ambitious software engineer. [0] https://news.ycombinator.com/item?id=38249029

No, thats not it as explained in my reply to that TerrifiedMouse comment in 2023 :)

On x86 Integer instructions _never_ waited for floating point opcode to retire. You can check it yourself by reading FPU status register busy flag - if FPU was blocking you could never catch it in BUSY state and FWAIT would be useless :-)

Abrash exploited the fact Pentium was the first time x87 FPU instructions could run pipelined overlapping one another. All other x86 vendors FPUs waited for previous FPU instruction to retire.

https://www.agner.org/optimize/microarchitecture.pdf page 47

    While floating point instructions in general cannot be paired, many can be pipelined, i.e. one
    instruction can begin before the previous instruction has finished. Example:
     fadd st1,st0 ; Clock cycle 1-3
     fadd st2,st0 ; Clock cycle 2-4
     fadd st3,st0 ; Clock cycle 3-5
     fadd st4,st0 ; Clock cycle 4-6
    Obviously, two instructions cannot overlap if the second instruction needs the result of the
    first one. Since almost all floating point instructions involve the top of stack register, ST0, 
    there are seemingly not very many possibilities for making an instruction independent of the
    result of previous instructions. The solution to this problem is register renaming. The FXCH
    instruction does not in reality swap the contents of two registers; it only swaps their names.

Paradoxically often mentioned Texture Divide every 16 pixels overlaps just fine on all CPUs and doesnt explain performance discrepancies. Intel FDIV latency is 19 cycles compared to Cyrix 24, mere 20% yet you need almost double the MHz on Cyrix to match FPS numbers. Answer lies in rest of Quake heavily pipelined FPU code.

Re: Execution units are often pipelined

#87

Earlier quoted context omitted.

Nope. 1957 in a transistorized computer is far too late for the origin of pipelining. Pipelining had already been used in computers with vacuum tubes a few years before and it had also been used already a decade earlier in computers with electromechanical relays, i.e. IBM SSEC, which had a 3-stage pipeline for the execution of its instructions (IBM SSEC had a Harvard architecture, with distinct kinds of memories for…

The earliest "pipeline" example I can find is the portsmouth block mills [1] implemented by Marc Brunel[2]/Henry Maudslay[3] around 1802 [1] https://en.wikipedia.org/wiki/Portsmouth_Block_Mills [2] https://en.wikipedia.org/wiki/Marc_Isambard_Brunel [3] https://en.wikipedia.org/wiki/Henry_Maudslay

Wikipedia gives another much more ancient example of a "pipeline", the Venetian Arsenal, which had a progressive assembly line for ships, which had a throughput that could be greater than of one ship per day, and which has been built in the 12th century.

Re: Execution units are often pipelined

#88

Earlier quoted context omitted.

Nope. 1957 in a transistorized computer is far too late for the origin of pipelining. Pipelining had already been used in computers with vacuum tubes a few years before and it had also been used already a decade earlier in computers with electromechanical relays, i.e. IBM SSEC, which had a 3-stage pipeline for the execution of its instructions (IBM SSEC had a Harvard architecture, with distinct kinds of memories for…

> Pipelined execution and parallel execution are dual methods for accelerating an iterative process that transforms a stream of data. In the former the process is divided into subprocesses through which the stream of data passes in series, while in the latter the stream of data is divided into substreams that go in parallel through multiple instances of the process. With parallel do you mean superscalar execution i.e…

Parallel execution can exist at many different levels, e.g. at processor level you can have multiple processors executing in parallel some threads.

At instruction level, the execution of instructions is an iterative process, so like for any other iterative process parallelism or pipelining or both parallelism and pipelining may be used.

Most modern CPUs use both parallelism and pipelining in the execution of instructions. If you have e.g. a stream of multiply instructions, the CPU may have for example 2 multiply pipelines, where each multiply pipeline has 4 stages. The incoming multiply instruction stream is divided into 2 substreams, which are dispatched in parallel to the 2 multiply pipelines, so 2 multiply instructions are initiated in each clock cycle, which makes the example CPU superscalar. The multiply instructions are completed after 4 clock cycles, which is their latency, when they exit the pipeline. Thus, in the example CPU, 8 multiply instructions are simultaneously executed in each clock cycle, in various stages of the 2 parallel pipelines.

Whenever you have independent iterations, e.g. what looks like a "for" loop in the source program, where there are no dependencies between distinct executions of the loop body, the iterations can be executed in 4 different ways, sequentially, interleaved, pipelined or in parallel.

The last 3 ways can provide an acceleration in comparison with the sequential execution of the iteration. In the last 2 ways there is simultaneous execution of multiple iterations or multiple parts of an iteration.

For parallel execution of the iteration (like in OpenMP "parallel for" or like in NVIDIA CUDA), a thread must be created for each iteration execution and all threads are launched to be executed in parallel by multiple hardware execution units.

For pipelined execution of the iteration, the iteration body is partitioned in multiple consecutive blocks that use as input data the output data of the previous block (which may need adding additional storage variables, to separate output from input for each block), then a thread must be created for each such block that implements a part of the iteration, and then all such threads are launched to be executed in parallel by multiple hardware execution units.

These 2 ways of organizing simultaneous work, pipelined execution and parallel execution are applicable to any kind of iterative process. Two of the most important such iterative processes are the execution of a stream of instructions and the implementation of an array operation, which performs some operation on all the elements of an array. In both cases one can use a combination of pipelining and parallelism to achieve maximum speed. For these 2 cases, sometimes the terms "instruction-level parallelism and pipelining" and "data-level parallelism and pipelining" are used. The second of these 2 terms is misleading, because not data are executed in parallel or pipelined, but the iterations that process data are executed in parallel or pipelined. For any case where pipelining may be used, it is important to recognize which is the iterative process that can be implemented in this way. For unrelated tasks a.k.a. processes a.k.a. threads, only 3 ways of execution are available: sequential, interleaved and in parallel. The 4th way of execution, pipelined, is available only for iterations, where the difference between iterations and unrelated tasks is that each iteration executes the same program (i.e. the loop body, when the iteration is written with the sequential loop syntax).

Re: Execution units are often pipelined

#89

divisions, regardless of integer or floating point, are usually NOT pipelined though

I haven't seen any cpu with a fully pipelined division, but division units are at least partially pipelined in recent-ish cpus. They usually can start a new division well before the previous one has stopped executing.

ALUs in Recent Apple cpus can actually start a new division every other cycle (in addition to having an abnormally low latency), which is very impressive.

Re: Execution units are often pipelined

#90

Earlier quoted context omitted.

> Pipelined execution and parallel execution are dual methods for accelerating an iterative process that transforms a stream of data. In the former the process is divided into subprocesses through which the stream of data passes in series, while in the latter the stream of data is divided into substreams that go in parallel through multiple instances of the process. With parallel do you mean superscalar execution i.e…

Parallel execution can exist at many different levels, e.g. at processor level you can have multiple processors executing in parallel some threads. At instruction level, the execution of instructions is an iterative process, so like for any other iterative process parallelism or pipelining or both parallelism and pipelining may be used. Most modern CPUs use both parallelism and pipelining in the execution of instruct…

> both parallelism and pipelining

You are right, but this can be make more precise: pipelining is a specific form of parallelism. After all the different stages of the pipeline are executing in parallel.

Post reply on HN