|
From: <mar...@us...> - 2008-02-04 04:32:39
|
Revision: 85
http://gridsim.svn.sourceforge.net/gridsim/?rev=85&view=rev
Author: marcos_dias
Date: 2008-02-03 20:32:43 -0800 (Sun, 03 Feb 2008)
Log Message:
-----------
This update includes a workload class that generates gridlets according to Lublin and Feitelson's workload model. The model is described in:
Uri Lublin and Dror G. Feitelson, The Workload on Parallel Supercomputers: Modeling the Characteristics of Rigid Jobs. J. Parallel & Distributed Comput. 63(11), pp. 1105-1122, Nov 2003.
This update also includes a short example on how to use the Lubin99Workload class.
Added Paths:
-----------
branches/gridsim4.0-branch3/examples/examples/workload/parallel/LublinWorkloadExample01.java
branches/gridsim4.0-branch3/source/gridsim/turbo/Lublin99Workload.java
Added: branches/gridsim4.0-branch3/examples/examples/workload/parallel/LublinWorkloadExample01.java
===================================================================
--- branches/gridsim4.0-branch3/examples/examples/workload/parallel/LublinWorkloadExample01.java (rev 0)
+++ branches/gridsim4.0-branch3/examples/examples/workload/parallel/LublinWorkloadExample01.java 2008-02-04 04:32:43 UTC (rev 85)
@@ -0,0 +1,182 @@
+
+package examples.workload.parallel;
+
+import gridsim.GridResource;
+import gridsim.GridSim;
+import gridsim.Machine;
+import gridsim.MachineList;
+import gridsim.turbo.Lublin99Workload;
+import gridsim.turbo.TResourceCharacteristics;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.LinkedList;
+import java.util.Random;
+
+/**
+ * Test Driver class for this example
+ */
+public class LublinWorkloadExample01
+{
+ /**
+ * Creates main() to run this example
+ */
+ public static void main(String[] args)
+ {
+ long startTime = System.currentTimeMillis();
+
+ try {
+
+ //////////////////////////////////////////
+ // Get the workload to be used The format should be:
+ // ASCII text, gzip or zip.
+
+ ArrayList<GridResource> resources = new ArrayList<GridResource>();
+
+ //////////////////////////////////////////
+ // Initialize the GridSim package. It should be called
+ // before creating any entities. We can't run this example without
+ // initializing GridSim first. We will get run-time exception
+ // error.
+
+ // number of grid user entities + any Workload entities.
+ int num_user = 1;
+ Calendar calendar = Calendar.getInstance();
+ boolean trace_flag = false; // mean trace GridSim events
+
+ long seed = 1062348;
+
+ // Initialize the GridSim package without any statistical
+ // functionalities. Hence, no GridSim_stat.txt file is created.
+ System.out.println("Initializing GridSim package");
+ GridSim.init(num_user, calendar, trace_flag);
+
+ //////////////////////////////////////////
+ // Creates one or more GridResource entities
+ int totalResource = 1; // total number of Grid resources
+ int rating = 377; // rating of each PE in MIPS
+ int totalPE = 9; // total number of PEs for each Machine
+ int totalMachine = 128; // total number of Machines
+ int i = 0;
+
+ String[] resArray = new String[totalResource];
+ for (i = 0; i < totalResource; i++) {
+ String resName = "Res_" + i;
+ GridResource resource = createGridResource(resName, rating, totalMachine, totalPE);
+ resources.add(resource);
+
+ // add a resource name into an array
+ resArray[i] = resName;
+ }
+
+ //////////////////////////////////////////
+ // Creates one Workload trace entity.
+
+ int resID = 0;
+ Random r = new Random();
+ resID = r.nextInt(totalResource);
+ Lublin99Workload workload =
+ new Lublin99Workload("Load_1", resArray[resID], rating, false, seed);
+
+ // uHi is going to contain log2 of the maximum number of PEs that a
+ // parallel job can require
+ double uHi = Math.log(totalPE * totalMachine) / Math.log(2d);
+ double uMed = uHi-2.5;
+
+ workload.setParallelJobProbabilities(Lublin99Workload.BATCH,
+ Lublin99Workload.ULOW_BATCH, uMed, uHi,
+ Lublin99Workload.UPROB_BATCH);
+
+ // sets the workload to create 1000 jobs
+ workload.setNumJobs(1000);
+
+ //////////////////////////////////////////
+ // Starts the simulation in debug mode
+// GridSim.startGridSimulation(true);
+
+ // Start the simulation in normal mode
+ GridSim.startGridSimulation();
+
+ //////////////////////////////////////////
+ // Final step: Prints the Gridlets when simulation is over
+ long finishTime = System.currentTimeMillis();
+ System.out.println("The simulation took " + (finishTime - startTime) + " milliseconds");
+
+ // prints the Gridlets inside a Workload entity
+ // workload.printGridletList(trace_flag);
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Creates one Grid resource. A Grid resource contains one or more
+ * Machines. Similarly, a Machine contains one or more PEs (Processing
+ * Elements or CPUs).
+ * @param name a Grid Resource name
+ * @param peRating rating of each PE
+ * @param totalMachine total number of Machines
+ * @param totalPE total number of PEs for each Machine
+ */
+ private static GridResource createGridResource(String name, int peRating,
+ int totalMachine, int totalPE)
+ {
+
+ //////////////////////////////////////////
+ // Here are the steps needed to create a Grid resource:
+ // 1. We need to create an object of MachineList to store one or more
+ // Machines
+ MachineList mList = new MachineList();
+
+ for (int i = 0; i < totalMachine; i++)
+ {
+ //////////////////////////////////////////
+ // 4. Create one Machine with its id and list of PEs or CPUs
+ mList.add( new Machine(i, totalPE, peRating) );
+ }
+
+ //////////////////////////////////////////
+ // 5. Create a ResourceCharacteristics object that stores the
+ // properties of a Grid resource: architecture, OS, list of
+ // Machines, allocation policy: time- or space-shared, time zone
+ // and its price (G$/PE time unit).
+ String arch = "Sun Ultra"; // system architecture
+ String os = "Solaris"; // operating system
+ double time_zone = 0.0; // time zone this resource located
+ double cost = 3.0; // the cost of using this resource
+
+ TResourceCharacteristics resConfig = new TResourceCharacteristics(
+ arch, os, mList, TResourceCharacteristics.CB_PARALLEL_SPACE_SHARED,
+ time_zone, cost);
+
+ //////////////////////////////////////////
+ // 6. Finally, we need to create a GridResource object.
+ double baud_rate = 10000.0; // communication speed
+ long seed = 11L*13*17*19*23+1;
+ double peakLoad = 0.0; // the resource load during peak hour
+ double offPeakLoad = 0.0; // the resource load during off-peak hr
+ double holidayLoad = 0.0; // the resource load during holiday
+
+ // incorporates weekends so the grid resource is on 7 days a week
+ LinkedList weekends = new LinkedList();
+ weekends.add(new Integer(Calendar.SATURDAY));
+ weekends.add(new Integer(Calendar.SUNDAY));
+
+ // incorporates holidays. However, no holidays are set in this example
+ LinkedList holidays = new LinkedList();
+ GridResource gridRes = null;
+ try {
+ gridRes = new GridResource(name, baud_rate, seed,
+ resConfig, peakLoad, offPeakLoad, holidayLoad, weekends,
+ holidays);
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ System.out.println("Creates one Grid resource with name = " + name);
+ return gridRes;
+ }
+} // end class
+
Added: branches/gridsim4.0-branch3/source/gridsim/turbo/Lublin99Workload.java
===================================================================
--- branches/gridsim4.0-branch3/source/gridsim/turbo/Lublin99Workload.java (rev 0)
+++ branches/gridsim4.0-branch3/source/gridsim/turbo/Lublin99Workload.java 2008-02-04 04:32:43 UTC (rev 85)
@@ -0,0 +1,1422 @@
+/*
+ * Title: GridSim Toolkit
+ * Description: GridSim (Grid Simulation) Toolkit for Modeling and Simulation
+ * of Parallel and Distributed Systems such as Clusters and Grids
+ * Licence: GPL - http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+package gridsim.turbo;
+
+import eduni.simjava.*;
+import gridsim.*;
+import gridsim.net.*;
+import java.util.*;
+
+/**
+ * The main purpose of this class is to create a realistic simulation
+ * environment where your jobs or Gridlets are competing with others.
+ * In other words, the grid resource might not be available at certain times.
+ * In addition, the arrival time of jobs are also captured in the workload model.
+ * <p>
+ * This class is responsible for creating jobs according to the workload model
+ * generator presented by Lublin and Feitelson and send Gridlets to only
+ * <tt>one</tt> destinated resource. <br>
+ * <b>NOTE:</b>
+ * <ul>
+ * <li> This class can be classified as <b>one grid user entity</b>.
+ * Hence, you need to incorporate this entity into <tt>numUser</tt>
+ * during {@link gridsim.GridSim#init(int, Calendar, boolean)}
+ * <li> If you need to use multiple trace files to submit Gridlets to
+ * same or different resources, then you need to create multiple
+ * instances of this class <tt>each with a unique entity name</tt>.
+ * <li> If you are running an experiment using the network extension,
+ * i.e. the gridsim.net package, then you need to use
+ * {@link #Lublin99Workload(String, double, double, int, String, String, int)}
+ * instead.
+ * <li> The default job file size for sending to and receiving from
+ * a resource is {@link gridsim.net.Link#DEFAULT_MTU}.
+ * However, you can specify
+ * the file size by using {@link #setGridletFileSize(int)}.
+ * <li> A job run time is only for 1 PE <tt>not</tt> the total number of
+ * allocated PEs.
+ * Therefore, a Gridlet length is also calculated for 1 PE.<br>
+ * For example, job #1 in the trace has a run time of 100 seconds
+ * for 2 processors. This means each processor runs
+ * job #1 for 100 seconds, if the processors have the same
+ * specification.
+ * </ul>
+ * <p>
+ * For more information on the workload model, please read the following paper: <br>
+ * Uri Lublin and Dror G. Feitelson, The Workload on Parallel Supercomputers:
+ * Modeling the Characteristics of Rigid Jobs. J. Parallel & Distributed Comput. 63(11),
+ * pp. 1105-1122, Nov 2003.
+ * <br>
+ *
+ * @see gridsim.GridSim#init(int, Calendar, boolean)
+ * @author Marcos Dias de Assuncao
+ * @since GridSim Turbo Alpha 0.1
+ * @invariant $none
+ */
+public class Lublin99Workload extends GridSim {
+
+ private String resName_; // resource name
+ private int resID_; // resource ID
+ private int rating_; // a PE rating
+ private int gridletID_; // gridletID
+ private int size_; // job size for sending it through a network
+ private ArrayList list_; // a list for getting all the Gridlets
+ private Random random_ = null; // the number generator to be used
+
+ // Log PI for lgamma method
+ private static final double LOGPI = 1.14472988584940017414;
+ protected final int INTERVAL = 10; // number of intervals
+
+ // ------------ CONSTANTS USED BY THE WORKLOAD MODEL --------------
+
+ // number of jobs generated by this entity
+ private static final int SIZE = 1000;
+
+ // no more than two days =exp(12) for runtime
+ private static final int TOO_MUCH_TIME = 12;
+
+ // no more than 5 days =exp(13) for arrivetime
+ private static final int TOO_MUCH_ARRIVE_TIME = 13;
+
+ // number of buckets in one day -- 48 half hours
+ private static final int BUCKETS = 48;
+
+ // we now define (calculate) how many seconds are in one hour,day,bucket
+ private static final int SECONDS_IN_HOUR = 3600;
+ private static final int SECONDS_IN_DAY = (24*SECONDS_IN_HOUR);
+ private static final int SECONDS_IN_BUCKET = (SECONDS_IN_DAY/BUCKETS);
+ private static final int HOURS_IN_DAY = 24;
+
+ // The hours of the day are being moved cyclically.
+ // instead of [0,23] make the day [CYCLIC_DAY_START,(24+CYCLIC_DAY_START-1)]
+ private static final int CYCLIC_DAY_START = 11;
+
+ // max iterations number for the iterative calculations
+ private static final int ITER_MAX = 1000;
+
+ // small epsilon for the iterative algorithm's accuracy
+ private static final double EPS = 1E-10;
+
+ /** Represents interactive jobs */
+ public static final int INTERACTIVE = 0;
+
+ /** Represents batch jobs */
+ public static final int BATCH = 1;
+
+ // ------------------- MODEL DEFAULT PARAMETERS -----------------------
+
+ /* The parameters for number of nodes:
+ * serial_prob is the proportion of the serial jobs
+ * pow2_prob is the proportion of the jobs with power 2 number of nodes
+ * ULow , UMed , UHi and Uprob are the parameters for the two-stage-uniform
+ * which is used to calculate the number of nodes for parallel jobs.
+ * ULow is the log2 of the minimal size of job in the system (you can add or
+ * subtract 0.2 to give less/more probability to the minimal size) .
+ * UHi is the log2 of the maximal size of a job in the system (system's size)
+ * UMed should be in [UHi-1.5 , UHi-3.5]
+ * Uprob should be in [0.7 - 0.95]
+ */
+ public static final double SERIAL_PROB_BATCH = 0.2927;
+ public static final double POW2_PROB_BATCH = 0.6686;
+ public static final double ULOW_BATCH = 1.2f; // smallest parallel batch job has 2 nodes
+ public static final double UMED_BATCH = 5;
+ public static final double UHI_BATCH = 7; // biggest batch job has 128 nodes
+ public static final double UPROB_BATCH = 0.875;
+
+ public static final double SERIAL_PROB_ACTIVE = 0.1541;
+ public static final double POW2_PROB_ACTIVE = 0.625;
+ public static final double ULOW_ACTIVE = 1; // smallest interactive parallel job has 2 nodes
+ public static final double UMED_ACTIVE = 3;
+ public static final double UHI_ACTIVE = 5.5f; // biggest interactive job has 45 nodes
+ public static final double UPROB_ACTIVE = 0.705;
+
+ /* The parameters for the running time
+ * The running time is computed using hyper-gamma distribution.
+ * The parameters a1,b1,a2,b2 are the parameters of the two gamma distributions
+ * The p parameter of the hyper-gamma distribution is calculated as a straight
+ * (linear) line p = pa*nodes + pb.
+ * 'nodes' will be calculated in the program, here we defined the 'pa','pb'
+ * parameters.
+ */
+ public static final double A1_BATCH = 6.57;
+ public static final double B1_BATCH = 0.823;
+ public static final double A2_BATCH = 639.1;
+ public static final double B2_BATCH = 0.0156;
+ public static final double PA_BATCH = -0.003;
+ public static final double PB_BATCH = 0.6986;
+
+ public static final double A1_ACTIVE = 3.8351;
+ public static final double B1_ACTIVE = 0.6605;
+ public static final double A2_ACTIVE = 7.073;
+ public static final double B2_ACTIVE = 0.6856;
+ public static final double PA_ACTIVE = -0.0118;
+ public static final double PB_ACTIVE = 0.9156;
+
+
+ /* The parameters for the inter-arrival time
+ * The inter-arriving time is calculated using two gamma distributions.
+ * gamma(aarr,barr) represents the inter_arrival time for the rush hours. It is
+ * independent on the hour the job arrived at.
+ * The cdf of gamma(bnum,anum) represents the proportion of number of jobs which
+ * arrived at each time interval (bucket).
+ * The inter-arrival time is calculated using both gammas
+ * Since gamma(aarr,barr) represents the arrive-time at the rush time , we use
+ * a constant ,ARAR (Arrive-Rush-All-Ratio), to set the alpha parameter (the new
+ * aarr) so it will represent the arrive-time at all hours of the day.
+ */
+ public static final double AARR_BATCH = 6.0415;
+ public static final double BARR_BATCH = 0.8531;
+ public static final double ANUM_BATCH = 6.1271;
+ public static final double BNUM_BATCH = 5.2740;
+ public static final double ARAR_BATCH = 1.0519;
+
+ public static final double AARR_ACTIVE = 6.5510;
+ public static final double BARR_ACTIVE = 0.6621;
+ public static final double ANUM_ACTIVE = 8.9186;
+ public static final double BNUM_ACTIVE = 3.6680;
+ public static final double ARAR_ACTIVE = 0.9797;
+
+ /*
+ * Here are the model's parameters for typeless data (no batch nor interactive)
+ * We use those parameters when INCLUDE_JOBS_TYPE is off (0)
+ */
+ public static final double SERIAL_PROB = 0.244;
+ public static final double POW2_PROB = 0.576;
+ public static final double ULOW = 0.8f; // The smallest parallel job is 2 nodes
+ public static final double UMED = 4.5f;
+ public static final double UHI = 7f; // SYSTEM SIZE is 2^UHI == 128
+ public static final double UPROB = 0.86;
+
+ public static final double A1 = 4.2;
+ public static final double B1 = 0.94;
+ public static final double A2 = 312;
+ public static final double B2 = 0.03;
+ public static final double PA = -0.0054;
+ public static final double PB = 0.78;
+
+ public static final double AARR = 10.2303;
+ public static final double BARR = 0.4871;
+ public static final double ANUM = 8.1737;
+ public static final double BNUM = 3.9631;
+ public static final double ARAR = 1.0225;
+
+ // start the simulation at midnight (hour 0)
+ private static final int START = 0;
+
+ // -------------- Variable dependent attributes --------------------
+
+ // The workload duration, that is, for how long the workload can
+ // go creating and submitting gridlets. numJobs keeps the number of
+ // jobs that this workload should generate. The workload will
+ // finish when it apporaches whichever of these values
+ private double workloadDuration_;
+ private int numJobs_;
+
+ private double[] a1, b1, a2, b2, pa, pb;
+ private double[] aarr, barr, anum, bnum;
+ private double[] serialProb, pow2Prob, uLow, uMed, uHi, uProb;
+
+ // the appropriate weight (points) for each
+ // time-interval used in the arrive function
+ double[][] weights = new double[2][BUCKETS];
+
+ /* useJobType us if we should differ between batch and interactive
+ * jobs or not. If the value is true, then we use both batch and interactive
+ * values for the parameters and the output sample includes both interactive
+ * and batch jobs. We choose the type of the job to be the type whose next
+ * job arrives to the system first (smaller next arrival time).
+ * If the value is false, then we use the "whole sample" parameters. The output
+ * sample includes jobs from the same type (arbitrarily we choose batch).
+ * We force the type to be interactive by setting the next arrival time of
+ * interactive jobs to be Long.MAX_VALUE -- always larger than the batchs's
+ * next arrival. */
+ private boolean useJobType_ = true;
+
+ /* current time interval (the bucket's number) */
+ private int[] current_;
+
+ /* the number of seconds from the beginning of the simulation*/
+ private long[] timeFromBegin_;
+
+ /**
+ * Create a new Workload object <b>without</b> using the network extension.
+ * This means this entity directly sends Gridlets to a destination resource
+ * without going through a wired network. <br>
+ * <tt>NOTE:</tt>
+ * You can not use this constructor in an experiment that uses a wired
+ * network topology.
+ * @param name this entity name
+ * @param resourceName the resource name
+ * @param rating the resource's PE rating
+ * @param useJobType useJobType us if we should differ between batch and interactive
+ * jobs or not. If the value is <tt>true</tt>, then we use both batch and interactive
+ * values for the parameters and the output sample includes both interactive
+ * and batch jobs. We choose the type of the job to be the type whose next
+ * job arrives to the system first (smaller next arrival time).
+ * If the value is <tt>false</tt>, then we use the "whole sample" parameters. The output
+ * sample includes jobs from the same type (arbitrarily we choose batch).
+ * We force the type to be interactive by setting the next arrival time of
+ * interactive jobs to be <tt>Long.MAX_VALUE</tt> -- always larger than the batchs's
+ * next arrival.
+ * @param seed seed used by the random number generator
+ * @throws Exception This happens when creating this entity before
+ * initialising GridSim package or this entity name is
+ * <tt>null</tt> or empty
+ * @throws ParameterException This happens for the following conditions:
+ * <ul>
+ * <li>the entity name is null or empty
+ * <li>the resource entity name is null or empty
+ * <li>the resource PE rating <= 0
+ * </ul>
+ * @pre name != null
+ * @pre fileName != nullb2
+ * @pre resourceName != null
+ * @pre rating > 0
+ * @post $none
+ */
+ public Lublin99Workload(String name, String resourceName,
+ int rating, boolean useJobType, long seed)
+ throws ParameterException, Exception {
+ super(name, GridSimTags.DEFAULT_BAUD_RATE);
+
+ // check the input parameters first
+ String msg = name + "(): Error - ";
+ if (resourceName == null || resourceName.length() == 0) {
+ throw new ParameterException(msg + "invalid resource name.");
+ }
+ else if (rating <= 0) {
+ throw new ParameterException(msg+"resource PE rating must be > 0.");
+ }
+
+ System.out.println(name + ": Creating a workload object ...");
+ init(resourceName, rating, useJobType, seed);
+ }
+
+ /**
+ * Create a new Workload object <b>with</b> the network extension.
+ * This means this entity directly sends Gridlets to a destination resourceb2
+ * through a link. The link is automatically created by this constructor.
+ *
+ * @param name this entity name
+ * @param baudRate baud rate of this link (bits/s)
+ * @param propDelay Propagation delay of the Link in milliseconds
+ * @param MTU Maximum Transmission Unit of the Link in bytes.
+ * Packets which are larger than the MTU should be split
+ * up into MTU size units.
+ * For example, a 1024 byte packet trying to cross a 576
+ * byte MTU link should get split into 2 packets of 576
+ * bytes and 448 bytes.
+ * @param resourceName the resource name
+ * @param rating the resource's PE rating
+ * @param useJobType useJobType us if we should differ between batch and interactive
+ * jobs or not. If the value is <tt>true</tt>, then we use both batch and interactive
+ * values for the parameters and the output sample includes both interactive
+ * and batch jobs. We choose the type of the job to be the type whose next
+ * job arrives to the system first (smaller next arrival time).
+ * If the value is <tt>false</tt>, then we use the "whole sample" parameters. The output
+ * sample includes jobs from the same type (arbitrarily we choose batch).
+ * We force the type to be interactive by setting the next arrival time of
+ * interactive jobs to be <tt>Long.MAX_VALUE</tt> -- always larger than the batchs's
+ * next arrival.
+ * @param seed seed used by the random number generator
+ * @throws Exception This happens when creating this entity before
+ * initialising GridSim package or this entity name is
+ * <tt>null</tt> or empty
+ * @throws ParameterException This happens for the following conditions:
+ * <ul>
+ * <li>the entity name is null or empty
+ * <li> baudRate <= 0
+ * <li> propDelay <= 0
+ * <li> MTU <= 0
+ * <li>the resource entity name is null or empty
+ * <li>the resource PE rating <= 0
+ * </ul>
+ * @pre name != null
+ * @pre baudRate > 0
+ * @pre propDelay > 0
+ * @pre MTU > 0
+ * @pre fileName != null
+ * @pre resourceName != null
+ * @pre rating > 0
+ * @post $none
+ */
+ public Lublin99Workload(String name, double baudRate, double propDelay, int MTU,
+ String resourceName, int rating, boolean useJobType, long seed)
+ throws ParameterException, Exception {
+ super( name, new SimpleLink(name+"_link", baudRate, propDelay, MTU) );
+
+ // check the input parameters first
+ String msg = name + "(): Error - ";
+ if (resourceName == null || resourceName.length() == 0) {
+ throw new ParameterException(msg + "invalid resource name.");
+ }
+ else if (rating <= 0) {
+ throw new ParameterException(msg+"resource PE rating must be > 0.");
+ }
+
+ System.out.println(name + ": Creating a workload object ...");
+ init(resourceName, rating, useJobType, seed);
+ }
+
+ /**
+ * Create a new Workload object <b>with</b> the network extension.
+ * This means this entity directly sends Gridlets to a destination resource
+ * through a link. The link is automatically created by this constructor.
+ *
+ * @param name this entity name
+ * @param link the link that will be used to connect this Workload
+ * to another entity or a Router.
+ * @param resourceName the resource name
+ * @param rating the resource's PE rating
+ * @param useJobType useJobType us if we should differ between batch and interactive
+ * jobs or not. If the value is <tt>true</tt>, then we use both batch and interactive
+ * values for the parameters and the output sample includes both interactive
+ * and batch jobs. We choose the type of the job to be the type whose next
+ * job arrives to the system first (smaller next arrival time).
+ * If the value is <tt>false</tt>, then we use the "whole sample" parameters. The output
+ * sample includes jobs from the same type (arbitrarily we choose batch).
+ * We force the type to be interactive by setting the next arrival time of
+ * interactive jobs to be <tt>Long.MAX_VALUE</tt> -- always larger than the batchs's
+ * next arrival.
+ * @param seed seed used by the random number generator
+ * @throws Exception This happens when creating this entity before
+ * initialising GridSim package or this entity name is
+ * <tt>null</tt> or empty
+ * @throws ParameterException This happens for the following conditions:
+ * <ul>
+ * <li>the entity name is null or empty
+ * <li>the link is empty
+ * <li>the resource entity name is null or empty
+ * <li>the resource PE rating <= 0
+ * </ul>
+ * @pre name != null
+ * @pre link != null
+ * @pre fileName != null
+ * @pre resourceName != null
+ * @pre rating > 0
+ * @post $none
+ */
+ public Lublin99Workload(String name, Link link,
+ String resourceName, int rating, boolean useJobType, long seed)
+ throws ParameterException, Exception {
+ super(name, link);
+
+ // check the input parameters first
+ String msg = name + "(): Error - ";
+ if (resourceName == null || resourceName.length() == 0) {
+ throw new ParameterException(msg + "invalid resource name.");
+ }
+ else if (rating <= 0) {
+ throw new ParameterException(msg+"resource PE rating must be > 0.");
+ }
+
+ System.out.println(name + ": Creating a workload object ...");
+ init(resourceName, rating, useJobType, seed);
+ }
+
+ /**
+ * Initialises all the attributes
+ * @param fileName trace file name
+ * @param resourceName resource entity name
+ * @param rating resource PE rating
+ * @param useJobType <tt>true</tt> whether the workload should generate
+ * both interactive and batch jobs; <tt>false</tt> if the workload
+ * should generate only batch jobs.
+ * @pre $none
+ * @post $none
+ */
+ private void init(String resourceName, int rating,
+ boolean useJobType, long seed) {
+
+ useJobType_ = useJobType;
+ resName_ = resourceName;
+ resID_ = GridSim.getEntityId(resName_);
+ rating_ = rating;
+ gridletID_ = 1; // starts at 1 to make it the same as in a trace file
+ list_ = null;
+ size_ = Link.DEFAULT_MTU;
+ random_ = new Random(seed);
+ workloadDuration_ = Double.MAX_VALUE;
+ numJobs_ = 1000;
+
+ a1 = new double[2]; b1 = new double[2];
+ a2 = new double[2]; b2 = new double[2];
+ pa = new double[2]; pb = new double[2];
+ aarr = new double[2]; barr = new double[2];
+ anum = new double[2]; bnum = new double[2];
+ serialProb = new double[2]; pow2Prob = new double[2];
+ uLow = new double[2]; uMed = new double[2];
+ uHi = new double[2]; uProb = new double[2];
+ current_ = new int[2];
+ timeFromBegin_ = new long[2];
+
+ // separate batch from interactive
+ if (useJobType_) {
+ serialProb[BATCH] = SERIAL_PROB_BATCH;
+ pow2Prob[BATCH] = POW2_PROB_BATCH;
+ uLow[BATCH] = ULOW_BATCH;
+ uMed[BATCH] = UMED_BATCH;
+ uHi[BATCH] = UHI_BATCH;
+ uProb[BATCH] = UPROB_BATCH;
+
+ serialProb[INTERACTIVE] = SERIAL_PROB_ACTIVE;
+ pow2Prob[INTERACTIVE] = POW2_PROB_ACTIVE;
+ uLow[INTERACTIVE] = ULOW_ACTIVE;
+ uMed[INTERACTIVE] = UMED_ACTIVE;
+ uHi[INTERACTIVE] = UHI_ACTIVE;
+ uProb[INTERACTIVE] = UPROB_ACTIVE;
+
+ a1[BATCH] = A1_BATCH; b1[BATCH] = B1_BATCH;
+ a2[BATCH] = A2_BATCH; b2[BATCH] = B2_BATCH;
+ pa[BATCH] = PA_BATCH; pb[BATCH] = PB_BATCH;
+
+ a1[INTERACTIVE] = A1_ACTIVE; b1[INTERACTIVE] = B1_ACTIVE;
+ a2[INTERACTIVE] = A2_ACTIVE; b2[INTERACTIVE] = B2_ACTIVE;
+ pa[INTERACTIVE] = PA_ACTIVE; pb[INTERACTIVE] = PB_ACTIVE;
+
+ aarr[BATCH] = AARR_BATCH*ARAR_BATCH; barr[BATCH] = BARR_BATCH;
+ anum[BATCH] = ANUM_BATCH; bnum[BATCH] = BNUM_BATCH;
+
+ aarr[INTERACTIVE] = AARR_ACTIVE*ARAR_ACTIVE;
+ barr[INTERACTIVE] = BARR_ACTIVE;
+ anum[INTERACTIVE] = ANUM_ACTIVE;
+ bnum[INTERACTIVE] = BNUM_ACTIVE;
+ }
+ else {
+ // whole sample -- make all batch jobs
+ serialProb[BATCH] = serialProb[INTERACTIVE] = SERIAL_PROB;
+ pow2Prob[BATCH] = pow2Prob[INTERACTIVE] = POW2_PROB;
+ uLow[BATCH] = uLow[INTERACTIVE] = ULOW ;
+ uMed[BATCH] = uMed[INTERACTIVE] = UMED ;
+ uHi[BATCH] = uHi[INTERACTIVE] = UHI ;
+ uProb[BATCH] = uProb[INTERACTIVE] = UPROB ;
+
+ a1[BATCH] = a1[INTERACTIVE] = A1;
+ b1[BATCH] = b1[INTERACTIVE] = B1;
+ a2[BATCH] = a2[INTERACTIVE] = A2;
+ b2[BATCH] = b2[INTERACTIVE] = B2;
+ pa[BATCH] = pa[INTERACTIVE] = PA;
+ pb[BATCH] = pb[INTERACTIVE] = PB;
+
+ aarr[BATCH] = aarr[INTERACTIVE] = AARR * ARAR;
+ barr[BATCH] = barr[INTERACTIVE] = BARR;
+ anum[BATCH] = anum[INTERACTIVE] = ANUM;
+ bnum[BATCH] = bnum[INTERACTIVE] = BNUM;
+ }
+
+ if ( ! useJobType_ ) // make all jobs batch
+ timeFromBegin_[INTERACTIVE] = Long.MAX_VALUE;
+ }
+
+ /**
+ * Sets the probability for serial jobs
+ * @param jobType the type of jobs
+ * @param prob the probability
+ * @return <tt>true</tt> if the probability has been set, or
+ * <tt>false</tt> otherwise.
+ * @see #INTERACTIVE
+ * @see #BATCH
+ */
+ public boolean setSerialProbability(int jobType, double prob) {
+ if(jobType > BATCH || jobType < INTERACTIVE)
+ return false;
+
+ if(useJobType_)
+ serialProb[jobType] = prob;
+ else
+ serialProb[INTERACTIVE] = serialProb[BATCH] = prob;
+
+ return true;
+ }
+
+ /**
+ * Sets the probability for power of two jobs
+ * @param jobType the type of jobs
+ * @param prob the probability
+ * @return <tt>true</tt> if the probability has been set, or
+ * <tt>false</tt> otherwise.
+ * @see #INTERACTIVE
+ * @see #BATCH
+ */
+ public boolean setPower2Probability(int jobType, double prob) {
+ if(jobType > BATCH || jobType < INTERACTIVE)
+ return false;
+
+ if(useJobType_)
+ pow2Prob[jobType] = prob;
+ else
+ pow2Prob[INTERACTIVE] = pow2Prob[BATCH] = prob;
+
+ return true;
+ }
+
+ /**
+ * Sets the parameters for the two-stage-uniform
+ * which is used to calculate the number of nodes for parallel jobs.
+ * @param jobType the type of jobs
+ * @param uLow is the log2 of the minimal size of job in the system (you can add or
+ * subtract 0.2 to give less/more probability to the minimal size).
+ * @param uMed should be in [uHi-1.5 , uHi-3.5]
+ * @param uHi is the log2 of the maximal size of a job in the system (system's size)
+ * @param uProb should be in [0.7 - 0.95]
+ * @return <tt>true</tt> if the probabilities have been set, or
+ * <tt>false</tt> otherwise.b2
+ * @see #INTERACTIVE
+ * @see #BATCH
+ */
+ public boolean setParallelJobProbabilities(int jobType,
+ double uLow, double uMed, double uHi, double uProb) {
+ if(jobType > BATCH || jobType < INTERACTIVE)
+ return false;
+ else if (uLow > uHi)
+ return false;
+ else if (uMed > uHi-1.5 || uMed < uHi-3.5)
+ return false;
+ else if(uProb < 0.7 || uProb > 0.95)
+ return false;
+
+ if(useJobType_) {
+ this.uLow[jobType] = uLow;
+ this.uMed[jobType] = uMed;
+ this.uHi[jobType] = uHi;
+ this.uProb[jobType] = uProb;
+ }
+ else {
+ this.uLow[INTERACTIVE] = this.uLow[BATCH] = uLow;
+ this.uMed[INTERACTIVE] = this.uMed[BATCH] = uMed;
+ this.uHi[INTERACTIVE] = this.uHi[BATCH] = uHi;
+ this.uProb[INTERACTIVE] = this.uProb[BATCH] = uProb;
+ }
+
+ return true;
+ }
+
+ /** Sets the parameters for the running time
+ * The running time is computed using hyper-gamma distribution.
+ * The parameters a1,b1,a2,b2 are the parameters of the two gamma distributions
+ * The p parameter of the hyper-gamma distribution is calculated as a straight
+ * (linear) line p = pa*nodes + pb. * 'nodes' will be calculated
+ * in the program, here we defined the 'pa','pb'
+ * parameters.
+ * @param a1 hyper-gamma distribution parameter.
+ * @param a2 hyper-gamma distribution parameter.
+ * @param b1 hyper-gamma distribution parameter.
+ * @param b2 hyper-gamma distribution parameter.
+ * @param pa hyper-gamma distribution parameter.
+ * @param pb hyper-gamma distribution parameter.
+ * @return <tt>true</tt> if the parameters have been set, or
+ * <tt>false</tt> otherwise.
+ */
+ public boolean setRunTimeParameters(int jobType,
+ double a1, double a2, double b1, double b2,
+ double pa, double pb) {
+ if(jobType > BATCH || jobType < INTERACTIVE)
+ return false;
+
+ if(useJobType_) {
+ this.a1[jobType] = a1; this.b1[jobType] = b1;
+ this.a2[jobType] = a2; this.b2[jobType] = b2;
+ this.pa[jobType] = pa; this.pb[jobType] = pb;
+ }
+ else {
+ this.a1[INTERACTIVE] = this.a1[BATCH] = a1;
+ this.b1[INTERACTIVE] = this.a1[BATCH] = b1;
+ this.a2[INTERACTIVE] = this.a1[BATCH] = a2;
+ this.b2[INTERACTIVE] = this.a1[BATCH] = b2;
+ this.pa[INTERACTIVE] = this.a1[BATCH] = pa;
+ this.pb[INTERACTIVE] = this.a1[BATCH] = pb;
+ }
+
+ return true;
+ }
+
+ /**
+ * Sets the parameters for the inter-arrival time
+ * The inter-arriving time is calculated using two gamma distributions.
+ * gamma(aarr,barr) represents the inter_arrival time for the rush hours. It is
+ * independent on the hour the job arrived at.
+ * The cdf of gamma(bnum,anum) represents the proportion of number of jobs which
+ * arrived at each time interval (bucket).
+ * The inter-arrival time is calculated using both gammas
+ * Since gamma(aarr,barr) represents the arrive-time at the rush time , we use
+ * a constant ,ARAR (Arrive-Rush-All-Ratio), to set the alpha parameter (the new
+ * aarr) so it will represent the arrive-time at all hours of the day.
+ */
+ public boolean setInterArrivalTimeParameters(int jobType,
+ double aarr, double barr, double anum, double bnum, double arar) {
+ if(jobType > BATCH || jobType < INTERACTIVE)
+ return false;
+
+ if(useJobType_) {
+ this.aarr[jobType] = aarr * arar;
+ this.barr[jobType] = barr;
+ this.anum[jobType] = anum;
+ this.bnum[jobType] = bnum;
+ }
+ else {
+ this.aarr[INTERACTIVE] = this.aarr[BATCH] = aarr * arar;
+ this.barr[INTERACTIVE] = this.barr[BATCH] = barr;
+ this.anum[INTERACTIVE] = this.barr[BATCH] = anum;
+ this.bnum[INTERACTIVE] = this.barr[BATCH] = bnum;
+ }
+
+ return true;
+ }
+
+ /**
+ * Sets the maximum number of jobs to be generated by this workload model
+ * @param numJobs the number of jobs
+ * @returns <tt>true</tt> if the number of jobs has been set;
+ * <tt>false</tt> othwerwise.
+ */
+ public boolean setNumJobs(int numJobs) {
+ if(numJobs < 1)
+ return false;
+
+ numJobs_ = numJobs;
+ return true;
+ }
+
+ /**
+ * Sets the maximum time duration of the workload. The workload will create
+ * jobs whose time of submission is less or equals to workloadDuration.
+ * The workload model will stop when it approaches workloadDuration.
+ * @param workloadDuration the maximum duration of the workload.
+ * @return <tt>true</tt> if the duration has been set;
+ * <tt>false</tt> othwerwise.
+ */
+ public boolean setMaximumWorkloadDuration(double workloadDuration) {
+ if(workloadDuration <= 0)
+ return false;
+
+ workloadDuration_ = workloadDuration;
+ return true;
+ }
+
+ /**
+ * Sets a Gridlet file size (in byte) for sending to/from a resource.
+ * @param size a Gridlet file size (in byte)
+ * @return <tt>true</tt> if it is successful, <tt>false</tt> otherwise
+ * @pre size > 0
+ * @post $none
+ */
+ public boolean setGridletFileSize(int size) {
+ if (size < 0) {
+ return false;
+ }
+
+ size_ = size;
+ return true;
+ }
+
+ /**
+ * Gets a list of completed Gridlets
+ * @return a list of Gridlets
+ * @pre $none
+ * @post $none
+ */
+ public ArrayList getGridletList() {
+ return list_;
+ }
+
+ /**
+ * Prints the Gridlet objects
+ * @param history <tt>true</tt> means printing each Gridlet's history,
+ * <tt>false</tt> otherwise
+ * @pre $none
+ * @post $none
+ */
+ public void printGridletList(boolean history) {
+ String name = super.get_name();
+ int size = list_.size();
+ Gridlet gridlet;
+
+ String indent = " ";
+ System.out.println();
+ System.out.println("========== OUTPUT for " + name + " ==========");
+ System.out.println("Gridlet_ID" + indent + "STATUS" + indent +
+ "Resource_ID" + indent + "Cost");
+
+ int i = 0;
+ for (i = 0; i < size; i++)
+ {
+ gridlet = (Gridlet) list_.get(i);
+ System.out.print(indent + gridlet.getGridletID() + indent
+ + indent);
+
+ // get the status of a Gridlet
+ System.out.print( gridlet.getGridletStatusString() );
+ System.out.println( indent + indent + gridlet.getResourceID() +
+ indent + indent + gridlet.getProcessingCost() );
+ }
+
+ System.out.println();
+ if (history == true)
+ {
+ // a loop to print each Gridlet's history
+ System.out.println();
+ for (i = 0; i < size; i++)
+ {
+ gridlet = (Gridlet) list_.get(i);
+ System.out.println( gridlet.getGridletHistory() );
+
+ System.out.print("Gridlet #" + gridlet.getGridletID() );
+ System.out.println(", length = " + gridlet.getGridletLength()
+ + ", finished so far = "
+ + gridlet.getGridletFinishedSoFar() );
+ System.out.println("=========================================");
+ System.out.println();
+ }
+ }
+ }
+
+ /**
+ * Reads from a given file when the simulation starts running.
+ * Then submits Gridlets to a resource and collects them before exiting.
+ * To collect the completed Gridlets, use {@link #getGridletList()}
+ * @pre $none
+ * @post $none
+ */
+ public void body() {
+ System.out.println();
+ System.out.println(super.get_name() + ".body() :%%%% Start ...");
+
+ // get the resource id
+ if (resID_ < 0)
+ {
+ System.out.println(super.get_name() +
+ ".body(): Error - invalid resource name: " + resName_);
+ return;
+ }
+
+ boolean success = createGridlets();
+
+ // if all the gridlets have been submitted
+ if (success == true) {
+ collectGridlet();
+ }
+ else {
+ System.out.println(super.get_name() +
+ ".body(): Error - unable to parse from a file.");
+ }
+
+ // shut down all the entities, including GridStatistics entity since
+ // we used it to record certain events.
+ shutdownGridStatisticsEntity();
+ shutdownUserEntity();
+ terminateIOEntities();
+
+ System.out.println(super.get_name() + ".body() : %%%% Exit ...");
+ }
+
+ //////////////////////// PROTECTED METHODS ///////////////////////
+
+ /**
+ * Collects Gridlets sent and stores them into a list.
+ * @pre $none
+ * @post $none
+ */
+ protected void collectGridlet() {
+ System.out.println(super.get_name() + ": Collecting Gridlets ...");
+ list_ = new ArrayList(gridletID_ + 1);
+
+ Object data = null;
+ Gridlet gl = null;
+
+ int counter = 1; // starts at 1, since gridletID_ starts at 1 too
+ Sim_event ev = new Sim_event();
+ while ( Sim_system.running() )
+ {
+ super.sim_get_next(ev); // get the next available event
+ data = ev.get_data(); // get the event's data
+
+ // handle ping request
+ if (ev.get_tag() == GridSimTags.INFOPKT_SUBMIT)
+ {
+ processPingRequest(ev);
+ continue;
+ }
+
+ // get the Gridlet data
+ if (data != null && data instanceof Gridlet) {
+ gl = (Gridlet) data;
+ list_.add(gl);
+ counter++;
+ }
+
+ // if all the Gridlets have been collected
+ if (counter == gridletID_) {
+ break;
+ }
+ }
+ }
+
+ /**
+ * Processes a ping request.
+ * @param ev a Sim_event object
+ * @pre ev != null
+ * @post $none
+ */
+ protected void processPingRequest(Sim_event ev) {
+ InfoPacket pkt = (InfoPacket) ev.get_data();
+ pkt.setTag(GridSimTags.INFOPKT_RETURN);
+ pkt.setDestID( pkt.getSrcID() );
+
+ // sends back to the sender
+ super.send(super.output, GridSimTags.SCHEDULE_NOW,
+ GridSimTags.INFOPKT_RETURN,
+ new IO_data(pkt, pkt.getSize(), pkt.getSrcID()) );
+ }
+
+ //////////////////////// PRIVATE METHODS ///////////////////////
+
+ /**
+ * Creates the gridlets according to the workload model and sends them
+ * to the grid resource entity.
+ * @return <tt>true</tt> if the gridlets were created successfully or
+ * <tt>false</tt> otherwise.
+ */
+ private boolean createGridlets() {
+
+ int type = INTERACTIVE;
+ int nodes; long arrTime; int runTime;
+
+ arrivalInit(aarr, barr, anum, bnum, START, weights);
+
+ for (int i=0; i<numJobs_; i++) {
+ long[] info = arrive(type, weights, aarr, barr);
+ type = (int)info[0];
+ arrTime = (long)info[1];
+
+ if(arrTime > workloadDuration_) {
+ return true;
+ }
+
+ nodes = calcNumberOfNodes(serialProb[type] , pow2Prob[type],
+ uLow[type], uMed[type], uHi[type], uProb[type]);
+
+ runTime = (int)timeFromNodes(a1[type], b1[type], a2[type], b2[type],
+ pa[type], pb[type], nodes);
+
+ submitGridlet(i+1, arrTime, runTime, nodes);
+ }
+
+ return true;
+ }
+
+ /*----------------------------------------------------------------------------*/
+ /* CALC_NUMBER_OF_NODES (NUMBER OF NODES) */
+ /* -------------------------------------------------------------------------- */
+ /*
+ * we distinguish between serial jobs , power2 jobs and other.
+ * for serial job (with probability SerialProb) the number of nodes is 1
+ * for all parallel jobs (both power2 and other jobs) we randomly choose a
+ * number (called 'par') from two-stage-uniform distribution.
+ * if the job is a power2 job then we make it an integer (par = round(par)),
+ * the number of nodes will be 2^par but since it must be an integer we return
+ * round(pow(2,par)).
+ * if we made par an integer then 2^par is ,obviously, a power of 2.
+ */
+ private int calcNumberOfNodes(double serialProb, double pow2Prob, double uLow,
+ double uMed, double uHi, double uProb) {
+ double u,par;
+
+ u = random_.nextDouble();
+ if (u <= serialProb) // serial job
+ return 1;
+ par = twoStageUniform(uLow, uMed, uHi, uProb);
+ if (u <= (serialProb + pow2Prob)) // power of 2 nodes parallel job
+ par = (int)(par + 0.5); // par = round(par)
+
+ return (int)(Math.pow(2, par) + 0.5); // return round(2^par)
+ }
+
+ /*----------------------------------------------------------------------------*/
+ /* TIMES_FROM_NODES (RUNTIME) */
+ /* -------------------------------------------------------------------------- */
+ /*
+ * time_from_nodes returns a value of a random number from hyper_gamma
+ * distribution.
+ * The a1,b1,a2,b2 are the parameters of both gammas.
+ * The 'p' parameter is calculated from the 'nodes' 'pa' and 'pb' arguments
+ * using the formula: p = pa * nodes + pb.
+ * we keep 'p' a probability by forcing its value to be in the interval [0,1].
+ * if the value that was randomly chosen is too big (larger than
+ * TOO_MUCH_TIME) then we choose another random value.
+ */
+ private long timeFromNodes(double alpha1, double beta1,
+ double alpha2, double beta2,
+ double pa, double pb, int nodes) {
+ double hg;
+ double p = pa*nodes + pb;
+
+ if (p>1)
+ p=1;
+ else if (p<0)
+ p=0;
+ do {
+ hg = hyperGamma(alpha1 , beta1 , alpha2 , beta2 , p);
+ } while (hg > TOO_MUCH_TIME);
+
+ return (long)Math.exp(hg);
+ }
+
+ /* The arrive process.
+ * 'arrive' returns arrival time (from the beginning of the simulation) of
+ * the current job.
+ * The (gamma distribution) parameters 'aarr' and 'barr' represent the
+ * inter-arrival time at rush hours.
+ * The (gamma distribution) parameters 'anum' and 'bnum' represent the number
+ * of jobs arriving at different times of the day. Those parameters fit a day
+ * that contains the hours [CYCLIC_DAY_START..24+CYCLIC_DAY_START] and are
+ * cyclically moved back to 0..24
+ * 'start' is the starting time (in hours 0-23) of the simulation.
+ * If the inter-arrival time randomly chosen is too big (larger than
+ * TOO_MUCH_ARRIVE_TIME) then another value is chosen.
+ *
+ * The algorithm (briefly):
+ * A. Preparations (calculated only once in 'arrive_init()':
+ * 1. foreach time interval (bucket) calculate its proportion of the number
+ * of arriving jobs (using 'anum' and 'bnum'). This value will be the
+ * bucket's points.
+ * 2. calculate the mean number of points in a bucket ()
+ * 3. divide the points in each bucket by the points mean ("normalize" the
+ * points in all buckets)
+ * B. randomly choosing a new arrival time for a job:
+ * 1. get a random value from distribution gamma(aarr , barr).
+ * 2. calculate the points we have.
+ * 3. accumulate inter-arrival time by passing buckets (while paying them
+ * points for that) until we do not have enough points.
+ * 4. handle reminders - add the new reminder and subtract the old reminder.
+ * 5. update the time variables ('current' and 'time_from_begin')
+ */
+ private void arrivalInit(double[] aarr, double[] barr,
+ double[] anum, double[] bnum, int start_hour, double weights[][]) {
+
+ int idx, moveto = CYCLIC_DAY_START;
+ double[] mean = new double[] {0,0};
+
+ for(int i=0; i<weights.length; i++)
+ for(int j=0; j<weights[i].length; j++)
+ weights[i][j] = 0;
+
+ current_[BATCH] = current_[INTERACTIVE] = start_hour * BUCKETS / HOURS_IN_DAY;
+
+ /*
+ * for both batch and interactive calculate the propotion of each bucket ,
+ * and their mean */
+ for (int j=0 ; j<=1 ; j++) {
+ for (int i=moveto ; i<BUCKETS+moveto ; i++) {
+ idx = (i-1)%BUCKETS; /* i-1 since array indices are 0..47 and not 1..48 */
+ weights[j][idx] =
+ gamcdf(i+0.5, anum[j], bnum[j]) - gamcdf(i-0.5, anum[j],bnum[j]);
+ mean[j] += weights[j][idx];
+ }
+ mean[j] /= BUCKETS;
+ }
+
+ /* normalize it so we associates between seconds and points correctly */
+ for (int j=0 ; j<=1 ; j++)
+ for (int i=0 ; i<BUCKETS ; i++)
+ weights[j][i] /= mean[j];
+
+ calcNextArrival(BATCH ,weights,aarr,barr);
+ calcNextArrival(INTERACTIVE,weights,aarr,barr);
+ }
+
+ /*
+ * 'calcNextArrival' calculates the next inter-arrival time according
+ * to the current time of the day.
+ * 'type' is the type of the next job -- interactive or batch
+ * alpha and barr are the parameters of the gamma distribution of the
+ * inter-arrival time.
+ * NOTE: this function changes the global variables concerning the arrival time.
+ */
+ private void calcNextArrival(int type, double[][] weights,
+ double[] aarr, double[] barr) {
+
+ double[] points = new double []{0,0};
+ double[] reminder = new double[]{0,0};
+ int bucket;
+ double gam, nextArrival, newReminder, moreTime;
+
+ bucket = current_[type]; // the bucket of the current time
+ do { // randomly choose a (not too big) number from gamma distribution
+ gam = gamrnd(aarr[type],barr[type]);
+ } while (gam > TOO_MUCH_ARRIVE_TIME);
+
+ points[type] += (Math.exp(gam) / SECONDS_IN_BUCKET); // number of points
+ nextArrival = 0;
+ while (points[type] > weights[type][bucket]) { // while have more points
+ points[type] -= weights[type][bucket]; // pay points to this bucket
+ bucket = (bucket+1) % 48; // ... and goto the next bucket
+ nextArrival += SECONDS_IN_BUCKET; // accumulate time in next_arrive
+ }
+
+ newReminder = points[type]/weights[type][bucket];
+ moreTime = SECONDS_IN_BUCKET * ( newReminder - reminder[type]);
+ nextArrival += moreTime; // add reminders
+ reminder[type] = newReminder; // save it for next call
+
+ // update the attributes
+ timeFromBegin_[type] += nextArrival;
+ current_[type] = bucket;
+ }
+
+ /*----------------------------------------------------------------------------*/
+ /* ARRIVE (ARRIVAL TIME AND TYPE) */
+ /*----------------------------------------------------------------------------*/
+ /*
+ * return the time for next job to arrive the system.
+ * returns also the type of the next job , which is the type that its
+ * next arrive time (time_from_begin) is closer to the start (smaller).
+ * notice that since calc_next_arrive changes time_from_begin[] we must save
+ * the time_from_begin in 'res' so we would be able to return it.
+ */
+ private long[] arrive(int type, double[][] weights, double[] aarr, double[] barr) {
+ long res;
+
+ type = (timeFromBegin_[BATCH] < timeFromBegin_[INTERACTIVE]) ? BATCH : INTERACTIVE;
+ res = timeFromBegin_[type]; // save the job's arrival time
+
+ // randomly choose the next job's (of the same type) arrival time
+ calcNextArrival(type, weights, aarr, barr);
+ return new long[] {type, res};
+ }
+
+ /**
+ * Creates a Gridlet with the given information, then submit it to a
+ * resource
+ * @param id a Gridlet ID
+ * @param submitTime Gridlet's submit time
+ * @param runTime Gridlet's run time
+ * @param numProc number of processors
+ * @pre id >= 0
+ * @pre submitTime >= 0
+ * @pre runTime >= 0
+ * @pre numProc > 0
+ * @post $none
+ */
+ protected void submitGridlet(int id, long submitTime, int runTime, int numProc)
+ {
+ // create the gridlet
+ int len = runTime * rating_; // calculate a job length for each PE
+ Gridlet gl = new Gridlet(id, len, size_, size_, GridSim.isTraceEnabled());
+ gl.setUserID( super.get_id() ); // set the owner ID
+ gl.setNumPE(numProc); // set the requested num of proc
+
+ // printing to inform user
+ if (gridletID_ == 1 || gridletID_ % INTERVAL == 0)
+ {
+ System.out.println(super.get_name() + ": Submitting Gridlets to " +
+ resName_ + " ...");
+ }
+
+ // check the submit time
+ if (submitTime < 0) {
+ submitTime = 0;
+ }
+
+ gridletID_++; // increment the counter
+
+ // submit a gridlet to resource
+ super.send(super.output, submitTime, GridSimTags.GRIDLET_SUBMIT,
+ new IO_data(gl, gl.getGridletFileSize(), resID_) );
+ }
+
+
+ // --- Methods required by the distributions used by the workload model ---
+
+ /*
+ * hyper_gamma returns a value of a random variable of mixture of two
+ * gammas. its parameters are those of the two gammas: a1,b1,a2,b2 and the
+ * relation between the gammas (p = the probability of the first gamma). we
+ * first randomly decide which gamma will be active ((a1,b1) or (a2,b2)).
+ * then we randomly choose a number from the chosen gamma distribution.
+ */
+ double hyperGamma(double a1, double b1, double a2, double b2, double p) {
+ double a, b, hg, u = random_.nextDouble();
+
+ if (u <= p) { /* gamma(a1,b1) */
+ a = a1;
+ b = b1;
+ } else { /* gamma(a2,b2) */
+ a = a2;
+ b = b2;
+ }
+
+ /* generate a value of a random variable from distribution gamma(a,b) */
+ hg = gamrnd(a, b);
+ return hg;
+ }
+
+ /*
+ * gamrnd returns a value of a random variable of gamma(alpha,beta).
+ * gamma(alpha,beta) = gamma(int(alpha),beta) +
+ * gamma(alpha-int(alpha),beta). This function and the following 3 functions
+ * were written according to Jain Raj, 'THE ART OF COMPUTER SYSTEMS
+ * PERFORMANCE ANALYSIS Techniques for Experimental Design, Measurement,
+ * Simulation, and Modeling'. Jhon Wiley & Sons , Inc. 1991. Chapter 28 -
+ * RANDOM-VARIATE GENERATION (pages 484,485,490,491)
+ * can be improved by getting 'diff' and 'intalpha' as function's parameters
+ */
+
+ private double gamrnd(double alpha, double beta) {
+ double diff, gam = 0;
+ long intalpha = (long) alpha;
+ if (alpha >= 1)
+ gam += gamrndIntAlpha(intalpha, beta);
+ if ((diff = alpha - intalpha) > 0)
+ gam += gamrndAlphaSmaller1(diff, beta);
+ return gam;
+ }
+
+ /*
+ * gamrnd_int_alpha returns a value of a random variable of gamma(n,beta)
+ * distribution where n is integer(unsigned long actually). gamma(n,beta) ==
+ * beta*gamma(n,1) == beta* sum(1..n){gamma(1,1)} == beta* sum(1..n){exp(1)} ==
+ * beta* sum(1..n){-ln(uniform(0,1))}
+ */
+ private double gamrndIntAlpha(long n, double beta) {
+ double acc = 0;
+ for (int i = 0; i < n; i++)
+ acc += Math.log(random_.nextDouble()); /* sum the exponential
+ * random variables
+ */
+ return (-acc * beta);
+ }
+
+ /*
+ * gamrnd_alpha_smaller_1 returns a value of a random variable of
+ * gamma(alpha,beta) where alpha is smaller than 1. This is done using the
+ * Beta distribution. (alpha<1) ==> (1-alpha<1) ==> we can use
+ * beta_less_1(alpha,1-alpha) gamma(alpha,beta) = exponential(beta) *
+ * Beta(alpha,1-alpha)
+ */
+ private double gamrndAlphaSmaller1(double alpha, double beta) {
+ double x = betarndLess1(alpha, 1 - alpha); /* beta random variable */
+ double y = -Math.log(random_.nextDouble()); /* exponential random
+ * variable */
+ return (beta * x * y);
+ }
+
+ /*
+ * betarnd_less_1 returns a value of a random variable of beta(alpha,beta)
+ * distribution where both alpha and beta are smaller than 1 (and larger
+ * than 0)
+ */
+ private double betarndLess1(double alpha, double beta) {
+ double x, y, u1, u2;
+ do {
+ u1 = random_.nextDouble();
+ u2 = random_.nextDouble();
+ x = Math.pow(u1, 1 / alpha);
+ y = Math.pow(u2, 1 / beta);
+ } while (x + y > 1);
+ return (x / (x + y));
+ }
+
+ /*
+ * Returns the cumulative distribution function of gamma(alpha, beta)
+ * distribution at the point 'x'; return -1 if an error (non-convergence)
+ * occurs.
+ * This function and the following two functions were written
+ * according to William H. Press , Brian P. Flannery , Saul A. Teukolsky and
+ * William T. Vetterling. NUMERICAL RECIPES IN PASCAL The Art of Scientific
+ * Computing. Cambridge University Press 1989 Chapter 6 - Special Functions
+ * (pages 180-183).
+ */
+ private double gamcdf(double x, double alpha, double beta) {
+ x /= beta;
+ if (x < (alpha + 1)) {
+ return gser(x, alpha);
+ }
+
+ /* x >= a+1 */
+ r...
[truncated message content] |