Achieve Maximum Application Performance Migrating From UNIX* to Linux*

Submit New Article

Last Modified On :   October 23, 2008 2:51 PM PDT
Rate
 


by An Le, Technical Consulting Engineer &
Max Domeika, Technical Consulting Engineer


Introduction

Unless you built your application using GNU C/C++ on UNIX*, migrating from UNIX to Linux* will most likely also involve switching compilers. This introduces a host of challenges such as changing compiler flags, makefiles, and the build process, while ensuring continued optimal performance. SourcePro* C++ allows the developer to automatically generate new makefiles for the low-level infrastructure code when you change platforms. Achieving the maximum potential of SourcePro C++ requires a compiler capable of producing highly optimized code. The Intel® C++ Compiler simplifies migration from UNIX to Linux by offering a very high level of conformance to the ANSI/ISO C++ standard, and advanced compiler optimizations that are used on UNIX systems. Optimization procedures include inter-procedural optimizations, profile guided optimization, as well as processor specific optimizations that can ensure better performance. Because the Intel C++ Compiler is binary compatible with GNU C/C++ on Linux, this allows developers to build performance-critical libraries used by their applications with the Intel C++ Compiler to gain additional flexibility when porting applications from UNIX to Linux. Learn more about the best techniques to ensure ease in compiler transition, while gaining the best possible performance on your Intel® processor-based Linux platform.


Rogue Wave SourcePro C++

Rogue Wave* SourcePro C++ is an integrated set of cross-platform, object-oriented C++ components based on the International Organization of Standards (ISO) and the American National Standards Institute (ANSI) standards. Rogue Wave SourcePro C++ products are provided with full source code and pre-built versions of the libraries. SourcePro C++ includes four primary components:

  • SourcePro Core — Fundamental C++ components
  • SourcePro DB — Components to provide relational database access in C++
  • SourcePro Net — Components for network and Internet Communication
  • SourcePro Analysis — Components for business and scientific analysis

 

Consistent across multiple platforms, SourcePro C++ components share common, compatible interfaces. And because the components are highly integrated, SourcePro C++ enables developers to quickly migrate software to other platforms, in many situations, without having to rewrite code. Using the pre-built software components helps development teams increase productivity, but in order to achieve the maximum performance potential, the SourcePro C++ components require a compiler capable of producing highly optimized code.


Intel® C++ Compiler

The Intel® C++ Compiler for Linux* offers excellent compatibility with GNU C/C++ and most Linux software utilities and contains advanced optimization features to easily maximize application performance. The advanced optimization features of the Intel C++ Compiler for Linux include high floating-point performance, inter-procedural optimization, profile-guided optimization, and vectorization support for processor specific ins truction sets on Intel® architecture. Since the Intel C++ Compiler for Linux is compatible with the GNU C/C++ compiler, and both the Intel C++ Compiler and the Rogue Wave SourcePro C++ components are ISO- and ANSI-standard compliant, developers can minimize compatibility and migration issues. By compiling SourcePro C++ components with the Intel C++ Compiler, the libraries created can be custom built to specifically target the architecture and to maximize performance of desired applications on Intel architecture.


ISO Conformance

Two widely used languages for software development are C and C++. Each of these languages has been standardized by various organizations. For example, ISO C conformance is the degree to which a compiler adheres to the ISO C standard. Currently, two ISO C standards are commonplace in the market: C89i and C99ii. C89 is currently the de facto standard for C applications; however use of C99 is increasing. The ISO C++iii standard was approved in 1998. The C++ language is derived from C89 and is largely compatible with it; differences between the languages are summarized in Appendix C of the ISO C++ standard. Very few C++ compilers offer full 100% conformance to the C++ standard due to a number of somewhat esoteric features such as exception specifications and export template. The Intel C++ Compiler offers a high degree of conformance.

The Intel compiler has a unique challenge in maintaining compatibility with other available compilers and functioning with these other compiler's header files and libraries while also maintaining compatibility with the language standard. In order to accommodate these needs, the compiler in its default mode is compatible with these other compilers. On Linux, the Intel C++ Compiler is interoperableiv with the GNU g++ compiler. The Intel compiler also provides options to conform more closely to the ISO standard. These options are summarized as follows:

Compilation Mode Description
Default Compatibility with GNU C++ compiler
-ansi Compatibility with GNU C++ compiler's definition of ISO conformance
-strict_ansi Intel C++ Compiler definition of ISO conformance
-[no-]c99 C99 conformance and feature support
-std=c89 C89 conformance and feature support

 


