Implement the clock offset correction

This commit is contained in:
Rodrigo Arias 2021-08-03 19:56:31 +02:00
parent 4e971bceff
commit e6e976023d
5 changed files with 183 additions and 75 deletions

10
dump.c
View File

@ -12,16 +12,6 @@
#include "ovni_trace.h" #include "ovni_trace.h"
#include "emu.h" #include "emu.h"
#define ENABLE_DEBUG
#ifdef ENABLE_DEBUG
#define dbg(...) fprintf(stderr, __VA_ARGS__);
#else
#define dbg(...)
#endif
#define err(...) fprintf(stderr, __VA_ARGS__);
static void static void
hexdump(uint8_t *buf, size_t size) hexdump(uint8_t *buf, size_t size)

208
emu.c
View File

@ -8,12 +8,20 @@
#include <stdatomic.h> #include <stdatomic.h>
#include <dirent.h> #include <dirent.h>
#include <assert.h> #include <assert.h>
#include <unistd.h>
#include "ovni.h" #include "ovni.h"
#include "ovni_trace.h" #include "ovni_trace.h"
#include "emu.h" #include "emu.h"
#include "prv.h" #include "prv.h"
/* Obtains the corrected clock of the given event */
int64_t
evclock(struct ovni_stream *stream, struct ovni_ev *ev)
{
return (int64_t) ovni_ev_get_clock(ev) + stream->clock_offset;
}
static void static void
emit_ev(struct ovni_stream *stream, struct ovni_ev *ev) emit_ev(struct ovni_stream *stream, struct ovni_ev *ev)
{ {
@ -24,7 +32,7 @@ emit_ev(struct ovni_stream *stream, struct ovni_ev *ev)
//dbg("sizeof(*ev) = %d\n", sizeof(*ev)); //dbg("sizeof(*ev) = %d\n", sizeof(*ev));
//hexdump((uint8_t *) ev, sizeof(*ev)); //hexdump((uint8_t *) ev, sizeof(*ev));
clock = ovni_ev_get_clock(ev); clock = evclock(stream, ev);
delta = clock - stream->lastclock; delta = clock - stream->lastclock;
@ -126,7 +134,8 @@ next_event(struct ovni_emu *emu)
struct ovni_ev *ev; struct ovni_ev *ev;
struct ovni_stream *stream; struct ovni_stream *stream;
struct ovni_trace *trace; struct ovni_trace *trace;
static int64_t t0 = -1;
static int done_first = 0;
trace = &emu->trace; trace = &emu->trace;
@ -144,10 +153,10 @@ next_event(struct ovni_emu *emu)
continue; continue;
ev = stream->cur_ev; ev = stream->cur_ev;
if(f < 0 || ovni_ev_get_clock(ev) < minclock) if(f < 0 || evclock(stream, ev) < minclock)
{ {
f = i; f = i;
minclock = ovni_ev_get_clock(ev); minclock = evclock(stream, ev);
} }
} }
@ -159,18 +168,21 @@ next_event(struct ovni_emu *emu)
set_current(emu, stream); set_current(emu, stream);
if(emu->lastclock > ovni_ev_get_clock(stream->cur_ev)) if(emu->lastclock > evclock(stream, stream->cur_ev))
{ {
fprintf(stdout, "warning: backwards jump in time %lu -> %lu\n", fprintf(stdout, "warning: backwards jump in time %lu -> %lu\n",
emu->lastclock, ovni_ev_get_clock(stream->cur_ev)); emu->lastclock, evclock(stream, stream->cur_ev));
} }
emu->lastclock = ovni_ev_get_clock(stream->cur_ev); emu->lastclock = evclock(stream, stream->cur_ev);
if(t0 < 0) if(!done_first)
t0 = emu->lastclock; {
done_first = 1;
emu->firstclock = emu->lastclock;
}
emu->delta_time = emu->lastclock - t0; emu->delta_time = emu->lastclock - emu->firstclock;
return 0; return 0;
} }
@ -376,44 +388,162 @@ close_prvs(struct ovni_emu *emu)
fclose(emu->prv_cpu); fclose(emu->prv_cpu);
} }
static void
usage(int argc, char *argv[])
{
err("Usage: emu [-c offsetfile] tracedir\n");
err("\n");
err("Options:\n");
err(" -c offsetfile Use the given offset file to correct\n");
err(" the clocks among nodes. It can be\n");
err(" generated by the ovnisync program\n");
err("\n");
err(" tracedir The output trace dir generated by ovni.\n");
err("\n");
err("The output PRV files are placed in the tracedir directory.\n");
exit(EXIT_FAILURE);
}
static void
parse_args(struct ovni_emu *emu, int argc, char *argv[])
{
int opt;
while((opt = getopt(argc, argv, "c:")) != -1)
{
switch(opt)
{
case 'c':
emu->clock_offset_file = optarg;
break;
default: /* '?' */
usage(argc, argv);
}
}
if(optind >= argc)
{
err("missing tracedir\n");
usage(argc, argv);
}
emu->tracedir = argv[optind];
}
static struct ovni_loom *
find_loom_by_hostname(struct ovni_emu *emu, char *host)
{
int i;
struct ovni_loom *loom;
for(i=0; i<emu->trace.nlooms; i++)
{
loom = &emu->trace.loom[i];
if(strcmp(loom->hostname, host) == 0)
return loom;
}
return NULL;
}
static void
load_clock_offsets(struct ovni_emu *emu)
{
FILE *f;
char buf[1024];
int i, rank;
double offset, std;
char host[HOST_NAME_MAX];
struct ovni_loom *loom;
struct ovni_trace *trace;
struct ovni_stream *stream;
f = fopen(emu->clock_offset_file, "r");
if(f == NULL)
{
perror("fopen clock offset file failed\n");
abort();
}
/* Ignore header line */
fgets(buf, 1024, f);
while(fscanf(f, "%d %s %lf %lf", &rank, host, &offset, &std) == 4)
{
loom = find_loom_by_hostname(emu, host);
if(loom == NULL)
{
err("No loom has hostname %s\n", host);
abort();
}
if(loom->clock_offset != 0)
{
err("warning: loom at host %s already has a clock offset\n",
host);
}
loom->clock_offset = (int64_t) offset;
}
/* Then populate the stream offsets */
trace = &emu->trace;
for(i=0; i<trace->nstreams; i++)
{
stream = &trace->stream[i];
loom = &trace->loom[stream->loom];
stream->clock_offset = loom->clock_offset;
}
fclose(f);
}
static void
emu_init(struct ovni_emu *emu, int argc, char *argv[])
{
memset(emu, 0, sizeof(emu));
parse_args(emu, argc, argv);
if(ovni_load_trace(&emu->trace, emu->tracedir))
abort();
if(ovni_load_streams(&emu->trace))
abort();
if(load_metadata(emu) != 0)
abort();
if(emu->clock_offset_file != NULL)
load_clock_offsets(emu);
open_prvs(emu, emu->tracedir);
}
static void
emu_destroy(struct ovni_emu *emu)
{
close_prvs(emu);
destroy_metadata(emu);
ovni_free_streams(&emu->trace);
}
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
char *tracedir;
struct ovni_emu emu; struct ovni_emu emu;
if(argc != 2) emu_init(&emu, argc, argv);
{
fprintf(stderr, "missing tracedir\n");
exit(EXIT_FAILURE);
}
tracedir = argv[1];
memset(&emu, 0, sizeof(emu));
if(ovni_load_trace(&emu.trace, tracedir))
abort();
if(ovni_load_streams(&emu.trace))
abort();
if(load_metadata(&emu) != 0)
abort();
open_prvs(&emu, tracedir);
printf("#Paraver (19/01/38 at 03:14):00000000000000000000_ns:0:1:1(%d:1)\n", emu.total_cpus);
emulate(&emu); emulate(&emu);
close_prvs(&emu); emu_destroy(&emu);
destroy_metadata(&emu);
ovni_free_streams(&emu.trace);
return 0; return 0;
} }

