Graphics Reference
In-Depth Information
substitute simpler, more easily implemented, algorithms (of similar efficiency)
over more complicated ones.
Do not unroll loops unnecessarily. Only unroll short innermost loops and only to
the point where there is enough code in the loop body to fill any stalls due to
instruction latencies, but not further.
Compile for size, not speed. Rather than compiling at the highest optimization
setting, try compiling with a compiler option that attempts to minimize code
size (such as -Os provided by the gcc compiler) and see what effect it has.
Avoid creeping featurism. Keep the functionality of a routine as simple as possible.
If a function handles several cases, but only one occurs at a time, provide multiple
functions, one for each case.
Use assembly language where beneficial to do so. For a few time-critical applica-
tions, writing assembly code can be a good option. Contrary to popular opinion,
good low-level programmers can frequently write better assembly code than a
compiler can generate.
Although it might conflict with common software engineering practices, an effec-
tive way of improving locality is to adopt a more monolithic approach to code writing.
Writing all code in a single function might be overkill, but writing larger functions
helps. It also helps bringing functions closer to frequent call sites, to fit within the
same cache page as the caller. Functions can be brought closer by manually moving
them from one file to another to be defined just before or after the function they
are called in. On some systems, functions can be moved automatically during link-
ing by defining multiple code segments, corresponding to contiguous areas of code
space. Compiler extensions then allow functions to be explicitly tagged with the code
segment they should be placed in (for example, the gcc compiler provides this func-
tionality through the __attribute__ ((section ("xxx"))) extension). If a function
is commonly used in several places, it can be worthwhile providing multiple copies
of the function, associating one with each call site. Some code profilers can aid in this
reorganization by providing a suggested function ordering.
Within functions, large if statements disrupt locality when either branch of the
statement is skipped. In some cases, the two branch paths can be merged into one,
reducing code size and therefore improving locality. As an example, consider the
following code, part of a large function.
if(m>n){
for(inti=a;i<b;i++)
c[i] = (big expression involving i) * d[i] + (second big expression
involving i);
} else {
for(inti=e;i<f;i++)
 
Search WWH ::




Custom Search