Programming Environment

Compilers

Several compiler suites are available on Pegasus. Table 11 summarizes the installed compilers.

Table 11: Summary of available compilers on the Pegasus cluster

Compiler Portland Group -7.1.5 Intel – 10.1 MPI GNU
C compiler pgcc icc mpicc gcc
C++ compiler pgCC icc mpiCC g++
Fortran-77 pgf77 ifort mpif77 g77
Fortran-90 pgf90 ifort mpif90 gfortran
Fortran-95 pgf95 ifort mpif95 gfortran

The MPI compilers are wrapper scripts which invoke the Portland Group, Intel or GNU compilers depending on the module chosen. For example if you wanted to use the Intel compilers, you must load the intel module.

$ which ifort
/usr/bin/which: no ifort in (/share/apps/...
$ module load intel
$ which ifort
/share/apps/intel/Compiler/11.1/069/bin/intel64/ifort
$ which icc
/share/apps/intel/Compiler/11.1/069/bin/intel64/icc

If you want to use the Portland compilers, you must load the pgi module.

[pdavila@u04 ~]$ which pgcc
/usr/bin/which: no pgcc in (/share/apps/...
$ module load pgi
$ which pgcc
/share/apps/pgi/10.3/linux86-64/10.3/bin/pgcc

See module section below for more information.

Modules

The Modules Package is installed on the Pegasus cluster which allows users to quickly switch between different programming environments. The Modules package sets up appropriate environment variables such as PATH, MANPATH, LD_LIBRARY_PATH etc. depending on the module chosen. Table 12 lists commonly used modules commands.

Table 12: Summary of modules package usage

Command Usage Purpose
module avail module avail lists all available modules
module load package module load ifort loads a module e.g., the ifort package
module list module list list modules currently loaded
module switch old new module switch ifort pgi replace old module with new
module purge module purge restores original setting by unloading all modules

The currently available modules as listed by the module avail command is shown below:

[user@Pegasus ~]$ module avail
------------- /share/apps/modules/Modules/versions ----------------
3.2.7

------------- /share/apps/modules/Modules/3.2.7/modulefiles -------
R                  fsl                mihg               openmpi/intel
atlas              gcc/4.4.3          modules            paraview
blast              gdb                mpich2/gcc         pgi
casava             gromacs            mpich2/intel       pvm
clustalw           gromacs-pbs        mpich2/pgi         python-2.6.4
cvs                gsl/gcc            netcdf-3.6.3/gcc   valgrind
eclipse            gsl/intel          netcdf-3.6.3/intel visit
emboss             impute             netcdf-4.0.1/gcc   xmgrace
ensembl            intel              netcdf-4.0.1/intel yasara
erange             java               null
fftw               lsf                openeye
freesurfer         maq                openmpi/gcc

------------ /nethome/sagebase/modulefiles ------------------------
sage

[user@Pegasus ~]$

Typically, modules are loaded as a part of the login by placing module commands in the
.bash_profile/.profile (for bash/sh/ksh users) or .login for (csh/tcsh users).

Assume your Fortran 90/C source program is stored in file ‘program.f/program.c’. These files
are compiled with the command:

Portland Group Fortran:
  pgf90 program.f -o program

Intel Fortran:
  ifort program.f -o program

Portland Group C:
  pgcc   program.c -o program

Intel Group C:
  icc   program.c -o program

The ‘-o program’ option instructs the compiler to name the executable program ‘program’. If the ‘-o’ option is not used, the executable program is called ‘a.out’ by default. If your source program is spread over multiple files, say for example that a subroutine in the file ‘program.f’ calls a subroutine/function that is declared in the file ‘program2.f/program2.c’. Then one can compile in two steps:

Portland Group Fortran:
  pgf90 -c program2.f
  pgf90 program.f program2.o -o program

Intel Fortran:
  ifort -c program2.f
  ifort  program.f program2.o -o program

Portland Group C:
  pgcc -c program2.c
  pgcc program.c program2.o -o program

Intel C:
  icc -c program2.c
  icc program.c program2.o -o program

The ‘-c’ option instructs the compiler to create an object file (program2.o) instead of an executable file. This object file is used at a later step of the compilation. In the last step of the compilation, all object files (or one source file with other object files) are usually linked together to create the executable file. By default, the compiler links these object files together with several libraries that are present on the system and that contain implementations of the language standard (for example Fortran intrinsics like abs, sin, mod, …).

When your code consists of many source files, the venerable Unix make utility can automate the maintenance, update, compilation, and regeneration of object and executable files. The make utility requires by default a file called ‘Makefile’ in which you specify your compiler options, source/object files, and rules for compilation. After you have created the Makefile, you can build your program with the command ‘make’ or ‘gmake’ (GNU make). The /nethome/examples directory contains an example Makefile for GNU make (which we recommend), that can be used to build an example Fortran program. The sample Makefile provides a template and can be edited to suit
your needs Writing Makefiles is not always easy but can simplify your life considerably. Contact user support for help when needed.

Compiling OpenMP Programs

Most options for compiling sequential programs can also be used for compiling parallel OpenMP (or threaded) programs. For example:

Portland Fortran:
  pgf90 -mp program.f

Intel Fortran:
  ifort -openmp program.f

Portland C:
  pgcc -mp program.c

Intel C:
  icc -openmp program.c

Compiling MPI Programs

Two open source MPI (Message Passing Interface) libraries MPICH3/OpenMPI are installed. A
module corresponding to the compiler you wish to use must be loaded in order to set up the
correct environment. MPI Libraries are specific to compiler and to networking protocol.
For example, to use MPICH3 library compiled with the Intel compiler over the Ethernet
networking protocol, which is the only protocol available, the command would be

module load intel openmpi/intel

Once the module is loaded the following commands should be used to compile programs that use MPI code:

Fortran:
  mpif90 program.f

C:
  mpicc  program.c

The ‘mpi…’ commands are wrapper shell scripts that invoke the chosen compiler. Flags are passed by mpif90 script to the back-end compiler, so any of the compiler options can be used on the mpi shell script. By default, the mpi.. scripts pass the proper MPI header files to the compilers. It is therefore not necessary to specify the directory (normally with the ‘-I’ option) where the MPI header file is located. The MPI compilers also link in the MPI libraries by default (and linking with something like ‘-L… -lmpi’ is not needed).

Frequently used Compiler Options

The different compilers accept many options e.g. for debugging, optimization for code size or performance.
Use ‘man pgf90′ or man ifort to get an overview of the options for the Fortran compilers and
‘man pgcc/pgCC’ or ‘man icc’ for the C/C++ compilers for detailed information on the available options.

For basic performance and run-time optimization a good starting point is to compile your code with the options

Portland Group:
	-fastsse 

Intel:
	-O3

Debugging Tools

Portland Linux Cluster Debugger (PGDBG)

You can use PGDBG to debug MPI-parallel and OpenMP thread-parallel programs on Pegasus. PGDBG complements the powerful MPI and OpenMP parallel performance
analysis profiler, PGPROF. Some features of PGDBG:

Control Threads and Processes Separately – The PGDBG cluster debugger provides the ability to separately debug and control OpenMP threads, pthreads, and MPI processes on your Linux cluster. You can Step, Next, Break, Halt, Wait or Continue on threads or processes individually or collectively as a group.

Powerful GUI Windows – PGDBG provides a comprehensive set of GUI windows at your disposal to assist you in this difficult task. Using a single window, you now have precise control over each node of your cluster or each thread of your multiple-CPU SMP node. The Main GUI window displays source code for your F77, F95, C or C++ program and it has buttons for one-touch commands such as Run, Break, Quit, Print, or Stack traceback.

Buttons on the Main window also allow you to select and control individual or collective threads and processes as well as the commands to access them. Input and output is displayed in the Main window or in a separate I/O Window. A Disassembly window shows you how the currently executing high-level source code has been compiled into assembly language. The assembly is interleaved with the source code as well. Assembly language Stepping is enabled as well as breakpoint indicators. Separate Active Process and Active Thread summary windows can be spawned that give you a current status on each active thread or process.

A Register window can be used to display register values in a variety of formats – integer, hex, floating point, etc. Custom Display windows can be used to follow values for important variables or memory regions in your executing program. A separate I/O Window can receive the stdout and stderr from your debug session.

Intel Debuggers

The Intel Debugger is a component of the Intel compilers. It is a full-featured symbolic source code application debugger that helps programmers locate run-time programming errors (i.e., bugs) in their code. It provides extensive debugging support for the following languages: C, C++ and Fortran (including Fortran 90). It also provides a choice of command-line or graphical user interface (GUI). The command-line interface provides DBX-like (default) or GDB (GNU Debugger)-like (optional) command syntax. The GUI supports all Intel Debugger command-line functionality. The main window includes the basic debugging and convenience features, optional windows, various pop-up menus and dialog boxes, and a command-entry prompt. Intel Debugger works with the following compilers Intel C/C++, Fortran GCC, G++ and G77 compilers.

Basic Profiling

gprof is a simple text-based utility that provides procedural-level profiling of serial and parallel codes. This helps users to identify how much time is being spent in subroutines and functions. xprofiler generates a graphical display of the performance, and provides application profiling at the source statement level. Both gprof and xprofiler are very simple to use:

  • Compile the code with the -pg option, in addition to optimization flags. If you use xprofiler, using -g in
    addition to the -pg option will offer profiling at source line level, however the -g will degrade the
    performance and is incompatible with some optimization flags (e.g. inlining).
  • Run the parallel code as usual.
  • Each process will write an additional file to disk named gmon.out.pid
  • Process the output with gprof or xprofiler where exec_file is the name of the compiled executable:
  • gprof exec_file gmon.out.pid

Portability Tips

The following table 13 may help you in porting your code (esp. makefiles) from IBM to LINUX and/or to change compilers on the Linux cluster. Always check options carefully before using it.

Table 13: Summary of compiler option on IBM and Linux Platforms


Task
IBM/XL Intel Portland GNU Comment

Compiler Name
xlf_r ifort pgf77 g77 f77

Fortran 77
xlf90_r ifort pgf90 g95 F90

Fortran 90
xlf95_r ifort pgf90 g95 F95

C
xlc_r icc pgcc gcc cc

C++
xlC_r icpc pgCC g++ C++

list compiler options
man xlf -help -help man g77

Fortran source file format
-qfixed/qfree -fixed/free -M fixed/free -ffixed-form/free-form fixed/free format

Generate 64-bit executables
-q64 (default) (default) -m64 (default)

Generate 32-bit executables
-q32 (default) change path setting -tp k8-32 -m32

Standard optimization options
-O[1,2,3] -O[1,2,3] -O[1,2,3] -O[1,2,3] same options, different meanings (!)

Architecture-specific optimization
-qarch=auto -qtune=auto -qcache=auto -xW -tp p7 -march=em64t

Agressive optimization
-O4 -qhot -ipa -fast -ipo -static -fastsse -ffast-math -funroll-all-loops -malign-double

Local variable Placement in Fortran
-qsave/nosave -save/auto -Msave/nosave -fstatic off/on the stack

OpenMP support
-qsmp=omp:opt -openmp -mp not available

Options for rounding(not equivalent)
-qstrict -mp -mp1 -pc XX see “man pgf90″ for -pc option

Runtime array bounds checking
-C -C -C -fbounds-check

C preprocessor directives
-WF,-D_DILL -D_DILL -D_DILL -D_DILL