ROSS
st-stats-buffer.c
Go to the documentation of this file.
1 #include <ross.h>
2 #include <time.h>
3 #include <sys/stat.h>
4 
5 static long missed_bytes = 0;
6 static MPI_Offset *prev_offsets = NULL;
7 static MPI_File *buffer_fh = NULL;
9 int g_st_buffer_size = 8000000;
11 static int buffer_overflow_warned = 0;
12 static const char *file_suffix[NUM_COL_TYPES];
15 
17 {
19  return;
20 
21  int i, rc;
22 
23  // setup directory for instrumentation output
25  {
26  if (!g_st_stats_path[0])
27  sprintf(g_st_stats_path, "stats-output");
28  rc = mkdir(g_st_stats_path, S_IRUSR | S_IWUSR | S_IXUSR);
29  if (rc == -1)
30  {
31  sprintf(stats_directory, "%s-%ld-%ld", g_st_stats_path, (long)getpid(), (long)time(NULL));
32  mkdir(stats_directory, S_IRUSR | S_IWUSR | S_IXUSR);
33  }
34  else
35  sprintf(stats_directory, "%s", g_st_stats_path);
36  }
37 
38  // make sure everyone has the directory name
40 
41  // allocate buffer pointers
42  g_st_buffer = (st_stats_buffer**) tw_calloc(TW_LOC, "instrumentation (buffer)", sizeof(st_stats_buffer*), NUM_COL_TYPES);
43 
44  // setup MPI file offsets
45  if (!prev_offsets)
46  {
47  prev_offsets = (MPI_Offset*) tw_calloc(TW_LOC, "statistics collection (buffer)", sizeof(MPI_Offset), NUM_COL_TYPES);
48  for (i = 0; i < NUM_COL_TYPES; i++)
49  prev_offsets[i] = 0;
50  }
51 
52  // set up file handlers
53  if (!buffer_fh)
54  buffer_fh = (MPI_File*) tw_calloc(TW_LOC, "statistics collection (buffer)", sizeof(MPI_File), NUM_COL_TYPES);
55 
56 }
57 
58 /* initialize circular buffer for stats collection
59  * basically the read position marks the beginning of used space in the buffer
60  * while the write postion marks the end of used space in the buffer
61  */
62 void st_buffer_init(int type)
63 {
64  char filename[INST_MAX_LENGTH];
65  file_suffix[0] = "gvt";
66  file_suffix[1] = "rt";
67  file_suffix[2] = "analysis-lps";
68  file_suffix[3] = "evtrace";
69  file_suffix[4] = "model";
70 
71  g_st_buffer[type] = (st_stats_buffer*) tw_calloc(TW_LOC, "statistics collection (buffer)", sizeof(st_stats_buffer), 1);
72  g_st_buffer[type]->size = g_st_buffer_size;
73  g_st_buffer[type]->write_pos = 0;
74  g_st_buffer[type]->read_pos = 0;
75  g_st_buffer[type]->count = 0;
76  g_st_buffer[type]->buffer = (char*) tw_calloc(TW_LOC, "statistics collection (buffer)", 1, g_st_buffer[type]->size);
77 
78  // set up MPI File
79  if (!g_st_disable_out)
80  {
81  if (!g_st_stats_out[0])
82  sprintf(g_st_stats_out, "ross-stats");
83  sprintf(filename, "%s/%s-%s.bin", stats_directory, g_st_stats_out, file_suffix[type]);
85  MPI_File_open(MPI_COMM_ROSS, filename, MPI_MODE_CREATE | MPI_MODE_EXCL | MPI_MODE_WRONLY, MPI_INFO_NULL, &buffer_fh[type]);
86  else if (strcmp(file_suffix[type], "evtrace") == 0 && g_tw_synchronization_protocol == SEQUENTIAL)
87  seq_ev_trace = fopen(filename, "w");
88  else if (strcmp(file_suffix[type], "model") == 0 && g_tw_synchronization_protocol == SEQUENTIAL)
89  seq_model = fopen(filename, "w");
91  seq_analysis = fopen(filename, "w");
92 
93  }
94 }
95 
96 /* write stats to buffer
97  * currently does not overwrite in cases of overflow, just records the amount of overflow in bytes
98  * for later reporting
99  */
100 void st_buffer_push(int type, char *data, int size)
101 {
102  int size1, size2;
103  if (!g_st_disable_out && st_buffer_free_space(g_st_buffer[type]) < size)
104  {
106  {
107  printf("WARNING: Stats buffer overflow on rank %lu\n", g_tw_mynode);
109  printf("tw_now() = %f\n", TW_STIME_DBL(tw_now(g_tw_lp[0])));
110  }
111  missed_bytes += size;
112  size = 0; // if we can't push it all, don't push anything to buffer
113  }
114 
115  if (size)
116  {
117  if ((size1 = g_st_buffer[type]->size - g_st_buffer[type]->write_pos) >= size)
118  {
119  // can use only one memcpy here
120  memcpy(st_buffer_write_ptr(g_st_buffer[type]), data, size);
121  g_st_buffer[type]->write_pos += size;
122  }
123  else // data to be stored wraps around end of physical array
124  {
125  size2 = size - size1;
126  memcpy(st_buffer_write_ptr(g_st_buffer[type]), data, size1);
127  memcpy(g_st_buffer[type]->buffer, data + size1, size2);
128  g_st_buffer[type]->write_pos = size2;
129  }
130  }
131  g_st_buffer[type]->count += size;
132  //printf("PE %ld wrote %d bytes to buffer; %d bytes of free space left\n", g_tw_mynode, size, st_buffer_free_space(g_st_buffer[type]));
133 }
134 
135 /* determine whether to dump buffer to file
136  * should only be called at GVT! */
137 void st_buffer_write(int end_of_sim, int type)
138 {
139  MPI_Offset offset = prev_offsets[type];
140  MPI_File *fh = &buffer_fh[type];
141  int write_to_file = 0;
142  int my_write_size = 0;
143  unsigned int i;
144  int write_sizes[tw_nnodes()];
145  tw_clock start_cycle_time = tw_clock_read();
146 
147  my_write_size = g_st_buffer[type]->count;
148 
149  MPI_Allgather(&my_write_size, 1, MPI_INT, &write_sizes[0], 1, MPI_INT, MPI_COMM_ROSS);
150  if (end_of_sim)
151  write_to_file = 1;
152  else
153  {
154  for (i = 0; i < tw_nnodes(); i++)
155  {
156  if ((double) write_sizes[i] / g_st_buffer_size >= g_st_buffer_free_percent / 100.0)
157  write_to_file = 1;
158  }
159  }
160 
161  if (write_to_file)
162  {
163  for (i = 0; i < tw_nnodes(); i++)
164  {
165  if (i < g_tw_mynode)
166  offset += write_sizes[i];
167  prev_offsets[type] += write_sizes[i];
168  }
169  //printf("rank %ld writing %d bytes at offset %lld (prev_offsets[ANALYSIS_LP] = %lld)\n", g_tw_mynode, my_write_size, offset, prev_offsets[type]);
170  // dump buffer to file
171  MPI_Status status;
172  g_tw_pe->stats.s_stat_comp += tw_clock_read() - start_cycle_time;
173  start_cycle_time = tw_clock_read();
174  MPI_File_write_at_all(*fh, offset, st_buffer_read_ptr(g_st_buffer[type]), my_write_size, MPI_BYTE, &status);
175  g_tw_pe->stats.s_stat_write += tw_clock_read() - start_cycle_time;
176 
177  // reset the buffer
178  g_st_buffer[type]->write_pos = 0;
179  g_st_buffer[type]->read_pos = 0;
180  g_st_buffer[type]->count = 0;
182  }
183  else
184  g_tw_pe->stats.s_stat_comp += tw_clock_read() - start_cycle_time;
185 }
186 
187 /* make sure we write out any remaining buffer data */
188 void st_buffer_finalize(int type)
189 {
190  // check if any data needs to be written out
191  if (!g_st_disable_out)
192  st_buffer_write(1, type);
193 
194  printf("PE %ld: There were %ld bytes of data missed because of buffer overflow\n", g_tw_mynode, missed_bytes);
195 
196  MPI_File_close(&buffer_fh[type]);
197 
198 }
tw_synch g_tw_synchronization_protocol
Definition: ross-global.c:18
#define TW_LOC
Definition: ross-extern.h:164
char g_st_stats_path[4096]
tw_lp ** g_tw_lp
Definition: ross-global.c:26
static st_stats_buffer ** g_st_buffer
void st_buffer_push(int type, char *data, int size)
void st_buffer_write(int end_of_sim, int type)
int g_st_buffer_free_percent
tw_statistics stats
per PE counters
Definition: ross-types.h:415
static MPI_Offset * prev_offsets
FILE * seq_model
static tw_clock tw_clock_read(void)
Definition: aarch64.h:6
int g_st_engine_stats
FILE * seq_ev_trace
MPI_Comm MPI_COMM_ROSS
Definition: network-mpi.c:4
tw_clock s_stat_comp
Definition: ross-types.h:151
unsigned int tw_nnodes(void)
Definition: network-mpi.c:103
void st_buffer_allocate()
#define INST_MAX_LENGTH
void st_buffer_init(int type)
static int buffer_overflow_warned
int g_st_buffer_size
#define st_buffer_free_space(buf)
#define st_buffer_write_ptr(buf)
tw_clock s_stat_write
Definition: ross-types.h:152
int g_st_use_analysis_lps
static long missed_bytes
static tw_stime tw_now(tw_lp const *lp)
tw_peid g_tw_mynode
Definition: ross-global.c:88
tw_peid g_tw_masternode
Definition: ross-global.c:89
#define st_buffer_read_ptr(buf)
FILE * seq_analysis
int g_st_model_stats
tw_pe * g_tw_pe
Definition: ross-global.c:75
uint64_t tw_clock
Definition: aarch64.h:4
int g_st_ev_trace
Definition: st-event-trace.c:3
static const char * file_suffix[NUM_COL_TYPES]
static MPI_File * buffer_fh
int g_st_disable_out
char g_st_stats_out[INST_MAX_LENGTH]
void * tw_calloc(const char *file, int line, const char *for_who, size_t e_sz, size_t n)
Definition: tw-util.c:203
void st_buffer_finalize(int type)
#define TW_STIME_DBL(x)
Definition: ross.h:153
char stats_directory[INST_MAX_LENGTH]