Research Article

Teaching Scientific Computing: A Model-Centered Approach to Pipeline and Parallel Programming with C

Listing 2

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <unistd.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include “mpi.h”
#define OUT_FILE “out_mpi.txt”
//number of Monte-Carlo (MC) simulations in each process
#define MC 100
#define N 10000 //number of clients
#define M 5 //number of phases
#define NP 10 //number of MPI processes
void print_results(double results, double time, int lambda) {
FILE fp;
const char DATA_FILE  =  OUT_FILE;
fp  =  fopen(DATA_FILE, “w”);
fprintf(fp, “%d%s%d%s%d%s%dn”, N, “,”, M, “,”, lambda0, “,”, lambda[M]);
time  =  MPI_Wtime() time;
fprintf(fp, “%fn”, time);
for (int i  =  0; i < MC NP 1; i++) fprintf(fp, “%f%s”, results[i], “,”);
fprintf(fp, “%fn”, results[MC NP 1]);
fclose(fp);
}
void process(int numprocs, int myid, gsl_rng ran, int lambda) {
double time  =  MPI_Wtime(); //start time
double tau[MC]  =  {0}; //interarrival time
double st[MC]  =  {0}; //sojourn time
//sojourn time of the previous customer in each phase
double st_prev[M][MC]  =  0;
double results[MC NP]  =  {0}; //overall results
for (int j  =  0; j < MC; j++) {
//init each MC trial
tau[j]  =  gsl_ran_exponential(ran, 1.0/lambda0);
st[j]  =  0;
for (int i  =  0; i < M; i++)
   for (int j  =  0; j < MC; j++) st_prev[i][j]  =  0.;
for (int i  =  0; i < N; i++) {
for (int t  =  0; t < M; t++) {
//recurrent equation
st[j] += gsl_ran_exponential(ran, 1.0/lambda[t + 1]) + fmax(0.0, st_prev[t][j] st[j] tau[j]);
st_prev[t][j]  =  st[j];
MPI_Gather(&st, MC, MPI_DOUBLE, &results, MC, MPI_DOUBLE, 0, MPI_COMM_WORLD);
if (myid  ==  0) {
print_results(&results0, time, &lambda0);
int main(int argc, char argv) {
int namelen;
char processor_name[MPI_MAX_PROCESSOR_NAME];
int numprocs;
int myid;
gsl_rng ran; //random generator
//parameter of the exponential distribution
int lambda[M + 1]  =  {0};
//init mpi
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &(numprocs));
MPI_Comm_rank(MPI_COMM_WORLD, &(myid));
MPI_Get_processor_name(processor_name, &namelen);
//init parameter for the exponential distribution
lambda0  =  30000;
for (int i  =  1; i < M; i++)lambda[i]  =  lambda[i 1] − 25000/M;              
lambda[M]  =  5000;
fprintf(stdout, “Process %d of %d is on %sn”, myid, numprocs, processor_name);
fflush(stdout);
//init random generator
gsl_rng_env_setup();
ran  =  gsl_rng_alloc(gsl_rng_ranlxs2);
gsl_rng_set(ran, (long) (myid) 22);
//process
process(numprocs, myid, ran, lambda);
//finish
gsl_rng_free(ran);
MPI_Finalize();
return (0);
}