Deduped images
This commit is contained in:
parent
4eef8b2919
commit
9e52de9586
233 changed files with 128 additions and 128 deletions
|
|
@ -50,16 +50,16 @@
|
|||
<P>68 degrees is warm for an uninsulated third floor in Buffalo in the dead of winter. Damn warm. It is not, however, particularly warm for a sauna. Eventually someone acknowledges the obvious and allows that it might have been a stupid idea after all, and everyone agrees, and they shut off the heater and leave, each no doubt offering silent thanks that they had gotten out of this without any incidents requiring major surgery.</P>
|
||||
<P>And so we see that the best idea in the world can fail for lack of either proper design or adequate horsepower. The primary cause of the Great Buffalo Sauna Fiasco was a lack of horsepower; the gas heater was flat-out undersized. This is analogous to trying to write programs that incorporate features like bitmapped text and searching of multisegment buffers without using high-performance assembly language. Any PC language can perform just about any function you can think of—eventually. That heater would eventually have heated the room to 110 degrees, too—along about the first of June or so.</P>
|
||||
<P>The Great Buffalo Sauna Fiasco also suffered from fundamental design flaws. A more powerful heater would indeed have made the room hotter—and might well have burned the house down in the process. Likewise, proper algorithm selection and good design are fundamental to performance. The extra horsepower a superb assembly language implementation gives a program is worth bothering with only in the context of a good design.</P>
|
||||
<TABLE WIDTH="100%"><TD ALIGN="LEFT" VALIGN="TOP" WIDTH="5%"><IMG SRC="images/07-01i.jpg"><TD ALIGN="LEFT" VALIGN="TOP" WIDTH="95%"><SMALL><I>Assembly language optimization is a small but crucial corner of the PC programming world. Use it sparingly and only within the framework of a good design—but ignore it and you may find various portions of your anatomy out in the cold.</I></SMALL>
|
||||
<TABLE WIDTH="100%"><TD ALIGN="LEFT" VALIGN="TOP" WIDTH="5%"><IMG SRC="images/i.jpg"><TD ALIGN="LEFT" VALIGN="TOP" WIDTH="95%"><SMALL><I>Assembly language optimization is a small but crucial corner of the PC programming world. Use it sparingly and only within the framework of a good design—but ignore it and you may find various portions of your anatomy out in the cold.</I></SMALL>
|
||||
</TABLE>
|
||||
<P>So, drawing fortitude from the knowledge that our quest is a pure and worthy one, let’s resume our exploration of assembly language instructions with hidden talents and instructions with well-known talents that are less than they appear to be. In the process, we’ll come to see that there is another, very important optimization level between the algorithm/design level and the cycle-counting/individual instruction level. I’ll call this middle level <I>local optimization;</I> it involves focusing on optimizing sequences of instructions rather than individual instructions, all with an eye to implementing designs as efficiently as possible given the capabilities of the x86 family instruction set.</P>
|
||||
<P>And yes, in case you’re wondering, the above story is indeed true. Was I there? Let me put it this way: If I were, I’d never admit it!</P>
|
||||
<H4 ALIGN="LEFT"><A NAME="Heading3"></A><FONT COLOR="#000077">When LOOP Is a Bad Idea</FONT></H4>
|
||||
<P>Let’s examine first an instruction that is less than it appears to be: <B>LOOP</B>. There’s no mystery about what <B>LOOP</B> does; it decrements CX and branches if CX doesn’t decrement to zero. It’s so beautifully suited to the task of counting down loops that any experienced x86 programmer instinctively stuffs the loop count in CX and reaches for <B>LOOP</B> when setting up a loop. That’s fine—<B>LOOP</B> does, of course, work as advertised—but there is one problem:</P>
|
||||
<TABLE WIDTH="100%"><TD ALIGN="LEFT" VALIGN="TOP" WIDTH="5%"><IMG SRC="images/07-02i.jpg"><TD ALIGN="LEFT" VALIGN="TOP" WIDTH="95%"><SMALL><I>On half of the processors in the x86 family, <B>LOOP</B> is slower than <B>DEC CX</B> followed by <B>JNZ</B>. (Granted, <B>DEC CX/JNZ</B> isn’t precisely equivalent to <B>LOOP,</B> because <B>DEC</B> alters the flags and LOOP doesn’t, but in most situations they’re comparable.)</I></SMALL>
|
||||
<TABLE WIDTH="100%"><TD ALIGN="LEFT" VALIGN="TOP" WIDTH="5%"><IMG SRC="images/i.jpg"><TD ALIGN="LEFT" VALIGN="TOP" WIDTH="95%"><SMALL><I>On half of the processors in the x86 family, <B>LOOP</B> is slower than <B>DEC CX</B> followed by <B>JNZ</B>. (Granted, <B>DEC CX/JNZ</B> isn’t precisely equivalent to <B>LOOP,</B> because <B>DEC</B> alters the flags and LOOP doesn’t, but in most situations they’re comparable.)</I></SMALL>
|
||||
</TABLE>
|
||||
<P>How can this be? Don’t ask me, ask Intel. On the 8088 and 80286, <B>LOOP</B> is indeed faster than <B>DEC CX/JNZ</B> by a cycle, and <B>LOOP</B> is generally a little faster still because it’s a byte shorter and so can be fetched faster. On the 386, however, things change; <B>LOOP</B> is two cycles <I>slower</I> than <B>DEC/JNZ,</B> and the fetch time for one extra byte on even an uncached 386 generally isn’t significant. (Remember that the 386 fetches four instruction bytes at a pop.) <B>LOOP</B> is three cycles slower than <B>DEC/JNZ</B> on the 486, and the 486 executes instructions in so few cycles that those three cycles mean that <B>DEC/JNZ</B> is nearly <I>twice</I> as fast as <B>LOOP</B>. Then, too, unlike <B>LOOP, DEC</B> doesn’t require that <B>CX</B> be used, so the <B>DEC/JNZ</B> solution is both faster and more flexible on the 386 and 486, and on the Pentium as well. (By the way, all this is not just theory; I’ve timed the relative performances of <B>LOOP</B> and <B>DEC CX/JNZ</B> on a cached 386, and LOOP really is slower.)</P>
|
||||
<TABLE WIDTH="100%"><TD ALIGN="LEFT" VALIGN="TOP" WIDTH="5%"><IMG SRC="images/07-03i.jpg"><TD ALIGN="LEFT" VALIGN="TOP" WIDTH="95%"><SMALL><I>Things are stranger still for <B>LOOP</B>’s relative <B>JCXZ,</B> which branches if and only if CX is zero. <B>JCXZ</B> is faster than <B>AND CX,CX/JZ</B> on the 8088 and 80286, and equivalent on the 80386—but is about twice as slow on the 486!</I></SMALL>
|
||||
<TABLE WIDTH="100%"><TD ALIGN="LEFT" VALIGN="TOP" WIDTH="5%"><IMG SRC="images/i.jpg"><TD ALIGN="LEFT" VALIGN="TOP" WIDTH="95%"><SMALL><I>Things are stranger still for <B>LOOP</B>’s relative <B>JCXZ,</B> which branches if and only if CX is zero. <B>JCXZ</B> is faster than <B>AND CX,CX/JZ</B> on the 8088 and 80286, and equivalent on the 80386—but is about twice as slow on the 486!</I></SMALL>
|
||||
</TABLE>
|
||||
<P><BR></P>
|
||||
<CENTER>
|
||||
|
|
|
|||
Loading…
Reference in a new issue