Skip to content

Commit

Permalink
add supplementaries for homework06
Browse files Browse the repository at this point in the history
  • Loading branch information
lemorage committed Sep 8, 2023
1 parent 285571e commit 8375d85
Show file tree
Hide file tree
Showing 14 changed files with 765 additions and 0 deletions.
Binary file added hw06/6.34.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions hw06/mountain/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
CC = gcc
CFLAGS = -Wall -O3 -D__i386__

mountain: mountain.c fcyc2.c clock.c
$(CC) $(CFLAGS) -o mountain mountain.c fcyc2.c clock.c

clean:
rm -f mountain *.o *~


8 changes: 8 additions & 0 deletions hw06/mountain/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
This directory contains code for generating a memory mountain, as
described in Computer Systems: A Programmer's Perspective

clock.{c,h} - routines for using x86 and Alpha cycle timers
fcyc2.{c,h} - routines that estimate the number of cycles required
by a function f that takes two arguments.
Makefile - memory mountain makefile
mountain.c - program that generates the memory mountain.
188 changes: 188 additions & 0 deletions hw06/mountain/clock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/times.h>
#include <string.h>
#include "clock.h"


/* Keep track of most recent reading of cycle counter */
static unsigned cyc_hi = 0;
static unsigned cyc_lo = 0;

void access_counter(unsigned *hi, unsigned *lo)
{
/* Get cycle counter */
asm("rdtsc; movl %%edx,%0; movl %%eax,%1"
: "=r" (*hi), "=r" (*lo)
: /* No input */
: "%edx", "%eax");
}

void start_counter()
{
access_counter(&cyc_hi, &cyc_lo);
}

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: Cycle counter returning negative value: %.0f\n", result);
}
return result;
}

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;
}


/* Keep track of clock speed */
double cpu_ghz = 0.0;

/* Get megahertz from /etc/proc */
#define MAXBUF 512

double core_mhz(int verbose) {
static char buf[MAXBUF];
FILE *fp = fopen("/proc/cpuinfo", "r");
cpu_ghz = 0.0;

if (!fp) {
fprintf(stderr, "Can't open /proc/cpuinfo to get clock information\n");
cpu_ghz = 1.0;
return cpu_ghz * 1000.0;
}
while (fgets(buf, MAXBUF, fp)) {
if (strstr(buf, "cpu MHz")) {
double cpu_mhz = 0.0;
sscanf(buf, "cpu MHz\t: %lf", &cpu_mhz);
cpu_ghz = cpu_mhz / 1000.0;
break;
}
}
fclose(fp);
if (cpu_ghz == 0.0) {
fprintf(stderr, "Can't open /proc/cpuinfo to get clock information\n");
cpu_ghz = 1.0;
return cpu_ghz * 1000.0;
}
if (verbose) {
printf("Processor Clock Rate ~= %.4f GHz (extracted from file)\n", cpu_ghz);
}
return cpu_ghz * 1000;
}

double mhz(int verbose) {
double val = core_mhz(verbose);
return val;
}



/* Determine clock rate by measuring cycles
elapsed 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;
}

///* 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(1);
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;
}
23 changes: 23 additions & 0 deletions hw06/mountain/clock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* Routines for using cycle counter */

/* Start the counter */
void start_counter();

/* Get # cycles since counter started */
double get_counter();


/* Measure overhead for counter */
double ovhd();

/* Determine clock rate of processor */
double mhz(int verbose);

/* Determine clock rate of processor, having more control over accuracy */
double mhz_full(int verbose, int sleeptime);

/** Special counters that compensate for timer interrupt overhead */

void start_comp_counter();

double get_comp_counter();
Loading

0 comments on commit 8375d85

Please sign in to comment.