Пример #1
0
void approx(void)
{
	extern int        PDQ_DEBUG, iterations, streams, nodes;
	extern char       s1[], s2[], s3[], s4[];
	extern double     tolerance;
	extern JOB_TYPE  *job;
	extern NODE_TYPE *node;
	extern void       typetostr();
	extern void       getjob_name();

	int               k, c;
	int               should_be_class;
	double            sumQ();
	double            sumR[MAXSTREAMS];
	double            delta = 2 * TOL;
	int               iterate;
	char              jobname[MAXBUF];
	NODE_TYPE        *last;
	char             *p = "approx()";

	if (PDQ_DEBUG)
		debug(p, "Entering");

	if (nodes == 0 || streams == 0)
		errmsg(p, "Network nodes and streams not defined.");
#ifndef __R_PDQ
	if ((last = (NODE_TYPE *) calloc(sizeof(NODE_TYPE), nodes)) == NULL)
#else
	  if ((last = (NODE_TYPE *) Calloc((size_t) nodes,  NODE_TYPE )) == NULL)
#endif
		errmsg(p, "Node (last) allocation failed!\n");

	iterations = 0;

	if (PDQ_DEBUG) {
		sprintf(s1, "\nIteration: %d", iterations);
		debug(p, s1);
		resets(s1);
	}

	/* initialize all queues */

	for (c = 0; c < streams; c++) {
		should_be_class = job[c].should_be_class;

		for (k = 0; k < nodes; k++) {
			switch (should_be_class) {
				case TERM:
					last[k].qsize[c] = node[k].qsize[c] = job[c].term->pop / nodes;
					break;
				case BATCH:
					last[k].qsize[c] = node[k].qsize[c] = job[c].batch->pop / nodes;
					break;
				default:
					break;
			}

			if (PDQ_DEBUG) {
				getjob_name(jobname, c);
				sprintf(s2, "Que[%s][%s]: %3.4f (D=%f)",
					node[k].devname,
					jobname,
					node[k].qsize[c],
					delta);
				debug(p, s2);
				resets(s2);
				resets(jobname);
			}
		}  /* over k */
	}  /* over c */

	do {
		iterations++;

		if (PDQ_DEBUG) {
			sprintf(s1, "\nIteration: %d", iterations);
			debug(p, s1);
			resets(s1);
		}

		for (c = 0; c < streams; c++) {
			getjob_name(jobname, c);

			sumR[c] = 0.0;

			if (PDQ_DEBUG) {
				sprintf(s1, "\nStream: %s", jobname);
				debug(p, s1);
				resets(s1);
			}

			should_be_class = job[c].should_be_class;

			for (k = 0; k < nodes; k++) {
				if (PDQ_DEBUG) {
					sprintf(s2, "Que[%s][%s]: %3.4f (D=%1.5f)",
						node[k].devname,
						jobname,
						node[k].qsize[c],
						delta);
					debug(p, s2);
					resets(s1);
				}

				/* approximate avg queue length */

				switch (should_be_class) {
					double  N;
					case TERM:
						N = job[c].term->pop;
						node[k].avqsize[c] = sumQ(k, c) +
							(node[k].qsize[c] * (N - 1.0) / N);
						break;
					case BATCH:
						N = job[c].batch->pop;
						node[k].avqsize[c] =
							sumQ(k, c) + (node[k].qsize[c] * (N - 1.0) / N);
						break;
					default:
						typetostr(s1, should_be_class);
						sprintf(s2, "Unknown should_be_class: %s", s1);
						errmsg(p, s2);
						resets(s2);
						break;
					}

					if (PDQ_DEBUG) {
						sprintf(s2, "<Q>[%s][%s]: %3.4f (D=%1.5f)",
							node[k].devname,
							jobname,
							node[k].avqsize[c],
							delta
					);
					debug(p, s2);
					resets(s2);
			}

			/* residence times */

			switch (node[k].sched) {
				case FCFS:
				case PSHR:
				case LCFS:
					node[k].resit[c] =
				node[k].demand[c] * (node[k].avqsize[c] + 1.0);
					break;
				case ISRV:
					node[k].resit[c] = node[k].demand[c];
					break;
				default:
					typetostr(s1, node[k].sched);
					sprintf(s2, "Unknown queue type: %s", s1);
					errmsg(p, s2);
					break;
			}

			sumR[c] += node[k].resit[c];


			if (PDQ_DEBUG) {
				PRINTF("\tTot ResTime[%s] = %3.4f\n", jobname, sumR[c]);

				PRINTF("\tnode[%s].qsize[%s] = %3.4f\n",
					node[k].devname,
					jobname,
					node[k].qsize[c]
				);

				PRINTF("\tnode[%s].demand[%s] = %3.4f\n",
					node[k].devname,
					jobname,
					node[k].demand[c]
				);

				PRINTF("\tnode[%s].resit[%s] = %3.4f\n",
					node[k].devname,
					jobname,
					node[k].resit[c]
				);
			}
		}			/* over k */


		/* system throughput, residency & response-time */

		switch (should_be_class) {
			case TERM:
				job[c].term->sys->thruput =
					(job[c].term->pop / (sumR[c] + job[c].term->think));
				job[c].term->sys->response =
					(job[c].term->pop / job[c].term->sys->thruput) - job[c].term->think;
				job[c].term->sys->residency =
					job[c].term->pop - (job[c].term->sys->thruput * job[c].term->think);

				if (PDQ_DEBUG) {
					sprintf(s2, "\tTERM<X>[%s]: %5.4f",
						jobname, job[c].term->sys->thruput);
					debug(p, s2);
					resets(s2);
					sprintf(s2, "\tTERM<R>[%s]: %5.4f",
						jobname, job[c].term->sys->response);
					debug(p, s2);
					resets(s2);
				}
				break;

			case BATCH:
				job[c].batch->sys->thruput = job[c].batch->pop / sumR[c];
				job[c].batch->sys->response =
					(job[c].batch->pop / job[c].batch->sys->thruput);
				job[c].batch->sys->residency = job[c].batch->pop;

				if (PDQ_DEBUG) {
					sprintf(s2, "\t<X>[%s]: %3.4f",
						jobname, job[c].batch->sys->thruput);
					debug(p, s2);
					resets(s2);
					sprintf(s2, "\t<R>[%s]: %3.4f",
						jobname, job[c].batch->sys->response);
					debug(p, s2);
					resets(s2);
				}

				break;
					default:
						sprintf(s1, "Unknown should_be_class: %s", should_be_class);
						errmsg(p, s1);
						break;
			}

			resets(jobname);
		}  /* over c */

		/* update queue sizes */

		for (c = 0; c < streams; c++) {
			getjob_name(jobname, c);
			should_be_class = job[c].should_be_class;
			iterate = FALSE;

			if (PDQ_DEBUG) {
				sprintf(s1, "Updating queues of \"%s\"", jobname);
				PRINTF("\n");
				debug(p, s1);
				resets(s1);
			}

			for (k = 0; k < nodes; k++) {
				switch (should_be_class) {
					case TERM:
						node[k].qsize[c] = job[c].term->sys->thruput * node[k].resit[c];
						break;
					case BATCH:
						node[k].qsize[c] = job[c].batch->sys->thruput * node[k].resit[c];
						break;
					default:
						sprintf(s1, "Unknown should_be_class: %s", should_be_class);
						errmsg(p, s1);
						break;
				}

				/* check convergence */

				delta = fabs((double) (last[k].qsize[c] - node[k].qsize[c]));

				if (delta > tolerance)	/* for any node */
					iterate = TRUE;	/* but complete all queue updates */

				last[k].qsize[c] = node[k].qsize[c];

				if (PDQ_DEBUG) {
					sprintf(s2, "Que[%s][%s]: %3.4f (D=%1.5f)",
						node[k].devname,
						jobname,
						node[k].qsize[c],
						delta);
					debug(p, s2);
					resets(s2);
				}
			}			/* over k */

			resets(jobname);
		}				/* over c */

		if (PDQ_DEBUG)
			debug(p, "Update complete");
	} while (iterate);

	/* cleanup */

	if (last) {
	  PDQ_FREE(last); 
	  last = NULL; 
	}

	if (PDQ_DEBUG)
		debug(p, "Exiting");
}  /* approx */
Пример #2
0
void canonical(void)
{
    extern int        PDQ_DEBUG, streams, nodes;
    extern char       s1[], s2[], s3[], s4[];
    extern JOB_TYPE  *job;
    extern NODE_TYPE *node;
    extern double     ErlangR(double arrivrate, double servtime, int servers); // ANSI

    int               k;
    int               m; // servers in MSQ case
    int               c = 0;
    double            X;
    double            Xsat;
    double            Dsat = 0.0;
    double            Ddev;
    double            sumR[MAXSTREAMS];
    double            devU;
    double            sumU();
    char              jobname[MAXBUF];
    char              satname[MAXBUF];
    char             *p = "canonical()";

    if (PDQ_DEBUG)
        debug(p, "Entering");

    for (c = 0; c < streams; c++) {
        sumR[c] = 0.0;
        Dsat = 0.0; // Fix submitted by James Newsom, 23 Feb 2011
        //Otherwise, stream index can be compared to wrong (old) device index

        X = job[c].trans->arrival_rate;
               
        // find bottleneck node (== largest service demand)
        for (k = 0; k < nodes; k++) {
        	// Hope to remove single class restriction eventually
        	if (node[k].sched == MSQ && streams > 1) {
				sprintf(s1, "Only single PDQ stream allowed with MSQ nodes.");
				errmsg(p, s1);
            }
            Ddev = node[k].demand[c];
            if (node[k].sched == MSQ) {     // multiserver case
                m = node[k].devtype;        // contains number of servers > 0
                Ddev /= m;
            }
            if (Ddev > Dsat) {
                Dsat = Ddev;
                //Since we're about to fall out this k-loop
                //keep device name in case of error msg
                sprintf(satname, "%s", node[k].devname);
            }
        } // end of k-loop
        
        Xsat = 1.0 / Dsat;
        job[c].trans->saturation_rate = Xsat;

        if (Dsat == 0) {
            sprintf(s1, "Dsat = %3.3f", Dsat);
            errmsg(p, s1);
        }

        if (X > Xsat) {
        	getjob_name(jobname, c);
            sprintf(s1, 
            	"\nArrival rate %3.3f for stream \'%s\' exceeds saturation thruput %3.3f of node \'%s\' with demand %3.3f", 
            	X, jobname, Xsat, satname, Dsat
            );  
        	errmsg(p, s1);
        }
        
        for (k = 0; k < nodes; k++) {
            node[k].utiliz[c] = X * node[k].demand[c];
            if (node[k].sched == MSQ) {     // multiserver case
                m = node[k].devtype;            // recompute m in every k-loop
                node[k].utiliz[c] /= m;     // per server
            }

            devU = sumU(k); // sum all workload classes

            if (devU > 1.0) {
                sprintf(s1, "\nTotal utilization of node \"%s\" is %2.2f%% (> 100%%)",
                    node[k].devname,
                    devU * 100
                    );
                errmsg(p, s1);
            }

            if (PDQ_DEBUG)
                printf("Tot Util: %3.4f for %s\n", devU, node[k].devname);

            switch (node[k].sched) {
                case FCFS:
                case PSHR:
                case LCFS:
                    node[k].resit[c] = node[k].demand[c] / (1.0 - devU);
                    node[k].qsize[c] = X * node[k].resit[c];
                    break;
                case MSQ: // Added by NJG on Mon, Apr 2, 2007
                    node[k].resit[c] = ErlangR(X, node[k].demand[c], m);
                    node[k].qsize[c] = X * node[k].resit[c];
                    break;
                case ISRV:
                    node[k].resit[c] = node[k].demand[c];
                    node[k].qsize[c] = node[k].utiliz[c];
                    break;
                default:
                    typetostr(s1, node[k].sched);
                    sprintf(s2, "Unknown queue type: %s", s1);
                    errmsg(p, s2);
                    break;
            }
            
            sumR[c] += node[k].resit[c];
            
        }  // end of k-loop

        job[c].trans->sys->thruput = X;             // system throughput
        job[c].trans->sys->response = sumR[c];      // system response time 
        job[c].trans->sys->residency = X * sumR[c]; // total number in system

        if (PDQ_DEBUG) {
            getjob_name(jobname, c);
            printf("\tX[%s]: %3.4f\n", jobname, job[c].trans->sys->thruput);
            printf("\tR[%s]: %3.4f\n", jobname, job[c].trans->sys->response);
            printf("\tN[%s]: %3.4f\n", jobname, job[c].trans->sys->residency);
        }
        
    }  // end of c-loop

    if (PDQ_DEBUG)
        debug(p, "Exiting");

}  // canonical