Normal quotes

This commit is contained in:
James Gregory 2013-12-30 18:34:31 +11:00
commit 18011c595a
352 changed files with 6040 additions and 6040 deletions

View file

@ -4,44 +4,44 @@
FDIV is a painfully slow instruction, taking 39 cycles at full precision
and 33 cycles at double precision, which is the default precision for
Visual C++ 2.0. While FDIV executes, the FPU is occupied, and can’t
Visual C++ 2.0. While FDIV executes, the FPU is occupied, and can't
process subsequent FP instructions until FDIV finishes. However, during
the cycles while FDIV is executing (with the exception of the one cycle
during which FDIV starts), the integer unit can simultaneously execute
instructions other than IMUL. (IMUL uses the FPU, and can only overlap
with FDIV for a few cycles.) Since the integer unit can execute two
instructions per cycle, this means it’s possible to have three
instructions per cycle, this means it's possible to have three
instructions, an FDIV and two integer instructions, executing at the
same time. That’s exactly what happens, for example, during the second
same time. That's exactly what happens, for example, during the second
cycle of this code:
FDIV ST(0),ST(1)
ADD EAX,ECX
INC EDX
There’s an important limitation, though; if the instruction stream
There's an important limitation, though; if the instruction stream
following the FDIV reaches a FP instruction (or an IMUL), then that
instruction and all subsequent instructions, both integer and FP, must
wait to execute until FDIV has finished.
When a FADD, FSUB, or FMUL instruction is executed, it is 3 cycles
before the result can be used by another instruction. (There’s an
before the result can be used by another instruction. (There's an
exception: If the instruction that attempts to use the result is an FST
to memory, there’s an extra cycle lost, so it’s 4 cycles from the start
to memory, there's an extra cycle lost, so it's 4 cycles from the start
of an arithmetic instruction until an FST of that value can begin, so
FMUL ST(0),ST(1)
FST [temp]
takes 6 cycles in all.) Again, it’s possible to execute integer-unit
takes 6 cycles in all.) Again, it's possible to execute integer-unit
instructions during the 2 (or 3, for FST) cycles after one of these FP
instructions starts. There’s a more exciting possibility here, though:
instructions starts. There's a more exciting possibility here, though:
Given properly structured code, the FPU is capable of averaging 1 cycle
per FADD, FSUB, or FMUL. The secret is pipelining.
#### Pipelining, Latency, and Throughput {#Heading5}
The Pentium’s FPU is the first pipelined x86 FPU. *Pipelining* means
The Pentium's FPU is the first pipelined x86 FPU. *Pipelining* means
that the FPU is capable of starting an instruction every cycle, and can
simultaneously handle several instructions in various stages of
completion. Only certain x86 FP instructions allow another instruction
@ -57,11 +57,11 @@ is not an issue.) Thus, in the code sequence
FADD~1~ can start on cycle N, FSUB can start on cycle N+1, FADD~2~ can
start on cycle N+2, and FMUL can start on cycle N+3. At the start of
cycle N+3, the result of FADD~1~ is available in the destination
operand, because it’s been 3 cycles since the instruction started; FSUB
operand, because it's been 3 cycles since the instruction started; FSUB
is starting the final cycle of calculation; FADD~2~ is starting its
second cycle, with one cycle yet to go after this; and FMUL is about to
be issued. Each of the instructions takes 3 cycles to produce a result
from the time it starts, but because they’re simultaneously processed at
from the time it starts, but because they're simultaneously processed at
different pipeline stages, one instruction is issued and one instruction
completes every cycle. Thus, the latency of these instructions—that is,
the time until the result is available—is 3 cycles, but the
@ -72,14 +72,14 @@ every 2 cycles, so between these two instructions
FMUL ST(1),ST(0)
FMUL ST(2),ST(0)
there’s a 1-cycle stall, and the following three instructions execute
there's a 1-cycle stall, and the following three instructions execute
just as fast as the above pair:
FMUL ST(1),ST(0)
FLD ST(4)
FMUL ST(0),ST(1)
There’s a caveat here, though: A FP instruction can’t be issued until
There's a caveat here, though: A FP instruction can't be issued until
its operands are available. The FPU can reach a throughput of 1 cycle
per instruction on this code
@ -93,7 +93,7 @@ Consider, however
FADD ST(0),ST(2)
FSUB ST(0),ST(1)
where the ST(0) operand to FSUB is calculated by FADD. Here, FSUB can’t
where the ST(0) operand to FSUB is calculated by FADD. Here, FSUB can't
start until FADD has completed, so there are 2 stall cycles between the
two instructions. When dependencies like this occur, the FPU runs at
latency rather than throughput speeds, and performance can drop by as
@ -110,12 +110,12 @@ ST(0), and FST can only store from ST(0). How, then, can we keep three
independent instructions going?
The easy answer would be for Intel to change the FP registers from a
stack to a set of independent registers. Since they couldn’t do that,
stack to a set of independent registers. Since they couldn't do that,
thanks to compatibility issues, they did the next best thing: They made
the FXCH instruction, which swaps ST(0) and any other FP register,
virtually free. In general, if FXCH is both preceded and followed by FP
instructions, then it takes *no* cycles to execute. (Application Note
500, “Optimizations for Intel’s 32-bit Processors,” February 1994,
500, "Optimizations for Intel's 32-bit Processors," February 1994,
available from [http://www.intel.com](http://www.intel.com), describes
all .the conditions under which FXCH is free.) This allows you to move
the target of a pending operation from ST(0) to another register, at the
@ -138,7 +138,7 @@ multiplications, without incurring any stalls, as shown in Listing 63.1.
### The Dot Product {#Heading7}
Now we’re ready to look at fast FP for common 3-D operations; we’ll
Now we're ready to look at fast FP for common 3-D operations; we'll
start by looking at how to speed up the dot product. As discussed in
Chapter 30, the dot product is heavily used in 3-D to calculate cosines
and to project points along vectors. The dot product is calculated as d
@ -152,9 +152,9 @@ by doing all three FMULs first, then using FXCH to set the third FXCH
aside to complete while the results of the first two FMULs, which have
completed, are added. Listing 43.3 still loses 50 percent to stalls, but
unless some other code is available to be interleaved with the dot
product code, that’s all we can do to speed things up. Fortunately, dot
products are often used in contexts where there’s plenty of interleaving
potential, as we’ll see when we discuss transformation.
product code, that's all we can do to speed things up. Fortunately, dot
products are often used in contexts where there's plenty of interleaving
potential, as we'll see when we discuss transformation.
------------------------ --------------------------------- --------------------
[Previous](63-01.html) [Table of Contents](index.html) [Next](63-03.html)