125 lines
6.9 KiB
Markdown
125 lines
6.9 KiB
Markdown
------------------------ --------------------------------- --------------------
|
||
[Previous](18-05.html) [Table of Contents](index.html) [Next](19-02.html)
|
||
------------------------ --------------------------------- --------------------
|
||
|
||
Chapter 19\
|
||
Pentium: Not the Same Old Song {#Heading1}
|
||
-------------------------------
|
||
|
||
### Learning a Whole Different Set of Optimization Rules {#Heading2}
|
||
|
||
I can still remember the day I did my first 8088 programming. I had just
|
||
moved over from the distantly related Z80, so the 8088 wasn’t totally
|
||
alien, but it was nonetheless an incredibly exciting processor. The
|
||
8088’s instruction set was vastly more powerful and varied than the
|
||
Z80’s, and as someone who thrives on puzzles of all sorts, from
|
||
crosswords to Freecell to jigsaws to assembly language optimization, I
|
||
was delighted to find that the 8088 made the optimization universe an
|
||
order of magnitude more complicated—and correspondingly more
|
||
interesting.
|
||
|
||
Well, the years went by and the Z80 just died, and 8088 optimization got
|
||
ever more complex and intriguing as I discovered the hazards of the
|
||
8088’s cycle-eaters. By the time 1989 rolled around, I had written *Zen
|
||
of Assembly Language*, in which I described all that I had learned about
|
||
the 8088 and concluded that 8088 optimization was a black art of
|
||
infinite subtlety. Unfortunately, by that time the 286 was the standard,
|
||
with the 386 coming on strong, and if the 286 was less amenable to hand
|
||
optimization than the 8088 (and it surely was), then the 386 was
|
||
downright unfriendly. Sure, assembly optimization could buy some
|
||
performance on the 386, but only 20, 30, 40 percent or so—a far cry from
|
||
the 100 to 400 percent of the 8088. At the same time, compiler
|
||
technology was improving quickly, and the days of hand tuning seemed
|
||
numbered.
|
||
|
||
Happily, the 486 traveled to the beat of a different drum. The 486 had
|
||
some interesting internal pipeline hazards, as well as an internal cache
|
||
that made cycle counting more meaningful than ever before, and careful
|
||
code massaging sometimes yielded startling results. Nonetheless, the 486
|
||
was still too simple to mark a return to the golden age of optimization.
|
||
|
||
### The Return of Optimization as Art {#Heading3}
|
||
|
||
Then the Pentium came around, and filled our code with optimization
|
||
hazards, and life was good again. The Pentium has two execution
|
||
pipelines and enough rules and exceptions to those rules to bring joy to
|
||
the heart of the hardest-core assembly junkie. For a change, Intel
|
||
documented most of the Pentium optimization rules and spread the word
|
||
about them, so we don’t have to go through as much spelunking of the
|
||
Pentium as with its predecessors. They’ve done this, I suspect, largely
|
||
because more than any previous x86 processor, the Pentium’s performance
|
||
is highly dependent on properly optimized code.
|
||
|
||
In the worst case, where the second execution pipe is dormant most of
|
||
the time, the Pentium won’t perform all that much better than a 486 at
|
||
the same clock speed. In the best case, where the second pipe is heavily
|
||
used and the Pentium’s other advantages (such as branch prediction,
|
||
write-back cache, 64-bit full speed external bus, and dual 8K caches)
|
||
can kick in, the Pentium can be more than twice as fast as a 486. In a
|
||
critical inner loop, hand optimization can double or even triple
|
||
performance over 486-optimized code—and that’s on top of the sorts of
|
||
algorithmic and design optimizations that are routinely performed on any
|
||
processor. Good compilers can make a big difference on the Pentium, too,
|
||
but there are some gotchas there, to which I’ll return later.
|
||
|
||
It’s been a long time coming, but hard-core, big-payoff assembly
|
||
language optimization is back in style, and for the rest of this book
|
||
I’ll be delving into the Byzantine wonders of the Pentium. In this
|
||
chapter, I’ll do a quick overview, then cover a variety of smaller
|
||
Pentium optimization topics. In the next chapter, I’ll tackle the
|
||
900-pound gorilla of Pentium optimization: superscalar (dual execution
|
||
pipe) programming. Trust me, this’ll be fun.
|
||
|
||
Listen, do you want to know a secret? This lead-in has been brought to
|
||
you with the help of “classic rock”—another way of saying “music Baby
|
||
Boomers listened to back when they cared more about music than 401Ks and
|
||
regular flossing.” There are so many of us Boomers that our music, even
|
||
the worst of it, will never go away. When we’re 90 years old, propped up
|
||
in our Kraftmatic adjustable beds and surfing the 5,000-channel
|
||
information superhighway from one infomercial to the next, the sound
|
||
system in the retirement community will be piping in a Muzak version of
|
||
“Louie, Louie,” while on the holovid Country Joe McDonald and the Fish
|
||
pitch Preparation H. I can hardly wait.
|
||
|
||
Gimme a “P”....
|
||
|
||
### The Pentium: An Overview {#Heading4}
|
||
|
||
Architecturally, the Pentium is vastly different in many ways from the
|
||
486, but most of those differences are transparent to programmers. After
|
||
all, the whole idea behind the Pentium is that it runs the same code as
|
||
previous x86 processors, but faster; otherwise, Intel could have made a
|
||
faster, cheaper RISC processor. Still, knowledge of the Pentium’s
|
||
architecture is useful for understanding exactly how code will perform,
|
||
and a few of the architectural differences are most decidedly *not*
|
||
transparent to performance programmers.
|
||
|
||
The Pentium is essentially one full 486 execution unit (EU), plus a
|
||
second stripped-down 486 EU, on a single chip. The first EU is referred
|
||
to as the U execution pipe, or *U-pipe;* the second, more limited one is
|
||
called the *V-pipe*. The two pipes are capable of executing instructions
|
||
simultaneously, have separate write buffers, and can even access the
|
||
data cache simultaneously (although with certain limitations that I’ll
|
||
discuss in the next chapter), so on the Pentium it is possible to
|
||
execute two instructions, even instructions that access memory, in a
|
||
single clock. The cycle times for instruction execution in a given pipe
|
||
(both pipes process instructions at the same speed) are comparable to
|
||
those for the 486, although some instructions—notably **MUL**, the
|
||
repeated string instructions, and some of the shifts and rotates—have
|
||
gotten faster.
|
||
|
||
My first thought upon hearing of the Pentium’s dual pipes was to wonder
|
||
how often the prefetch queue stalls for lack of instruction bytes, given
|
||
that the demand for instruction bytes can be twice that of the 486. The
|
||
answer is: rarely indeed, and then only because the code is not in the
|
||
internal cache. The 486 has a single 8K cache that stores both code and
|
||
data, and prefetching can stall if data fetching doesn’t allow time for
|
||
prefetching to occur (although this rarely happens in practice).
|
||
|
||
------------------------ --------------------------------- --------------------
|
||
[Previous](18-05.html) [Table of Contents](index.html) [Next](19-02.html)
|
||
------------------------ --------------------------------- --------------------
|
||
|
||
* * * * *
|
||
|
||
Graphics Programming Black Book © 2001 Michael Abrash
|