Embedded Systems Software, Computer Networking and Geeky Fun

nerd1951.com

April 20, 2008

C/C++ Compiler Optimizations

Filed under: Tools, Rants, Programming — Harvey @ 7:33 pm

I have often seen obscure code written in a misguided attempt at “hand optimizing.” The irony is that I have also noticed in the make files for the same code that no optimization options were used when compiling the code. What a waste of time; human and computer.

The default level of optimization for most C/C++ compilers is none. The compiler spits out machine code that conforms very closely to the code you have written. This is good for debugging but is not efficient when running the code.

Let’s take a look at some code for a couple of simple functions in C and the assembly language that GCC generates for the ARM processor. Here is the C code:

int adder(int a, int b)
{
    int c;
    c = a + b;
    return c;
}

main(int argc, char* argv[])
{
    int a, b, c;
    a = atoi(argv[1]);
    b = atoi(argv[2]);
    c = adder(a, b);

    printf("nsum = %dn", c);
}

Now let’s look at the assembler generated for the function adder. The assembly was generated with the option -fverbose-asm. This option tells the compiler to put some comments in the assembly language about what it’s doing. The option is generally only used by compiler developers but it’s also useful for our purpose, trying to understand how optimizations effect the generated code.

adder:
        @ args = 0, pretend = 0, frame = 12
        @ frame_needed = 1, uses_anonymous_args = 0
        mov     ip, sp  @,
        stmfd   sp!, {fp, ip, lr, pc}   @,
        sub     fp, ip, #4      @,,
        sub     sp, sp, #12     @,,
        str     r0, [fp, #-20]  @ a, a
        str     r1, [fp, #-24]  @ b, b
        ldr     r2, [fp, #-20]  @ a, a
        ldr     r3, [fp, #-24]  @ b, b
        add     r3, r2, r3      @ tmp105, a, b
        str     r3, [fp, #-16]  @ tmp105, c
        ldr     r3, [fp, #-16]  @ D.1727, c
        mov     r0, r3  @ (result), (result)
        sub     sp, fp, #12
        ldmfd   sp, {fp, sp, pc}

The @ symbol begins a comment. The first four lines of code save some state information then create space on the stack for the function’s parameters. In C, local variables and function parameters are traditionally passed on the stack. The compiler makes room for two four byte words on the stack with the instructions:

    sub    fp, ip, #4
    sub    sp, sp, #12

What does it do with this space? It takes the two parameters that are already loaded in registers and stores them in memory on the stack; exactly what the C code says to do. Then the same two values are loaded into registers so we can do the real work of the function, add a and b. The result is moved to R0 to pass it back to the caller. Again, the traditional implementation in C is to return results in R0.

Why would the compiler generate code that wastes time moving things in and out of memory like this? It’s actually to make the code easier to debug. You might not have access to the processor’s registers due to the limitations of your debug tools and writing the parameters out to memory might be your only chance to see what is being passed to a function.

So now lets look at what the first level of optimization does to our function (-O1 for gcc).

        @ link register save eliminated.
        @ lr needed for prologue
        add     r0, r0, r1      @ (result), a, b
        mov     pc, lr  @

Quite a bit smaller, isn’t it? The first thing the compiler has told us that it doesn’t need to save the link register. Actually the compiler generated code doesn’t save a lot of state information that it did it the previous case. Next the parameters are left in the registers. The compiler was even smart enough to put one of the parameters, a, in R0. Since we are about to clobber R0 to pass back the result, this saves using another register. So the first level of optimization saves about a dozen instructions without doing anything exotic.

At the highest level of optimization, -O3 for gcc, the compiler uses the option -finline-functions-called-once. This tells the compiler to inline any functions that are only used once. So the entire function shrinks to a single line of code in main():

     add     r4, r4, r0      @ tmp109, a,

This is an important optimization to know about. Often you may have a long function that should be broken up into several functions for readability but you may be reluctant to do this because you don’t want to incur the overhead of several function calls. With the -finline-functions-called-once optimization you don’t have to worry about the function call overhead and you can focus on writing readable code.

So when you’re done debugging your code, don’t forget to turn on the optimization options and recompile. Then test it one last time. Compilers are smart but not infallible.

• • •
 

April 15, 2008

Battle Plans and Software Design Documents

Filed under: Rants — Harvey @ 9:01 pm

Dwight D. Eisenhower once said of battle plans:

In preparing for battle I have always found that plans are useless, but planning is indispensable.

For those of you who don’t remember their history, Eisenhower was supreme commander of the allied forces in Europe in World War II. He oversaw the D-Day invasion at Normandy, one of the most complex military maneuvers ever executed. I’d say Eisenhower knew a bit about battle plans and planning for battle.

I think software design documents are a bit like battle plans. Once code is being written, things start to change and the design documents quickly become useless. But writing the design document is invaluable.

Writing a design document forces you to think about solving the problem at hand. As you break down the problem into sections that you can describe in a document, you are also partitioning the software into logical pieces. In order to organize your ideas enough to write them down, you discover details and issues that you will need to address during implementation. But once you start coding, you will learn even more and the final result will render the design documentation obsolete.

I have often heard this obsolescence used as a reason for skimping on design documentation or skipping this step at all. Many agile methods eschew formal design documents. But I think this misses the point of creating design documents. The goal of design is not to write a document but to gain a better understanding of the problem.

So, what do we do to support software maintenance? Write good code and document it well. Use a code documentation tool like Doxygen or JavaDoc. These tools not only generate documents that match the code but also enforce a level of discipline in commenting code. Running Doxygen against your code will show you just how well you’ve done commenting it. Comment the code in a way that makes the Doxygen documentation useful. The you can through away the original design documents and anyone new to the code will have an accurate road map to the design and the implementation.

• • •
 

April 11, 2008

Pinnacle of Nerdlyness, time, and distance

Filed under: Geeky Fun — Harvey @ 7:07 pm

Today I was walking past a hall way discussion when one of our engineers said “This is a wavelength,” holding his hands about 8” apart to illustrate. After I passed, I turned around and said “but this is a nanosecond,” Holding my hands roughly a foot apart. The three of them just looked at me blankly. My nerd humor has reached such a pinnacle of nerdlyness that even other engineers don’t understand my jokes. Then one of them chuckled and said, “You can tell it took us longer than a nanosecond to catch on.

Had they ever been to a lecture given by Admiral Grace Hopper, they would have understood immediately. Admiral Hopper was a pioneer in computing in the Navy. In order to illustrate the speed of what happens in computers to her less technical fellow officers, she would pass out “nanoseconds” pieces of wire, a little under a foot in length that showed how far light could travel in a nanosecond.

This got me thinking about the bandwidth and data rates of the equipment we work with in the early 21st century. It takes an electrical signal about 1.5 nanoseconds to travel the length of an equipment shelf in a standard 19” rack. In the nineties, we could clock backplanes with a central clock. Every module plugged into the backplane would use the same clock to synchronize data transfers. We could live with the propagation delay across the backplane for clock and data as long as we kept the data rate below about 500 MHz.

In the late nineties we ran into the physical limits of this approach as we started dealing with data rates of 1 GHz, 2.5 GHz. and even 10 GHz. Now such data rates are common place and in a modular design, this means that data arriving from different modules is skewed according to the distance the data travels. The solution is that now both clock and data are carried together and the data must be synchronized at its destination. Often the clock is derived from the data stream itself.

So now I think “Wow, 100 picoseconds is this long,” holding my thumb and index finger about an inch apart.

• • •
 

April 9, 2008

Scientists Abusing Drugs?

Filed under: Rants — Harvey @ 8:45 pm

OK this is an off topic and a real rant but it annoys me when people who should know better think that there are chemical short cuts.

Scientists take drugs to boost brain power: study OK, this is interesting. Scientists think it’s OK to abuse “performance enhancing” drugs for their work but athletes aren’t allowed. Is it because the scientist’s work is more important? Or, do they just know what they’re doing because scientists are like, “smarter” than athletes?

The drugs they are talking about are primarily Ritilin and PROVIGIL (modafinil). What we use to call speed. High class/low octane versions of METH.

Many even said that they would give it to their children if they thought other children were using these drugs to gain an advantage.

Has this “hurry up and get it done now” world gotten to the point that our brightest minds have to be hyped up to perform fast enough. What ever happened to old fashion contemplation of difficult and interesting problems? What about the old fashion notion of getting a good nights sleep. How many times have discoveries been made because of a dream? The structure of benzene is a famous case of a discovery based on a dream. How often has someone woken up in the morning with an answer or a fresh approach to a problem? I’m not a world class researcher but I know I’ve had more good ideas in my morning shower or during my morning commute after a good night’s sleep than I ever had using a “cognitive enhancer.” (Like coffee, I really mean coffee).

• • •