Normal quotes
This commit is contained in:
parent
5e10794a24
commit
18011c595a
352 changed files with 6040 additions and 6040 deletions
30
20-03.md
30
20-03.md
|
|
@ -21,12 +21,12 @@ execute its instruction, as shown in Figure 20.4. Out of the theoretical
|
|||
6 cycles of work that can be done during this time, we actually get only
|
||||
4 cycles of work, or 67 percent utilization. Even though these
|
||||
instructions pair, then, this sequence fails to make maximum use of the
|
||||
Pentium’s horsepower.
|
||||
Pentium's horsepower.
|
||||
|
||||
The key here is that when two instructions pair, both execution units
|
||||
are tied up until both instructions have finished (which means at least
|
||||
for the amount of time required for the longer of the two to execute,
|
||||
plus possibly some extra cycles for pairable instructions that can’t
|
||||
plus possibly some extra cycles for pairable instructions that can't
|
||||
fully overlap, as described below). The logical conclusion would seem to
|
||||
be that we should strive to pair instructions of the same lengths, but
|
||||
that is often not correct.
|
||||
|
|
@ -38,35 +38,35 @@ that is often not correct.
|
|||
\
|
||||
**Figure 20.4** *Lockstep execution and idle time in the V-pipe.*
|
||||
|
||||
Here’s why. The Pentium is fully capable of handling instructions that
|
||||
Here's why. The Pentium is fully capable of handling instructions that
|
||||
use memory operands in either pipe, or, if necessary, in both pipes at
|
||||
once. Each pipe has its own write FIFO, which buffers the last few
|
||||
writes and takes care of writing the data out while the Pentium
|
||||
continues processing. The Pentium also has a write-back internal data
|
||||
cache, so data that is frequently changed doesn’t have to be written to
|
||||
cache, so data that is frequently changed doesn't have to be written to
|
||||
external memory (which is much slower than the cache) very often. This
|
||||
combination means that unless you write large blocks of data at a high
|
||||
speed, the Pentium should be able to keep up with both pipes’ memory
|
||||
speed, the Pentium should be able to keep up with both pipes' memory
|
||||
writes without stalling execution.
|
||||
|
||||
The Pentium is also designed to satisfy both pipes’ needs for reading
|
||||
The Pentium is also designed to satisfy both pipes' needs for reading
|
||||
memory operands with little waiting. The data cache is constructed so
|
||||
that both pipes can read from the cache *on the same cycle*. This feat
|
||||
is accomplished by organizing the data cache as eight-banked memory, as
|
||||
shown in Figure 20.5, with each 32-byte cache line consisting of 8
|
||||
dwords, 1 in each bank. The banks are independent of one another, so as
|
||||
long as the desired data is in the cache and the U- and V-pipes don’t
|
||||
long as the desired data is in the cache and the U- and V-pipes don't
|
||||
try to read from the same bank on the same cycle, both pipes can read
|
||||
memory operands on the same cycle. (If there is a cache bank collision,
|
||||
the V-pipe instruction stalls for one cycle.)
|
||||
|
||||
Normally, you won’t pay close attention to which of the eight dword
|
||||
banks your paired memory accesses fall in—that’s just too much work—but
|
||||
Normally, you won't pay close attention to which of the eight dword
|
||||
banks your paired memory accesses fall in—that's just too much work—but
|
||||
you might want to watch out for simultaneously read addresses that have
|
||||
the same values for address
|
||||
|
||||
\
|
||||
**Figure 20.5** *The Pentium’s eight bank data cache.*
|
||||
**Figure 20.5** *The Pentium's eight bank data cache.*
|
||||
|
||||
bits 2, 3, and 4 (fall in the same bank) in tight loops, and you should
|
||||
also avoid sequences like
|
||||
|
|
@ -89,15 +89,15 @@ instructions; by contrast, the obvious way of loading BX
|
|||
|
||||
mov bx,[esi]
|
||||
|
||||
takes 1.5 to two cycles because the size prefix can’t pair, as described
|
||||
takes 1.5 to two cycles because the size prefix can't pair, as described
|
||||
below. This is yet another example of how different Pentium optimization
|
||||
can be from everything we’ve learned about its predecessors.
|
||||
can be from everything we've learned about its predecessors.
|
||||
|
||||
The problem with pairing non-single-cycle instructions arises when a
|
||||
pipe executes an instruction other than **MOV** that has an explicit
|
||||
memory operand. (I’ll call these *complex memory instructions*. They’re
|
||||
memory operand. (I'll call these *complex memory instructions*. They're
|
||||
the only pairable instructions, other than branches, that take more than
|
||||
one cycle.) We’ve already seen that, because instructions go through the
|
||||
one cycle.) We've already seen that, because instructions go through the
|
||||
pipes in lockstep, if one pipe executes a complex memory instruction
|
||||
such as **ADD EAX,[EBX]** while the other pipe executes a single-cycle
|
||||
instruction, the pipe with the faster instruction will sit idle for part
|
||||
|
|
@ -105,7 +105,7 @@ of the time, wasting cycles. You might think that if both pipes execute
|
|||
complex instructions of the same length, then neither would lie idle,
|
||||
but that turns out to not always be the case. Two two-cycle instructions
|
||||
(instructions with register destination operands) can indeed pair and
|
||||
execute in two cycles, so it’s okay to pair two instructions such as
|
||||
execute in two cycles, so it's okay to pair two instructions such as
|
||||
these:
|
||||
|
||||
add esi,[SourceSkip] ;U-pipe cycles 1 and 2
|
||||
|
|
|
|||
Loading…
Reference in a new issue