Research Article

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

Listing 5

#include <stdio.h>
#include <math.h>
#include <time.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include <omp.h>
#define OUT_FILE “out_omp_pipe.txt”
//total number of Monte-Carlo (MC) simulations
#define MC 10000
#define CMC 100 //chunks per MC axis
#define N 10000 //total number of clients
#define M 5 //total number of phases
#define CN 100 //chunks per clients axis
#define OPENMP 12 //OMP threads
//parameters of exponential distributions
int lambda[M + 1]  =  {0};
//interarrival time for each MC trial
double tau[MC]  =  {0};
double st[MC]  =  {0}; //sojourn time
//sojourn time of the previous client
//each MC trial and each phase
double st_prev[MC][M]  =  0;
//aux variable - each MC chunk flag
int flag[CMC]  =  {0};
//aux variable - each MC chunk counter
int task_counter[CMC]  =  {0};
int main(int argc, char argv) {
time_t t1, t2;
t1  =  time(NULL);
//init exponential distribution parameters
lambda0  =  30000;
for (int i  =  1; i < M; i++)lambda[i]  =  lambda[i 1] 25000/M;            
lambda[M]  =  5000;
gsl_rng ran; //random generator
gsl_rng_env_setup();
ran  =  gsl_rng_alloc(gsl_rng_ranlxs2);
gsl_rng_set(ran, (long) (CN CMC + 10) 22.); //seed
//set interarrival time for each MC trial
for (int i  =  0; i < MC; i++)
tau[i]  =  gsl_ran_exponential(ran, 1.0/lambda0);
gsl_rng_free(ran);
omp_set_num_threads(OPENMP);
#pragma omp parallel //start threads
{
#pragma omp single //one thread to create tasks
{
int i, j, t, c; //aux variables
int v  =  0; //local variable - MC chunk number
int sum  =  0; //local variable - number of tasks
int while_flag  =  1; //var. to stop external while
//dynamic task creation in each of MC chunks
while (while_flag) {
if (!flag[v]) {
flag[v]  =  1;
//create a new task if previous task had finished
#pragma omp task default(none)private(i, j, t, c, ran)
firstprivate(tau, lambda, v, gsl_rng_ranlxs2)
shared(st, st_prev, flag, task_counter)
{
gsl_rng ran; //random generator for this task
gsl_rng_env_setup();
ran  =  gsl_rng_alloc(gsl_rng_ranlxs2);
//seed with the task number
gsl_rng_set(ran, (long)(task_counter[v] + v CN) 22.);
for (j  =  0; j < MC/CMC; j++) {
c  =  j + v (MC/CMC); //MC trial number
for (i  =  0; i < N/CN; i++) {
for (t  =  0; t < M; t++) {
//recurrent equation
st[c] += gsl_ran_exponential(ran, 1.0 /lambda[t + 1]) + fmax(0.0, st_prev[c][t] st[c] tau[c]);
st_prev[c][t]  =  st[c];
}}}
//end of the current task
gsl_rng_free(ran);
task_counter[v]++;
flag[v]  =  0;
}}
//if all tasks of this chunk of Monte-Carlo trials
//had finished -then stop this chunk
//v numbered MC chunk is over
if (task_counter[v] == CN) flag[v]  =  1;
v++;
if (v == CMC) v  =  0; //again a new loop
sum  =  0; //variable to test all chunks
for (i  =  0; i < CMC; i++) sum += task_counter[i];
//if all task had finished - exit while cycle
if (sum == CN CMC) while_flag  =  0;
}}}
//print results
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]);
t2  =  time(NULL);
fprintf(fp, “%fn”, difftime(t2, t1));
for (int j  =  0; j < MC 1; j++) fprintf(fp, “%f%s”, st[j], “,”);
fprintf(fp, “%fn”, st[MC 1]);
fclose(fp);
return (0);
}