High Performance Computing: Porting A Code to Another Platform

Porting A Code to Another Platform

Software Differences | Same Code, Same Data | Compiler and Loader Option Differences
Tracking Problems with Preprocessor, Compiler, and Loader Options

Software Differences

The problems encountered when porting a code to another machine are usually due to different software (preprocessor, compiler, loader, operating system, environment) or hardware. These software differences can cause:

  • Operations executed in a slightly different manner.
  • Values stored differently.
  • Exceptions handled differently.
  • Problems due to a previously unknown bug in the code.
  • Slightly different or vastly different results.

When a problem is encountered in porting a code, the best solution is to read the documentation and then begin debugging the code.

When porting a code between two machines from different vendors, there is always the possibility of encountering problems or locating bugs not previously known in a code. This can also happen when porting a code to a different machine or environment using the same vendor.

Verify That You Are Testing the Same Code with the Same Data

  • Do not begin rewriting sections of the code to take advantage of the machine to which you are porting until after you have successfully ported a plain-vanilla version of the code that works identically on both the original and new platform.
  • Do not try new compilers or features available on the new platform. Use the default compilers and features, or those most similar to the platform from which you are porting. The time to try new options, compilers, and features is after you have had success in porting the code.
  • Do not begin parallelizing a code on a new platform when the code hasn't been first ported in a serial version, if possible.
  • You may want to start with a completely unoptimized code on both platforms as a baseline for the port.
  • Do not make even minor changes to the data that you are "sure will not affect anything." Whenever possible, test your port on the identical data used to test the code on the original platform. If the original test case cannot be used on the new platform, try to develop a new test case that can be used to test the port on both platforms.


Compiler and Loader Option Differences

  • Check all the options used to preprocess, compile, load, and execute the code on both the old and new architectures to make sure the same default behavior is being targeted. This may involve checking your environment variables, path, and if it exists, the libpath setting.
  • Make sure you thoroughly understand each of the options used. Use of an option can change the way the code is built and can change the behavior of the code. Make sure all the options used are interpreted in the same way on the different platforms.
  • Check the level of precision, e.g., how many bits are being used in integer arithmetic, and how many bits used for real and double precision arithmetic. Are there options to override the precision specified within the code? Consider using the same precision on both architectures to see if it solves the problem.
  • Are default levels of optimization being overridden? Although in most cases optimization levels should not cause different behavior, it is worth checking. You might consider lowering the level of optimization on both architectures to the most limited level or no optimization.
  • Check how string constants are handled (Hollerith or character string).
  • Are variables being initialized (or not initialized) during the building of the code (e.g., setting default values to zero, null, or another value)?
  • Check how logical values are determined (e.g., will the same values be evaluated to true and false on both platforms)?
  • Are there exception handlers that are or are not enabled by default (e.g., overflow, divide by zero, etc.)? Do the exception handlers that are enabled behave in the same manner (e.g., are overflows and underflows ignored or is an error printed)?
  • Is stack or static storage of variable values used? If two different methods are being used, this can cause different initialization of variables within routines.
  • Are any options used that might cause parallel execution using threads or other parallel execution models? Try porting a serial version of the code first, and if that is not possible, try porting a version that runs on a minimum number of nodes.
  • Are there any options or default behaviors that could cause different rounding methods to be used? For example, rounding of constants at compile time or execute time and rounding algorithms for numeric operations.
  • Is the architecture being specified when the code is being built? If this type of option is being used, make sure a valid architecture is being specified, and check if the target architecture being ported to is supported on the machine on which the code is running (this is most useful when porting to a machine from the same vendor).
  • Options that set or change the level of the language standard or which change or more strictly enforce the standard exist in some software. Make sure the software is using the same standard or style (ISO, ANSI, POSIX, K&R, etc.).


Tracking Problems with Preprocessor, Compiler, and Loader Options

  • Bounds checking.
  • Display extra levels of error and warning messages, at all severity levels. Carefully check all messages.
  • Change the level of optimization, starting with no optimization on both platforms and working up to the default optimization before moving on to a higher level of optimization.
  • If possible, get and read the load map, checking which libraries are loaded and verifying that an unexpected library or routines from an unexpected library are not being used. If a load map is not available, try explicitly specifying the libraries you expect to use on your compile or load execute line. Use the LC findentry utility to locate which library contains particular routines. A nice feature of findentry is that it will tell you if a routine is found in more than one library, which is sometimes the cause of a problem.
  • If you are explicitly specifying libraries, do so very carefully and as a last resort, because loading libraries in an incorrect order can cause problems.

C Language Considerations

Some of the LC machines provide a default C compiler that supports the ANSI standard, while the default on other machines is a KAI version of the C compiler.


  • cc and xlc are KAI style C.

Use the genproto=\<parmnames\> option to produce ANSI prototypes from KAI function definitions.


The Intel C++ compiler, icc, is designed to preprocess, compile, assemble, and link C and C++ programs on systems based on Intel architecture.

Conformance Options
-ansi-alias -ansi -strict-ansi -c99 -std=c99

gcc Interoperability

C language object files created with the Intel C++ compiler are binary compatible with the GNU gcc compiler and glibc, the GNU C language library. See the icc man page for details and a summary of the compiler options.

MPI Considerations

Different vendors provide different implementations of MPI. While they should all produce the same results, in reality different buffer sizes and methods and different default or limit values may affect results.

If there is an MPI implementation available on both platforms that is not vendor dependent (e.g., MPICH) and if using it does not require too many coding changes, first try using the software available on both platforms. Once ported and verified, try using the vendor-supported MPI.