Archive for the ‘Optimization’ Category

Large Arrays In C

Monday, August 24th, 2009

Subscribe To Our Feed | Follow Us On Twitter | Get Updates on Email

Most C programmers, even beginners, would claim that arrays are easy, except those abundant off-by-one errors and they are right. Arrays are easy indeed. However, here are a few points to consider when writing a program that needs a rather large array (By the way, the thought for this article came into mind while helping a colleague to resolve an error a couple of days ago). When creating a large array (e.g. something like int a[1000][1000], which BTW takes up around 3.8 MB on most machines), you might not have any issue at all or might see either a compile time error or worse, runtime errors.
Why do these errors happen? Depending on your machine’s limitations you are most probably consuming the total available stack (if you used a local variable) or data memory. Depending on your compiler, these might be flagged at compile time or surface when you try to run your program. Or it might be that your compiler isn’t able to work with large arrays. What you can do to alleviate these:

  • The first and best way is to minimize your array size (This makes for an amazing example here from the bookd “Programming Peals”: http://www.cs.bell-labs.com/cm/cs/pearls/cto.html )
  • Use “huge” memory model.
  • Use a global variable (or a static variable if you are particular about its visibility to the rest of the program). The stack is generally quite limited as compared to the data memory available to a program. So, a variable with static storage would ensure that you use memory from the data segment.
  • Don’t declare it as an array at all and instead use a pointer and dynamically allocate the memory required for it. You might have to use special allocation calls instead of normal malloc/calloc to get this working though (e.g. using farmalloc)
  • Create a section in assembly with the “Area” directive (or whatever it is for your particular assembler) and reserve space for your array there and refer to that array as an extern variable.

The first approach is something that you should always look for. But if you can’t mimize your need any further, choose one out of the rest two. But few things to be kept in mind here that these options can still fail, e.g., when you don’t have enough RAM/heap memory remaining at runtime (of course, you would have planned for a graceful exit though in such case instead of the random crash that would have occured otherwise). But still these could be useful to you in case you don’t have any real RAM limitations but just that your compiler isn’t able to work with large objects.

© Safer Code | Large Arrays In C

Liked this post? Get FREE Updates
Subscribe to RSS feed

Or
Enter Your E-mail ID below

Volatile: C Keyword Myths Dispelled

Tuesday, February 24th, 2009

Subscribe To Our Feed | Follow Us On Twitter | Get Updates on Email

Last time we explained the real meaning of const keyword, this time it’s going to be Volatile, the other sibling of this most misunderstood duo in C history. Let’s separate out the myths and the facts first and then we will discuss the how’s and why’s of it.

FACTS:

  • A volatile qualifier is important to be used for auto-storage variables within setjmp and longjmp.
  • A volatile qualifier must be used when reading the contents of a memory location whose value can change unknown to the current program.
  • A volatile qualifier must be used for shared data modified in signal handlers or interrupt service routines.

MYTHS:

  • All shared data in multi-threaded programs must be declared volatile.

Now, we’ll see how we made the above classfication.

(more…)

© Safer Code | Volatile: C Keyword Myths Dispelled

Liked this post? Get FREE Updates
Subscribe to RSS feed

Or
Enter Your E-mail ID below

Tweak Your Code For Speed: Unroll Those Loops Part 1

Tuesday, January 27th, 2009

Subscribe To Our Feed | Follow Us On Twitter | Get Updates on Email

One of the ways to optimize your code for speed is to unroll the loops you have in your program. If you don’t know what loop unrolling is, then see the following simple example, where we are trying to copy a 5 element long string:
A Simple Loop:

for (i = 0 ; i < 5; ++i)
{
    *j++ = *k++;
}

The same loop unrolled:

*j++ = *k++;
*j++ = *k++;
*j++ = *k++;
*j++ = *k++;
*j++ = *k++;

Now, the unrolled version is definitely going to be faster because of the following reasons:

1. There are no branches any more. In a loop, the compiler has to insert branches to jump back to the for statement.

2. There are no condition checks. In a loop, the value of i is checked every time to see what to do next.

3. A third rather hidden, but really important, advantage is that unrolled code can be pipelined efficiently by the processor hence resulting in faster execution.

The above code in itself might not show you any perceivable difference in execution time, but it does become crucial when the loops are of much higher magnitude and especially in embedded/real time scenarios.

Now, the loop unrolling can be done by the compiler or manually by the coder. In this part, we will see how to facilitate compiler to carry out loop unrolling efficiently. (more...)

© Safer Code | Tweak Your Code For Speed: Unroll Those Loops Part 1

Liked this post? Get FREE Updates
Subscribe to RSS feed

Or
Enter Your E-mail ID below

Optimizing Switch-Case Statements In C For Speed

Tuesday, October 28th, 2008

Subscribe To Our Feed | Follow Us On Twitter | Get Updates on Email

The biggest bottlenecks in making efficient code today are jumps or branches. You must have always heard of people telling you to use switch-case blocks instead of cascadin if-else’es. They were right, but partially.

This is because a cascading if-else block will check for each condition in each iteration until it reaches the correct one. On the other hand, switch-case blocks are “supposed to” (why supposed to, we’ll see just now) just execute the correct statement and move on.

Optimization Technique 1: Keep the case label values close and small (Answer to “supposed to”)

Actually switch-case statements are also many times changed into if-else cascades by the compilers. This happens when the case label values are too far apart and/or are spread over a fairly large range. If you have a small switch-case statement like below, then the compiler will generate a jump-table instead of the if-else cascade.

switch(a)
{
  case 0: /*do something*/
  case 1: /*do something*/
  case 2: /*do something*/
  case 3: /*do something*/
  default:
}

A jump table is like a “lookup table” or a “dispatch table”. You can assume that compiler creates an internal array of addresses. The array is indexed by the case lable values and the value at that index is the address of instructions corresponding to that case.

Optimization Technique 2: Place those cases first which are more likely to occur

(more…)

© Safer Code | Optimizing Switch-Case Statements In C For Speed

Liked this post? Get FREE Updates
Subscribe to RSS feed

Or
Enter Your E-mail ID below