13
emu.h
View File

@ -8,8 +8,6 @@
/* Debug macros */ /* Debug macros */
#define ENABLE_DEBUG
#ifdef ENABLE_DEBUG #ifdef ENABLE_DEBUG
# define dbg(...) fprintf(stderr, __VA_ARGS__); # define dbg(...) fprintf(stderr, __VA_ARGS__);
#else #else
@ -140,13 +138,15 @@ struct ovni_cpu {
/* State of each loom on post-process */ /* State of each loom on post-process */
struct ovni_loom { struct ovni_loom {
size_t nprocs; size_t nprocs;
char name[HOST_NAME_MAX]; char hostname[HOST_NAME_MAX];
int max_ncpus; int max_ncpus;
int max_phyid; int max_phyid;
int ncpus; int ncpus;
struct ovni_cpu cpu[OVNI_MAX_CPU]; struct ovni_cpu cpu[OVNI_MAX_CPU];
int64_t clock_offset;
/* Virtual CPU */ /* Virtual CPU */
struct ovni_cpu vcpu; struct ovni_cpu vcpu;
@ -173,6 +173,7 @@ struct ovni_stream {
int active; int active;
struct ovni_ev *cur_ev; struct ovni_ev *cur_ev;
uint64_t lastclock; uint64_t lastclock;
int64_t clock_offset;
}; };
struct ovni_emu { struct ovni_emu {
@ -187,12 +188,16 @@ struct ovni_emu {
struct nosv_task *cur_task; struct nosv_task *cur_task;
uint64_t lastclock; int64_t firstclock;
int64_t lastclock;
int64_t delta_time; int64_t delta_time;
FILE *prv_thread; FILE *prv_thread;
FILE *prv_cpu; FILE *prv_cpu;
char *clock_offset_file;
char *tracedir;
/* Total counters */ /* Total counters */
int total_thread; int total_thread;
int total_proc; int total_proc;

View File

@ -252,7 +252,9 @@ hook_pre_ovni(struct ovni_emu *emu)
{ {
case 'H': ev_thread(emu); break; case 'H': ev_thread(emu); break;
case 'A': ev_affinity(emu); break; case 'A': ev_affinity(emu); break;
case 'B': dbg("burst %c\n", emu->cur_ev->header.value); break; case 'B':
//dbg("burst %c\n", emu->cur_ev->header.value);
break;
default: default:
dbg("unknown ovni event class %c\n", dbg("unknown ovni event class %c\n",
emu->cur_ev->header.class); emu->cur_ev->header.class);

23
ovni.c
View File

@ -21,16 +21,6 @@
#include "ovni_trace.h" #include "ovni_trace.h"
#include "parson.h" #include "parson.h"
#define ENABLE_DEBUG
#ifdef ENABLE_DEBUG
#define dbg(...) fprintf(stderr, __VA_ARGS__);
#else
#define dbg(...)
#endif
#define err(...) fprintf(stderr, __VA_ARGS__);
//#define ENABLE_SLOW_CHECKS //#define ENABLE_SLOW_CHECKS
//#define USE_RDTSC //#define USE_RDTSC
@ -661,11 +651,7 @@ load_proc(struct ovni_eproc *proc, int index, int pid, char *procdir)
while((dirent = readdir(dir)) != NULL) while((dirent = readdir(dir)) != NULL)
{ {
if(find_dir_prefix_int(dirent, "thread", &tid) != 0) if(find_dir_prefix_int(dirent, "thread", &tid) != 0)
{
err("warning: ignoring bogus directory entry %s\n",
dirent->d_name);
continue; continue;
}
sprintf(path, "%s/%s", procdir, dirent->d_name); sprintf(path, "%s/%s", procdir, dirent->d_name);
@ -710,11 +696,7 @@ load_loom(struct ovni_loom *loom, int loomid, char *loomdir)
while((dirent = readdir(dir)) != NULL) while((dirent = readdir(dir)) != NULL)
{ {
if(find_dir_prefix_int(dirent, "proc", &pid) != 0) if(find_dir_prefix_int(dirent, "proc", &pid) != 0)
{
err("warning: ignoring bogus directory entry %s\n",
dirent->d_name);
continue; continue;
}
sprintf(path, "%s/%s", loomdir, dirent->d_name); sprintf(path, "%s/%s", loomdir, dirent->d_name);
@ -777,7 +759,7 @@ ovni_load_trace(struct ovni_trace *trace, char *tracedir)
loom = &trace->loom[i]; loom = &trace->loom[i];
/* FIXME: Unsafe */ /* FIXME: Unsafe */
strcpy(loom->name, loom_name); strcpy(loom->hostname, loom_name);
sprintf(path, "%s/%s", tracedir, dirent->d_name); sprintf(path, "%s/%s", tracedir, dirent->d_name);
@ -861,7 +843,7 @@ ovni_load_streams(struct ovni_trace *trace)
return -1; return -1;
} }
fprintf(stderr, "loaded %d streams\n", trace->nstreams); err("loaded %d streams\n", trace->nstreams);
for(s=0, i=0; i<trace->nlooms; i++) for(s=0, i=0; i<trace->nlooms; i++)
{ {
@ -918,7 +900,6 @@ ovni_load_next_event(struct ovni_stream *stream)
{ {
stream->cur_ev = (struct ovni_ev *) stream->buf; stream->cur_ev = (struct ovni_ev *) stream->buf;
stream->offset = 0; stream->offset = 0;
dbg("first event\n");
goto out; goto out;
} }