G++ Compatibility

The Intel C++ Compiler 9.0 for Linux is interoperable1 with GNU g++ 3.2, 3.3, 3.4, & 4.0. The Intel C++ Compiler detects the version of g++ accessible in your search path (specified by the PATH environment variable) to determine which version to be compatible with by default. In addition, the following options can be employed to tailor the degree of compatibility with GNU g++:

Option Description
-gcc-version=<Version string> Specify the version of g++ compatibility
-no-gcc Turn off GCC predefines
-fno-gnu-keywords Do not recognize 'typeof' as a keyword
-gcc-name<name> Specify the precise location of the g++ compiler for compatibility

 

For more information on gcc/g++ compatibility see the compatibility whitepaperv.

Applications compiled by the Intel C++ Compiler 9.0 for Linux can be linked with the C++ run-time provided by GNU which includes the standard C++ header files, library and language support (libstdc++). The Intel Compiler still allows use of legacy Intel provided C++ header files and library (libcprts, libcxa and libunwind) by specifying the -cxxlib-icc option. The principle advantage of linking with libstdc++ is potentially greater compatibility to 3rd party libraries and shared objects; code compiled by the Intel C++ Compiler is interoperable with 3rd party libraries and shared objects which have been compiled by GNU g++ and shipped as binaries.

i ISO/IEC 9899:1990, Programming Languages C.

ii ISO/IEC 9899:1999, Programming Languages C.

iiiISO/IEC 14882, Standard for the C++ Language

iv Goodman, Joe, "Interoperability & C++ Compilers," C/C++ Users Journal, March 2004, pg. 44-47.

v Intel® Compilers for Linux*: Compatibility with GNU Compilers, http://www.intel.com/cd/ids/developer/asmo-na/eng/222301.htm

 


Performance

The strongest advantage of the Intel C++ Compiler is its optimization technology and performance feature support. The Intel C++ compiler offers aggressive optimization at all levels of the spectrum: architecture-independent, architecture-dependent, and advanced optimizations.

  • Architecture-inde pendent optimization employs an advanced framework called Static Single Assignment and implementations of partial-redundancy elimination, Boolean propagation, induction variable optimization, and many others.
  • For architecture-dependent optimizations, the Intel Compiler engineers collaborate closely with Intel microprocessor architects to prototype and develop many optimizations during the development of a new microprocessor. This level of cooperation ensures the best level of architecture-dependent optimization possible.
  • To extract even more performance from your application, use advanced optimizations such as vectorization, Interprocedural Optimization, and Profile-guided Optimization.

 

For detailed information on using the performance features of the Intel C++ Compiler, please consult the optimization whitepapervi. The next four sections describe a few of the key optimization phases available in the Intel C++ Compiler. Use of these optimizations can enable substantial performance gains in your application.


Interprocedural Optimization

Compilers typically process one function at a time and in isolation from other functions in the program. During optimization, the compiler must often make conservative assumptions regarding values in the program due to side-effects that may occur in other functions, limiting the opportunity for optimization. A compiler with interprocedural optimization optimizes each function with detailed knowledge of other functions in the application. Interprocedural optimization is an enabler of other optimizations. These other optimizations are more aggressive, but safe, because of the enhanced interprocedural information. Descriptions of several optimizations enabled by interprocedural optimization follow:

  • Interprocedural constant propagation — constant values are propagated through function calls, particularly function call arguments.
  • Arguments in registers — passing arguments in registers can reduce call/return overhead.
  • Loop-invariant code motion — increased interprocedural information enables detection of code that can be safely moved outside of loop bodies.
  • Dead code elimination — increased interprocedural information enables detection of code that may be proven unreachable.

 


Profile Guided Optimization

Profile-guided optimization enables the compiler to learn from experience. Profile-guided optimization is a three-stage process involving 1) a compile of the application with instrumentation added, 2) a profile generation phase where the application is executed and monitored, and 3) a recompile where the data collected during the first run aids optimization. A description of several code size influencing profile-guided optimizations follows:

  • Basic block and function ordering — place frequently-executed blocks and functions together to take advantage of instruction-cache locality.
  • Aid inlining decisions — Inline frequently-executed functions so the increase in code size is paid in areas of highest performance impact.
  • Aid vectorization decisions — vectorize high trip count and frequently-executed loops so the increase in code size is mitigated by the in crease in performance.

 


