• Embed Doc
  • Readcast
  • Collections
  • CommentGo Back
Download
 
12
February 2008
|
LINuX For you
|
 www.pnITis.cm
c m yk
Insight
hen can we write highlyecient code? It is when weunderstand how the underlyingmachine works and make bestuse o that knowledge. Onewell-known way to write highly ecient codeis to write code in assembly. There are manydisadvantages with this; or example, wecannot port the programs easily, it is dicultto maintain the code, etc. So, we need to look
 
 W 
or alternatives to write ecient code.We can write in low-level programminglanguages like C to get write code, whoseeciency is oten comparable to theequivalent code written in assembly. For thisreason, C is oten reerred as a ‘high-levelassembler’. In this article, we’ll look at variousprogramming constructs rom the perspectiveo eciency. We’ll consider general machinearchitecture or illustration; and or specic
How many programmers can actually write assembly programs? With the rising popularityof high-level languages (like Java, VB.Net, etc), there is rarely any need for programmersto learn assembly or low-level programming. However, there are domains where writing
efcient code is very important, for example, game programming and scientic computing.
Insight
Understand the Machineto Write Efficient Code
 
www.pnITis.cm
|
LINuX For you
|
February 2008
c m yk
13
Insight
examples, x86 architecture will beused. A word o caution beore weproceed: the techniques and issuescovered are not or general-purposeprogramming.
Basic types
The machine, in general,understands only three types o  values: address, integer and foating-point values. For representationand manipulation, here is thecorrespondence between the typesthat the machine can understandand what C supports. Addressescorrespond to the pointer construct;integers—both signed andunsigned—correspond to short, int,long, long long, char (yes, a char isrepresented as an int internally!) etc;foating-point types correspond tofoat, double, long double, etc.The most ecient data-typethat a processor handles is a ‘word’,which corresponds to ‘int’ typein C. For foating-point types, allcomputation is typically done ina larger foating-point type. Forexample, in x86 machines, allfoating-point computation is donein ‘extended precision’, which is 80bits in size and usually correspondsto ‘long double’ in C; i foating pointexpressions are used in the code,they are internally converted toextended precision by the processorand the results are converted backto foat (which occupies 32 bits).The processor does foating-pointcomputations in a separate ‘co-processor’ unit. Address computation (suchas array index access) is doneusing pointers in C. They directlycorrespond to memory accessoperations in the underlying machine(such as index addressing, in thiscase).The ‘int’ type is the most ecientor computations. Unsigned typesand operations on that are asecient as signed types. Floatingpoint types and operations are slowcompared to integral types. Forexample, in an imaginary processor,i integer division takes our cycles,foating point division operationmight take 50 to 100 cycles. Memoryaccess operations are very slow—i the desired memory location is not incache, then it might take hundreds o cycles to etch the data rom the mainmemory.
Operators
C supports a rich set o operators.There are ew operators that aredirectly supported by the processorand there are a ew that are simulatedin the sotware.For integral types, bit-manipulation operators are astercompared to other operators likearithmetic, logical or relationaloperators. One o the ways to writeecient code is to write code usingbitwise operations instead o otherslower operations. Here is a well-known example: Using ‘<<’ is moreoperator ecient than dividing aninteger value by 2. We’ll look at adierent example or illustrationhere. A typical code segment ortoggling a character’s case is to userelational operators, as in:
// precondition: the char ch providedis in range [‘a’-‘z’] or [‘A’-‘Z’]char toggle_ascii_char_case(char ch) {if( (ch >= ‘a’) && (ch <= ‘z’)) // lower casech = ch - 0x20;else if( (ch >= ‘A’) && (ch <=‘Z’) ) // upper casech = ch + 0x20;return ch;}
The code works on the ollowingassumption: the given char ch iswithin the range [a-z] or [A-Z]. I the char is [A-Z], it returns thecorresponding char in [a-z] and vice versa, that is, it toggles the case o the character. The value 0x20 isadded or subtracted based on the actthat the alphabetic characters areseparated by the hex value 0x20 inthe ASCII table.But this unction is slow. I this is a library unction used ortoggling the case o charactersin a string, then it is not a goodimplementation.The code can be improvedas ollows: since the comparisonoperators are not required, theunction precondition says thatch passed to the unction is in thegiven range [‘a’-‘z’] or [‘A’-‘Z’]. Basedon C tradition, we need not checkto ensure that the given char isin act in this range. Also, sincewe are perorming either the ‘-’ or‘+’ arithmetic operation, we canreplace it with bit-wise operationsor toggling the bit using the ex-or operator. With this the codebecomes ecient and simple:
// precondition: the char ch providedis in range [‘a’-‘z’] or [‘A’-‘Z’]char toggle_ascii_char_case(char ch){return (ch ^= 0x20);}
This example is just orillustration purposes. Using bit-wiseoperators obscures the code, but itusually signicantly improves theeciency o the code.
Control flow
C has various conditional andlooping constructs. A C compilertransorms such code constructsto branching (also known as‘jump’) instructions. So, goto is themost straightorward constructor programming. It is possible totake any C program and create anequivalent program by removing allconditions and loops with just gotostatements. Though it is ultimatelybranching instructions, there aresubtle dierences in constructswhen it comes to eciency.Which one is more ecient—nested i conditions or switchstatements? In general, a switchis more ecient than nested i statements. I both are implementedusing branching, why is switch moreecient than nested i conditions?Recall that, in a switch statement,all cases are constants. So, a
of 00

Leave a Comment

You must be to leave a comment.
Submit
Characters: ...
You must be to leave a comment.
Submit
Characters: ...