Normal quotes
This commit is contained in:
parent
5e10794a24
commit
18011c595a
352 changed files with 6040 additions and 6040 deletions
50
19-04.md
50
19-04.md
|
|
@ -15,30 +15,30 @@ or V-pipe, respectively)—1 or 2 cycles more than a branch and 3 or 4
|
|||
cycles more than a fall-through on the 486.
|
||||
|
||||
------------------- -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
 *Branch prediction is unprecedented in the x86, and fundamentally alters the nature of pedal-to-the-metal optimization, for the simple reason that it renders unrolled loops largely obsolete. Rare indeed is the loop that can’t afford to spare even 1 or 0 (yes, zero!) cycles per iteration for loop counting, and that’s how low the cost can go for maintaining a loop on the Pentium.*
|
||||
 *Branch prediction is unprecedented in the x86, and fundamentally alters the nature of pedal-to-the-metal optimization, for the simple reason that it renders unrolled loops largely obsolete. Rare indeed is the loop that can't afford to spare even 1 or 0 (yes, zero!) cycles per iteration for loop counting, and that's how low the cost can go for maintaining a loop on the Pentium.*
|
||||
------------------- -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Also, unrolled loops are bigger than normal loops, so there are extra
|
||||
(and expensive) cache misses the first time through the loop if the
|
||||
entire loop isn’t already in the cache; then, too, an unrolled loop will
|
||||
entire loop isn't already in the cache; then, too, an unrolled loop will
|
||||
shoulder other code out of the internal and external caches. If in a
|
||||
critical loop you absolutely need the time taken by the loop control
|
||||
instructions, or if you need an extra register that can be freed by
|
||||
unrolling a loop, then by all means unroll the loop. Don’t expect the
|
||||
unrolling a loop, then by all means unroll the loop. Don't expect the
|
||||
sort of speed-up you get from this on the 486 or especially the 386,
|
||||
though, and watch out for the cache effects.
|
||||
|
||||
You may well wonder exactly *when* the Pentium correctly predicts
|
||||
branching. Alas, this is one area that Intel has declined to document,
|
||||
beyond saying that you should endeavor to fall through branches when you
|
||||
have a choice. That’s good advice on every other x86 processor, anyway,
|
||||
so it’s well worth following. Also, it’s a pretty safe bet that in a
|
||||
have a choice. That's good advice on every other x86 processor, anyway,
|
||||
so it's well worth following. Also, it's a pretty safe bet that in a
|
||||
tight loop, the Pentium will start guessing the right branch direction
|
||||
at the bottom of the loop pretty quickly, so you can treat loop branches
|
||||
as one-cycle instructions.
|
||||
|
||||
It’s an equally safe bet that it’s a bad move to have in a loop a
|
||||
conditional branch that goes both ways on a random basis; it’s hard to
|
||||
It's an equally safe bet that it's a bad move to have in a loop a
|
||||
conditional branch that goes both ways on a random basis; it's hard to
|
||||
see how the Pentium could consistently predict such branches correctly,
|
||||
and mispredicted branches are more expensive than they might appear to
|
||||
be. Not only does a mispredicted branch take 4 or 5 cycles, but the
|
||||
|
|
@ -47,11 +47,11 @@ time—3 times as many as the 486 can execute during its branch time—so
|
|||
correct branch prediction (or eliminating branch instructions, if
|
||||
possible) is very important in inner loops. Note that on the 486 you can
|
||||
count on a branch to take 1 cycle when it falls through, but on the
|
||||
Pentium you can’t be sure whether it will take 1 or either 4 or 5 cycles
|
||||
Pentium you can't be sure whether it will take 1 or either 4 or 5 cycles
|
||||
on any given iteration.
|
||||
|
||||
------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
 *As things currently stand, branch prediction is an annoyance for assembly language optimization because it’s impossible to be certain exactly how code will perform until you measure it, and even then it’s difficult to be sure exactly where the cycles went. All I can say is try to fall through branches if possible, and try to be consistent in your branching if not.*
|
||||
 *As things currently stand, branch prediction is an annoyance for assembly language optimization because it's impossible to be certain exactly how code will perform until you measure it, and even then it's difficult to be sure exactly where the cycles went. All I can say is try to fall through branches if possible, and try to be consistent in your branching if not.*
