⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clock.c

📁 ICS 课程的Lab6
💻 C
字号:
/*  * clock.c - Routines for using the cycle counters on x86,  *           Alpha, and Sparc boxes. *  * Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved. * May not be used, modified, or copied without permission. */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/times.h>#include "clock.h"/*******************************************************  * Machine dependent functions  * * Note: the constants __i386__ and  __alpha * are set by GCC when it calls the C preprocessor * You can verify this for yourself using gcc -v. *******************************************************/#if defined(__i386__)  /******************************************************* * Pentium versions of start_counter() and get_counter() *******************************************************//* $begin x86cyclecounter *//* Initialize the cycle counter */static unsigned cyc_hi = 0;static unsigned cyc_lo = 0;/* Set *hi and *lo to the high and low order bits  of the cycle counter.     Implementation requires assembly code to use the rdtsc instruction. */void access_counter(unsigned *hi, unsigned *lo){    asm("rdtsc; movl %%edx,%0; movl %%eax,%1"   /* Read cycle counter */	: "=r" (*hi), "=r" (*lo)                /* and move results to */	: /* No input */                        /* the two outputs */	: "%edx", "%eax");}/* Record the current value of the cycle counter. */void start_counter(){    access_counter(&cyc_hi, &cyc_lo);}/* Return the number of cycles since the last call to start_counter. */double get_counter(){    unsigned ncyc_hi, ncyc_lo;    unsigned hi, lo, borrow;    double result;    /* Get cycle counter */    access_counter(&ncyc_hi, &ncyc_lo);    /* Do double precision subtraction */    lo = ncyc_lo - cyc_lo;    borrow = lo > ncyc_lo;    hi = ncyc_hi - cyc_hi - borrow;    result = (double) hi * (1 << 30) * 4 + lo;    if (result < 0) {	fprintf(stderr, "Error: counter returns neg value: %.0f\n", result);    }    return result;}/* $end x86cyclecounter */#elif defined(__alpha)/**************************************************** * Alpha versions of start_counter() and get_counter() ***************************************************//* Initialize the cycle counter */static unsigned cyc_hi = 0;static unsigned cyc_lo = 0;/* Use Alpha cycle timer to compute cycles.  Then use   measured clock speed to compute seconds *//* * counterRoutine is an array of Alpha instructions to access  * the Alpha's processor cycle counter. It uses the rpcc  * instruction to access the counter. This 64 bit register is  * divided into two parts. The lower 32 bits are the cycles  * used by the current process. The upper 32 bits are wall  * clock cycles. These instructions read the counter, and  * convert the lower 32 bits into an unsigned int - this is the  * user space counter value. * NOTE: The counter has a very limited time span. With a  * 450MhZ clock the counter can time things for about 9  * seconds. */static unsigned int counterRoutine[] ={    0x601fc000u,    0x401f0000u,    0x6bfa8001u};/* Cast the above instructions into a function. */static unsigned int (*counter)(void)= (void *)counterRoutine;void start_counter(){    /* Get cycle counter */    cyc_hi = 0;    cyc_lo = counter();}double get_counter(){    unsigned ncyc_hi, ncyc_lo;    unsigned hi, lo, borrow;    double result;    ncyc_lo = counter();    ncyc_hi = 0;    lo = ncyc_lo - cyc_lo;    borrow = lo > ncyc_lo;    hi = ncyc_hi - cyc_hi - borrow;    result = (double) hi * (1 << 30) * 4 + lo;    if (result < 0) {	fprintf(stderr, "Error: Cycle counter returning negative value: %.0f\n", result);    }    return result;}#else/**************************************************************** * All the other platforms for which we haven't implemented cycle * counter routines. Newer models of sparcs (v8plus) have cycle * counters that can be accessed from user programs, but since there * are still many sparc boxes out there that don't support this, we * haven't provided a Sparc version here. ***************************************************************/void start_counter(){    printf("ERROR: You are trying to use a start_counter routine in clock.c\n");    printf("that has not been implemented yet on this platform.\n");    printf("Please choose another timing package in config.h.\n");    exit(1);}double get_counter() {    printf("ERROR: You are trying to use a get_counter routine in clock.c\n");    printf("that has not been implemented yet on this platform.\n");    printf("Please choose another timing package in config.h.\n");    exit(1);}#endif/******************************* * Machine-independent functions ******************************/double ovhd(){    /* Do it twice to eliminate cache effects */    int i;    double result;    for (i = 0; i < 2; i++) {	start_counter();	result = get_counter();    }    return result;}/* $begin mhz *//* Estimate the clock rate by measuring the cycles that elapse */ /* while sleeping for sleeptime seconds */double mhz_full(int verbose, int sleeptime){    double rate;    start_counter();    sleep(sleeptime);    rate = get_counter() / (1e6*sleeptime);    if (verbose) 	printf("Processor clock rate ~= %.1f MHz\n", rate);    return rate;}/* $end mhz *//* Version using a default sleeptime */double mhz(int verbose){    return mhz_full(verbose, 2);}/** Special counters that compensate for timer interrupt overhead */static double cyc_per_tick = 0.0;#define NEVENT 100#define THRESHOLD 1000#define RECORDTHRESH 3000/* Attempt to see how much time is used by timer interrupt */static void callibrate(int verbose){    double oldt;    struct tms t;    clock_t oldc;    int e = 0;    times(&t);    oldc = t.tms_utime;    start_counter();    oldt = get_counter();    while (e <NEVENT) {	double newt = get_counter();	if (newt-oldt >= THRESHOLD) {	    clock_t newc;	    times(&t);	    newc = t.tms_utime;	    if (newc > oldc) {		double cpt = (newt-oldt)/(newc-oldc);		if ((cyc_per_tick == 0.0 || cyc_per_tick > cpt) && cpt > RECORDTHRESH)		    cyc_per_tick = cpt;		/*		  if (verbose)		  printf("Saw event lasting %.0f cycles and %d ticks.  Ratio = %f\n",		  newt-oldt, (int) (newc-oldc), cpt);		*/		e++;		oldc = newc;	    }	    oldt = newt;	}    }    if (verbose)	printf("Setting cyc_per_tick to %f\n", cyc_per_tick);}static clock_t start_tick = 0;void start_comp_counter() {    struct tms t;    if (cyc_per_tick == 0.0)	callibrate(0);    times(&t);    start_tick = t.tms_utime;    start_counter();}double get_comp_counter() {    double time = get_counter();    double ctime;    struct tms t;    clock_t ticks;    times(&t);    ticks = t.tms_utime - start_tick;    ctime = time - ticks*cyc_per_tick;    /*      printf("Measured %.0f cycles.  Ticks = %d.  Corrected %.0f cycles\n",      time, (int) ticks, ctime);    */    return ctime;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -