Optimizing C and Ur Tech-Mind

 

"None of us learn in a vacuum; we all stand on the shoulders of giants such as Wirth and Knuth and thousands of others. Lend your shoulders to building the future!"

   -Michael Abrash

TOC

1.First thing before optimization. 1

2, Design Considerations. 2

2.1 Usage of STL (Standard Template Library) Containers. 2

3. Tips for Coding. 2

3.1 Using References Instead of Pointers. 2

3.2 Optimize inner loops. 2

3.3 Use finite differences to avoid multiplies. 3

3.4 Use powers of two for multidimensional arrays. 3

4 eXtra. 4

 


1.First thing before optimization

            To write a piece of code, there will be right and wrong, fast and slow, optimized and not optimized ways. In this document I will try to give you a brief sketch of the best coding strategies.

            Don’t blindly assume something as a criterion for code optimization. This may make your code more badly. Benchmark the old and current code and use a proper guidance. Avoid premature optimization. Donald Knuth said, "Premature optimization is the root of all evil." Optimization is one of the last steps of a project. Plan for it! Don’t sacrifice the readability to optimization. Give importance to the code correctness first.

Never worry about performance before concentrating on code correctness. Write the code without optimizations first. Let performances issues guide your design, data structures, and algorithms, but don't let performance affect every aspect of your code.

            Here are some tips

ü      Set goals for performance levels

ü      Choose a program architecture appropriate to the problem to solve

ü      Select the proper data structure

ü      Be sure to concentrate on perceived performance

ü      Understand the costs of programming operations and algorithms

ü      Profile to find bottlenecks

ü      Evaluate near-final code (Use release version rather than debug)

ü      Choose the right algorithms

E.g.: consider a code to swap two no, there can be difference methods for it:

 

void swap (int &a, int &b)

{

                int temp = a;

                a = b;

                b = temp;

}

 

void swap (int &a, int &b)

{

                a = a + b;

                b = a - b;

                a = a - b;

}

void swap (int &a, int &b)

{

                a ^= b;

                b ^= a;

                a ^= b;

}

 

Think yourself. Which is better…?

 

2, Design Considerations

            When you start working on your next program and begin to think about coding conventions, compilers, libraries, and general C++ issues, there are many factors to consider.

2.1 Usage of STL (Standard Template Library) Containers

            It is considerably beneficial to use STL containers, since STL vendors focus their efforts on optimization and compiler vendors improve template compilation its advantages are,

·        It's Standard

·        It's Thin

·        It's Flexible

·        It's already written. And debugged, and tested.

One of the disadvantages of the use of STL is, it may not fit into your purpose. The functionality provided in it may be not sufficient or may not be necessary. And you will be forced to create your own library or class for this functionality.

3. Tips for Coding

3.1 Using References Instead of Pointers

            Consider this

                        void Ptr_Incr(const int* p) { x += *p; }

void Ref_Inct(const int& p) { x += p; }

 

            Here we can clearly understand the benefit of using reference over pointers,

Ø      No need to check that the reference is not NULL

Ø      No need of * dereference operator, less and clean code

Ø      Opportunity for greater efficiency with references. There is no guarantee that your compiler will do a better job at optimization, but it might.

3.2 Optimize inner loops

            Reduce the coding inside loops. If possible take the codes outside of it.

for(…;…;…)

{

                if(…)

                                Do A

                else if(…)

                                Do B

                else if(…)

                                Do C

                Etc…

}

 

if(…)

                for(…;…;…)

                                Do A

else if(…)

                 for(…;…;…)

                                Do B

else if(…)

                 for(…;…;…)

                                Do C

Etc…}

           

            It ordinary conditions the second statements executes faster. Because it avoid execution of the conditional statements (which may lot of time) in a loop.

3.3 Use finite differences to avoid multiplies

            Multiplication operation takes much more time to that for addition.

 

for(i=0;i<10;i++)

{

                printf("%d\n",i*10);

}

 

for(i=0;i<100;i+=10)

{

                printf("%d\n",i);

}

 

3.4 Use powers of two for multidimensional arrays

            The advantage of using powers of two for all but the leftmost array size is when accessing the array. Ordinarily the compiled code would have to compute a multiply to get the address of an indexed element from a multidimensional array, but most compilers will replace a constant multiply with a shift if it can. Shifts are ordinarily much faster than multiplies.

 

char playfield[80][25];

 

char playfield[80][32];

 

 

3.5 Declare local functions as "static"

Doing so tells the compiler that the function need not be so general as to service arbitrary general calls from unrelated modules. If the function is small enough, it may be inlined without having to maintain an external copy. If the function's address is never taken, the compiler can try to simplify and rearrange usage of it within other functions.

void swap(int *x, int *y)

{

   int t;

    t = *y;

    *y = *x;

    *x = t;

}

 

static void swap(int *x, int *y) 
{
    int t;
    t = *y;
    *y = *x;
    *x = t;
}

 

4 eXtra

  1. Initialize all variables .  If I declare an int I do this (int iValue = 0;)  if I allocate a char array I do this (char szTemp[20]; memset(szTemp,0,20);).
  2. Check the return codes of all function calls.
  3. Catch all exceptions at an appropriate level and deal with them.  One of the bad habits I had earlier in my career was to setup an empty catch block and think I was going to fill it in later.
  4. When defining function prototypes consider error conditions.  This means deciding whether to return a bool or an int (an int can return a set of predefined flags indicating what kind of problem occurred.  A bool can only indicate success/failure.)  If there is additional info that a simple code can supply, consider passing in a string or other variable by reference to hold the extra error information OR consider throwing an exception.
  5. Never pass objects by value unless ABSOLUTELY necessary.  (I can't think of a situation where this has ever been necessary, but there might be.)
  6. Use GOTOs wisely. 
  7. Create more utility classes than program-specific classes.  
  8. Think about how a piece of code might be used in another project and go ahead and develop for that.  (Don't take this to an extreme, though.)
  9. Comment judiciously.  When I write code comments I try to comment on the architecture and purpose of a function/class instead of on the lowest level of details. 

 

        _ _

 

 

                       ++

    x = y % 32;

    x = y &31;

 

    x = y * 8;

    x = y <<3;

 

    x = y / w + z / w;

    x = (y + z) / w;

 

    if( a==b &&c==d &&e==f ) {...}

    if( ((a-b)|(c-d)|(e-f))==0 ) {...}

 

    if( (x &1) || (x &4) ) {...}

    if( x &5 ) {...}

 

    if( x>=0 &&x<8 &&y>=0 &&y<8 ) {...}

    if( ((unsigned)(x|y))<8 ) {...}

 

    if( (x==1) || (x==2) 
|| (x==4) || (x==8) || ... )

    if( x&(x-1)==0 &&x!=0 )

 

    if( (x==2) || (x==3) || (x==5) ||
    (x==7) || (x==11) || (x==13) 
|| (x==17) || (x==19) ) {...}
    if( (1<<x)&((1<<2)|(1<<3)|(1<<5)|(1<<7)
    |(1<<11)|(1<<13)|(1<<17)|(1<<19))){...} 

 

    int a[3][3][3];
    int b[3][3][3];
    ...
    for(i=0;i<3;i++)
      for(j=0;j<3;j++)
         for(k=0;k<3;k++)
            b[i][j][k] = a[i][j][k];

    for(i=0;i<3;i++)
      for(j=0;j<3;j++)
         for(k=0;k<3;k++)
            a[i][j][k] = 0;

    typedef struct

{
  int element[3][3][3];
} Three3DType;
  Three3DType a,b;
    ...
  b = a;
  memset(a,0,sizeof(a)); 

 

    unsigned int x, y, a;

        ...
    a = (x + y) >>1;
    /* overflow fixup */
    if( a <x &&a <y ) a += 0x8000000;  

    unsigned int x, y, a;
    ...
    a = (x &y) + ((x ^ y)>>1);

 

    Look through school notes for ideas.

    Get examples from WEB/FTP

 

    Ignore suggestions from others.

    Code, code, code, code ...

    Get suggestions but be skeptical.
    Think, code, think, code ...

 

                                  Hi, I Hope this document will be helpful to you as this is my experience in C programming, advices from friends and off course help of net.

-        Franchi

Next Release: Optimizing CPP as OOPS