Franklin
Quick Start Guide
Access to Franklin
Software
Status & StatsNERSC MOTD Announcements Known Problems Current Queue Look Completed Jobs List Job Stats |
Programming on Franklin: Other Topics
Vendor Documentation on Interlanguage Programming and OpenMPPlease see the PGI User's Guide (PDF), chapter 10, "Inter-Language Calling." This chapter describes inter-language calling conventions for C, C++ and Fortran programs using the PGI compilers. The following sections describe how to call a Fortran function or subroutine from a C or C++ program and how to cal a C or C++ function from a Fortran program. Table 10-1 covers Fortran and C/C++ data type compatibility, and Table 10-2 describe complex type representations. Section 10.8 is an example of a Fortran main program calling a C function, and Section 10.9 is an example of a C main program calling a Fortran function. Section 10.12 is an example of a Fortran main program calling a C++ function, and Section 10.13 is an example of a C++ main program calling a Fortran function. The examples include invocations of the pgcc, pgCC and pgf95 compilers. OpenMP for Fortran is described in Chapter 5 of the PGI User's Guide, and OpenMP for C/C++ is described in Chapter 6. The environment variable OMP_NUM_THREADS is used to control the number of threads in an OpenMP section. Specifying more threads than processors may result in performance degradation. For small, serial codes to be run on the service nodes (e.g., login nodes) with a standard SuSE Linux environment, the examples in the PGI User's Guide mentioned above should be followed.
Fortran Hybrid MPI/OpenMP ExampleThis example is based on a code at the OpenMP.org site. The code "solves a finite difference discretization of Helmholtz equation...using Jacobi iterative method." This code has been modified to use a constant set of input values and to compute ther over-relaxation parameter based on the MPI rank. The code is run with one MPI task per node. With the default one thread per task, the time for the computation is about twice that with two threads per task. Because Franklin nodes only have two cores, allowing more than two threads with one MPI task per node does not improve performance. Fortran Source CodeBatch Job Script% cat runjac #PBS -N jac #PBS -q debug #PBS -l mppwidth=4 #PBS -l mppnppn=1 #PBS -l mppdepth=2 #PBS -l walltime=00:10:00 #PBS -e jacobijob.out #PBS -j eo cd $PBS_O_WORKDIR ftn -o jac -mp=nonuma -Minfo=mp jac-openmp.f setenv OMP_NUM_THREADS 2 time aprun -N 1 -n 4 ./jac Output File
C/MPI Main Calling Fortran SubroutineHere is a full example of a parallel C code using MPI which calls a Fortran subroutine. The Fortran subroutine sets a number of data values based on the MPI task ID. The code is compiled and run using the batch system. C Source Code
% cat cmainmpi.c
#include "mpi.h"
int main(int argc, char* argv[]) {
char bool1, letter1;
int numint1, numint2;
float numfloat1;
double numdoub1;
short numshor1;
extern void forts_();
int myid, numprocs;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
forts_(&bool1, &letter1, &numint1, &numint2, &numfloat1,
&numdoub1, &numshor1, &myid, 1);
printf(" Hello from proc %d of %d; data values: %s %c %d %d %3.1f %.0f %d\n",
myid, numprocs, bool1?"TRUE":"FALSE", letter1, numint1,
numint2, numfloat1, numdoub1, numshor1);
MPI_Finalize();
}
Fortran Source Code
% cat forts.f
subroutine forts(bool1,letter1,numint1,numint2,numfloat1,
& numdoub1,numshor1,numtask)
logical*1 bool1
character letter1
integer numint1, numint2, numtask
double precision numdoub1
real numfloat1
integer*2 numshor1
bool1 = .true.
if (numtask .ne. 2*(numtask/2)) bool1 = .false.
letter1 = "y"
numint1 = 11*numtask
numint2 = numtask
numdoub1 = 902
numfloat1 = 39.6 + (0.1*numtask)
numshor1 = 299
return
end
Batch Job Script% cat runhello #PBS -N hellojob #PBS -q debug #PBS -l mppwidth=4 #PBS -l walltime=00:01:00 #PBS -e hellojob.out #PBS -j eo cd $PBS_O_WORKDIR cc -c cmainmpi.c ftn -o cftnmpi -Mnomain cmainmpi.o forts.f aprun -n 4 ./cftnmpi Output File% cat hellojob.out Warning: no access to tty (Bad file descriptor). Thus no job control in this shell. /opt/xt-pe/2.0.24b/bin/snos64/cc: INFO: linux target is being used /opt/xt-pe/2.0.24b/bin/snos64/ftn: INFO: linux target is being used forts.f: Hello from proc 1 of 4; data values: FALSE y 11 1 39.7 902 299 Hello from proc 0 of 4; data values: TRUE y 0 0 39.6 902 299 Hello from proc 3 of 4; data values: FALSE y 33 3 39.9 902 299 Hello from proc 2 of 4; data values: TRUE y 22 2 39.8 902 299 Application 149009 resources: utime 0, stime 0
C++/MPI Main Calling Fortran SubroutineHere is a full example of a parallel C++ code using MPI which calls a Fortran subroutine. The Fortran subroutine sets a number of data values based on the MPI task ID. The code is compiled and run using the batch system. C++ Source Code
% cat cpmain.C
#include <mpi.h>
#include <iostream>
using namespace std;
extern "C" { extern void forts_(char *,char *,int *,int *,
float *,double *,short *); }
int main (int argc, char* argv[])
{
char bool1, letter1;
int numprocs, myid;
float numfloat1;
double numdoub1;
short numshor1;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
forts_(&bool1,&letter1,&myid,&numprocs,&numfloat1,&numdoub1,&numshor1);
cout << " bool1 = ";
bool1?cout << "TRUE ":cout << "FALSE ";
cout << "; letter1 = " << letter1 << "; myid = " << myid << " numprocs = " << numprocs;
cout << " myid/numprocs = " << numfloat1 << endl;
cout << " numdoub1 = " << numdoub1 << " numshor1 = " << numshor1 << endl;
MPI_Finalize();
}
Fortran Source Code
% cat forts.f
subroutine forts
. (bool1,letter1,numint1,numint2,numfloat1,numdoub1,numshor1)
logical*1 bool1
character letter1
integer numint1, numint2
double precision numdoub1
real numfloat1
integer*2 numshor1
bool1 = .true.
if (numint1 .ne. 2*(numint1/2)) bool1 = .false.
letter1 = "v"
numdoub1 = 902
numfloat1 = (1.0*numint1)/(1.0*numint2)
numshor1 = 299
return
end
Batch Job Script% cat runftncpp #PBS -N ftncpp #PBS -q debug #PBS -l mppwidth=4 #PBS -l walltime=00:01:00 #PBS -e ftncpp.out #PBS -j eo cd $PBS_O_WORKDIR ftn -c forts.f CC -o cppftn forts.o cpmain.C -lpgf90 -lpgf90_rpm1 -lpgf902 -lpgf90rtl -lpgftnrtl aprun -n 4 ./cppftn Output File% cat ftncpp.out Warning: no access to tty (Bad file descriptor). Thus no job control in this shell. /opt/xt-pe/2.0.24b/bin/snos64/ftn: INFO: linux target is being used /opt/xt-pe/2.0.24b/bin/snos64/CC: INFO: linux target is being used bool1 = FALSE ; letter1 = v; myid = 1 numprocs = 4 myid/numprocs = 0.25 numdoub1 = 902 numshor1 = 299 bool1 = TRUE ; letter1 = v; myid = 0 numprocs = 4 myid/numprocs = 0 numdoub1 = 902 numshor1 = 299 bool1 = FALSE ; letter1 = v; myid = 3 numprocs = 4 myid/numprocs = 0.75 numdoub1 = 902 numshor1 = 299 bool1 = TRUE ; letter1 = v; myid = 2 numprocs = 4 myid/numprocs = 0.5 numdoub1 = 902 numshor1 = 299 Application 173761 resources: utime 0, stime 0
C/MPI Main Calling Fortran/OpenMP SubroutineHere is a full example of a parallel C code using MPI which calls a Fortran subroutine. The Fortran subroutine includes a multi-threaded parallel segment and sets a number of data values based on the MPI task ID and number of OpenMP threads. The code is compiled and run using the batch system. The environment variable OMP_NUM_THREADS is used to control the number of threads in the OpenMP segment. Use of OpenMP requires a particular set of options on the Fortran compiler line: ftn -mp=nonuma -Minfo=mp .... The source code for the C main program is the same as shown above. The Fortran routine, the batch script, and the output for the mixed C/Fortran and mixed MPI/OpenMP example are shown below. Fortran Source Code
% cat forts.f
subroutine forts(bool1,letter1,numint1,numint2,numfloat1,
& numdoub1,numshor1,numtask)
logical*1 bool1
character letter1
integer numint1, numint2, numtask
integer nthreads, tid
integer OMP_GET_NUM_THREADS, OMP_GET_THREAD_NUM
double precision numdoub1
real numfloat1
integer*2 numshor1
bool1 = .true.
if (numtask .ne. 2*(numtask/2)) bool1 = .false.
letter1 = "y"
numint1 = 11*numtask
numint2 = numtask
numdoub1 = 902
numfloat1 = 39.6 + (0.1*numtask)
!$OMP PARALLEL PRIVATE(nthreads, tid)
tid = OMP_GET_THREAD_NUM()
IF (tid .EQ. 0) THEN
nthreads = OMP_GET_NUM_THREADS()
numshor1 = nthreads
ENDIF
!$OMP END PARALLEL
return
end
Batch Job Script% cat runhello #PBS -N hellojob #PBS -q debug #PBS -l mppwidth=2 #PBS -l mppnppn=1 #PBS -l mppdepth=2 #PBS -l walltime=00:05:00 #PBS -e hellojob.out #PBS -j eo cd $PBS_O_WORKDIR cc -c cmainmpi.c ftn -o cftnmpi -Mnomain -mp=nonuma -Minfo=mp cmainmpi.o forts.f setenv OMP_NUM_THREADS 2 aprun -n 2 -N 1 ./cftnmpi Output File
% cat hellojob.out
Warning: no access to tty (Bad file descriptor).
Thus no job control in this shell.
/opt/xt-pe/2.0.44a2/bin/snos64/cc: INFO: linux target is being used
/opt/xt-pe/2.0.44a2/bin/snos64/ftn: INFO: linux target is being used
forts.f:
forts:
19, Parallel region activated
24, Parallel region terminated
Hello from proc 0 of 2; data values: TRUE y 0 0 39.6 902 2
Hello from proc 1 of 2; data values: FALSE y 11 1 39.7 902 2
Application 4904044 resources: utime 0, stime 5
|
![]() |
Page last modified: Thu, 22 May 2008 21:39:08 GMT Page URL: http://www.nersc.gov/nusers/resources/franklin/programming/interlanguage.php Web contact: webmaster@nersc.gov Computing questions: consult@nersc.gov Privacy and Security Notice |
![]() |