|
||||
------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
### Miscellaneous Pentium Topics {#Heading9}
|
||||
|
|
@ -59,24 +59,24 @@ on any given iteration.
|
|||
The Pentium has all the instructions of the 486, plus a few new ones.
|
||||
One much-needed instruction that has finally made it into the
|
||||
instruction set is **CPUID**, which allows your code to determine what
|
||||
processor it’s running on. **CPUID** is 15 years late, but at least it’s
|
||||
processor it's running on. **CPUID** is 15 years late, but at least it's
|
||||
finally here. Another new instruction is **CMPXCHG8B**, which does a
|
||||
compare and conditional exchange on a qword. **CMPXCHG8B** doesn’t seem
|
||||
to me to be a particularly useful instruction, but I’m sure Intel
|
||||
wouldn’t have added it without a reason; if you know of a use for it,
|
||||
compare and conditional exchange on a qword. **CMPXCHG8B** doesn't seem
|
||||
to me to be a particularly useful instruction, but I'm sure Intel
|
||||
wouldn't have added it without a reason; if you know of a use for it,
|
||||
please pass it along to me.
|
||||
|
||||
#### 486 versus Pentium Optimization {#Heading10}
|
||||
|
||||
Many Pentium optimizations help, or at least don’t hurt, on the 486.
|
||||
Many Pentium optimizations help, or at least don't hurt, on the 486.
|
||||
Many, but not all—and many *do* hurt on the 386. As I discuss various
|
||||
Pentium optimizations, I will attempt to note the effects on the 486 as
|
||||
well, but doing this in complete detail would double the sizes of these
|
||||
discussions and make them hard to follow. In general, I’d recommend
|
||||
discussions and make them hard to follow. In general, I'd recommend
|
||||
reserving Pentium optimization for your most critical code, and even
|
||||
there, it’s a good idea to have at least two code paths, one for the 386
|
||||
and one for the 486/Pentium. It’s also a good idea to time your code on
|
||||
a 486 before and after Pentium-optimizing it, to make sure you haven’t
|
||||
there, it's a good idea to have at least two code paths, one for the 386
|
||||
and one for the 486/Pentium. It's also a good idea to time your code on
|
||||
a 486 before and after Pentium-optimizing it, to make sure you haven't
|
||||
hurt performance on what will be, after all, by far the most important
|
||||
processor over the next couple of years.
|
||||
|
||||
|
|
@ -88,12 +88,12 @@ on the fastest hardware, Pentium optimization can make your code
|
|||
|
||||
#### Going Superscalar {#Heading11}
|
||||
|
||||
In the next chapter, we’ll look into the single biggest element of
|
||||
Pentium performance, cranking up the Pentium’s second execution pipe.
|
||||
In the next chapter, we'll look into the single biggest element of
|
||||
Pentium performance, cranking up the Pentium's second execution pipe.
|
||||
This is the area in which compiler technology is most touted for the
|
||||
Pentium, the two thoughts apparently being that (1) most existing code
|
||||
is in C, so recompiling to use the second pipe better is an automatic
|
||||
win, and (2) it’s so complicated to optimize Pentium code that only a
|
||||
win, and (2) it's so complicated to optimize Pentium code that only a
|
||||
compiler can do it well. The first point is a reasonable one, but it
|
||||
does suffer from one flaw for large programs, in that Pentium-optimized
|
||||
code is larger than 486- or 386-optimized code, for reasons that will
|
||||
|
|
@ -106,15 +106,15 @@ but can be less beneficial than expected or even slower in some cases.
|
|||
What makes more sense is enabling Pentium optimization *only* for key
|
||||
code. Better yet, you could hand-tune the most important code—and yes,
|
||||
you can absolutely do a better job with a small, critical loop than any
|
||||
PC compiler I’ve ever seen, or expect to see. Sure, you keep hearing how
|
||||
PC compiler I've ever seen, or expect to see. Sure, you keep hearing how
|
||||
great each new compiler generation is, and compilers certainly have
|
||||
improved; but they play by the same rules we do, and we’re more flexible
|
||||
and know more about what we’re doing—and now we have the wonderfully
|
||||
improved; but they play by the same rules we do, and we're more flexible
|
||||
and know more about what we're doing—and now we have the wonderfully
|
||||
complex and powerful Pentium upon which to loose our carbon-based
|
||||
optimizers.
|
||||
|
||||
A compiler that generates better code than a good assembly programmer?
|
||||
That’ll be the day.
|
||||
That'll be the day.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](19-03.html) [Table of Contents](index.html) [Next](20-01.html)
|
||||
|
|
|
|||
Loading…
Reference in a new issue