Normal quotes
This commit is contained in:
parent
5e10794a24
commit
18011c595a
352 changed files with 6040 additions and 6040 deletions
20
16-06.md
20
16-06.md
|
|
@ -5,17 +5,17 @@
|
|||
### Levels of Optimization {#Heading9}
|
||||
|
||||
Three levels of optimization were evident in the word-counting entries I
|
||||
received in response to my challenge. I’d briefly describe them as
|
||||
“fine-tuning,” “new perspective,” and “table-driven state machine.” The
|
||||
received in response to my challenge. I'd briefly describe them as
|
||||
"fine-tuning," "new perspective," and "table-driven state machine." The
|
||||
latter categories produce faster code, but, by the same token, they are
|
||||
harder to design, harder to implement, and more difficult to understand,
|
||||
so they’re suitable for only the most demanding applications. (Heck, I
|
||||
don’t even guarantee that David Stafford’s entry works perfectly,
|
||||
so they're suitable for only the most demanding applications. (Heck, I
|
||||
don't even guarantee that David Stafford's entry works perfectly,
|
||||
although, knowing him, it probably does; the more complex and cryptic
|
||||
the code, the greater the chance for obscure bugs.)
|
||||
|
||||
------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
 *Remember, optimize only when needed, and stop when further optimization will not be noticed. Optimization that’s not perceptible to the user is like buying Telly Savalas a comb; it’s not going to do any harm, but it’s nonetheless a waste of time.*
|
||||
 *Remember, optimize only when needed, and stop when further optimization will not be noticed. Optimization that's not perceptible to the user is like buying Telly Savalas a comb; it's not going to do any harm, but it's nonetheless a waste of time.*
|
||||
------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#### Optimization Level 1: Good Code {#Heading10}
|
||||
|
|
@ -28,7 +28,7 @@ but that framework is implemented more efficiently.
|
|||
One obvious level 1 optimization is using a **word** rather than
|
||||
**dword** counter. **ScanBuffer** can never be called upon to handle
|
||||
more than 64K bytes at a time, so no more than 32K words can ever be
|
||||
found. Given that, it’s a logical step to use **INC** rather than
|
||||
found. Given that, it's a logical step to use **INC** rather than
|
||||
**ADD/ADC** to keep count, adding the tally into the full 32-bit count
|
||||
only upon exiting the function. Another useful optimization is aligning
|
||||
loop tops and other branch destinations to **word** , or better yet
|
||||
|
|
@ -44,7 +44,7 @@ the point of unrolling a loop is to reduce the number of times you have
|
|||
to check for the end of the buffer! The trick to this is to set CX to
|
||||
the number of repetitions of the *unrolled* loop and count down only
|
||||
once each time through the unrolled loop. In order to handle repetition
|
||||
counts that aren’t exact multiples of the unrolling factor, you must
|
||||
counts that aren't exact multiples of the unrolling factor, you must
|
||||
enter the loop by branching into the middle of it to perform whatever
|
||||
fraction of the number of unrolled repetitions is required to make the
|
||||
whole thing come out right. Listing 16.5 (QSCAN3.ASM) illustrates this
|
||||
|
|
@ -63,7 +63,7 @@ eliminate it entirely. The most straightforward way to reduce such
|
|||
branching is to employ two loops. One loop is used to look for the end
|
||||
of a word when the last byte was a non-separator, and one loop is used
|
||||
to look for the start of a word when the last byte was a separator. This
|
||||
way, it’s no longer necessary to maintain a flag to indicate the state
|
||||
way, it's no longer necessary to maintain a flag to indicate the state
|
||||
of the last byte; that state is implied by whichever loop is currently
|
||||
executing. This considerably simplifies and streamlines the inner loop
|
||||
code.
|
||||
|
|
@ -71,11 +71,11 @@ code.
|
|||
Listing 16.6, contributed by Willem Clements, of Granada, Spain,
|
||||
illustrates a variety of level 1 optimizations: the two-loop approach,
|
||||
the use of a 16- rather than 32-bit counter, and the use of **LODSW** .
|
||||
Together, these optimizations made Willem’s code nearly twice as fast as
|
||||
Together, these optimizations made Willem's code nearly twice as fast as
|
||||
mine in Listing 16.4. A few details could stand improvement; for
|
||||
example, **AND AX,AX** is a shorter way to test for zero than **CMP
|
||||
AX,0** , and **ALIGN 2** could be used. Nonetheless, this is good code,
|
||||
and it’s also fairly compact and reasonably easy to understand. In
|
||||
and it's also fairly compact and reasonably easy to understand. In
|
||||
short, this is an excellent example of how an hour or so of
|
||||
hand-optimization might accomplish significantly improved performance at
|
||||
a reasonable cost in complexity and time. This level of optimization is
|
||||
|
|
|
|||
Loading…
Reference in a new issue