Vectorization

Vectorization is an advanced optimization that analyzes loops and determines when it is safe and effective to execute several iterations of the loop in parallel by utilizing MMX, SSE, SSE2 and SSE3. Figure 1 is a graphical representation of a vectorized loop that shows four iterations computed with one SSE2 operation. Use vectorization to optimize your application code and take advantage of these new extensions when running on Intel processors.


Processor Dispatch

One challenge with these instructions (MMX, SSE, SSE2 and SSE3) in applications is the desire to support several generations of IA-32 processors with one version of the application while still taking advantage of these instructions. One solution is to manually code a cpuid check into your application that calls different versions of a function based upon the processor of execution. A unique Intel Compiler solution, processor dispatch technology, offers language features and an automatic method that allows the use of SSE3 instructions when the application is executing on the latest Intel processors and designates alternate code paths when the application is executing on an Intel processor that does not support SSE3.

 


Tools for Achieving Successful Migration to Linux

There are many challenges to porting C++ applications to Linux. In some cases, the transition process can be handled efficiently and effectively by using developer tools from Rogue Wave Software and Intel. De velopers can work through potential ISO conformance issues by using the Rogue Wave Standard Library implementation that behave the same and work identically on all supported platforms. The high performance Rogue Wave Standard Library is fully tested, and it is fully supported by the Intel Compiler for Linux. Figure 2 in the appendix contains sample code that demonstrates a matrix multiply utilizing SourcePro C++ library and the Intel Compiler. Combining these tools will help developers to efficiently and effectively port C++ applications to Linux.


Conclusion

The Intel C++ Compiler provides a number of desirable features that can increase the performance of your application. When used in conjunction with Rogue Wave SourcePro C++, the Intel C++ Compiler eases porting of applications from Unix to Linux.

About the Authors

An Le is a senior software engineer in the Software Products Division at Intel, working with software tools targeting the Intel architecture. He has held several positions in software development focusing on porting and optimizing application targeted for Intel architecture. He has also presented classes at Intel Developer Forums on performance optimization using Intel software tools. An currently provides technical consulting for the Intel Compiler products. He earned his B.S. in Computer Science from Portland State University.

Max Domeika is a senior staff software engineer in the Software Products Division at Intel, creating software tools targeting the Intel Architecture market. Over the past 9 years, Max has held several positions at Intel in compiler development including project lead for the C++ front end and developer on the optimizer and the IA32 code generator. He currently provides technical consulting for a variety of products targeting Embedded Intel® Architecture and also provides software tools training serving as an instructor with the Intel® Software College. He earned a B.S. in Computer Science from the University of Puget Sound and an M.S. in Computer Science from Clemson University.


Appendix
//Figure 2. Code demonstrating matrix multiply using Rogue Wave SourcePro* C++ 

//library and the Intel C++ Compiler for Linux



#include "rw/cstring.h"

#include "rw/math/genmat.h"



#ifndef RW_NO_IOSTD

# include "fstream"

#else

# include "fstream.h"

#endif



#if !defined(RW_NO_STD_NAMESPACE)

# if !defined(RW_NO_IOSTD)

using std::cout;

using std::cin;

using std::endl;

using std::flush;

using std::ios;

using std::ifstream;

using std::ofstream;

# endif

#endif



int main()

{

RWGenMat<int> A,B;

RWCString inputFile1 = "./m1.in";

RWCSt
ring inputFile2 = "./m2.in";

RWCString outputFile3 = "./m3.out";



//Read in data file in the format

// 2x2 [1 2

// 3 4]

//and initialize the matrices.



ifstream dataFile1( inputFile1.data(), ios::in );

if ( !dataFile1 )

{

cout << "Could not open file " + inputFile1 + " from the input directory" << endl;

return FALSE;

}

dataFile1 >> A;



ifstream dataFile2( inputFile2.data(), ios::in );

if ( !dataFile2 )

{

cout << "Could not open file " + inputFile2 + " from the input directory" << endl;

return FALSE;



} dataFile2 >> B;



//Matrix multiply

RWGenMat <int> C = product(A,B);



//Ouput result to a file

ofstream dataFile3(outputFile3.data(), ios::out);

if ( !dataFile3 )

{

cout << "Could not open file " + outputFile3 + " from the input directory" << endl;

return FALSE;

}

dataFile3 << C;



return 0;

}