MACSio  0.9
Multi-purpose, Application-Centric, Scalable I/O Proxy App
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
probe.c
Go to the documentation of this file.
1 /*
2 Copyright (c) 2015, Lawrence Livermore National Security, LLC.
3 Produced at the Lawrence Livermore National Laboratory.
4 Written by Mark C. Miller
5 
6 LLNL-CODE-676051. All rights reserved.
7 
8 This file is part of MACSio
9 
10 Please also read the LICENSE file at the top of the source code directory or
11 folder hierarchy.
12 
13 This program is free software; you can redistribute it and/or modify it under
14 the terms of the GNU General Public License (as published by the Free Software
15 Foundation) version 2, dated June 1991.
16 
17 This program is distributed in the hope that it will be useful, but WITHOUT
18 ANY WARRANTY; without even the IMPLIED WARRANTY OF MERCHANTABILITY or FITNESS
19 FOR A PARTICULAR PURPOSE. See the terms and conditions of the GNU General
20 Public License for more details.
21 
22 You should have received a copy of the GNU General Public License along with
23 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
24 Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26 
27 #include <assert.h>
28 #include <math.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <sys/time.h>
32 #include <unistd.h>
33 
34 #ifdef USE_MPI
35 #include <mpi.h>
36 #endif
37 
38 #define BUF_SIZE ((size_t)1<<27) /* 1/8th Gigabyte */
39 #define TOT_BUFS 8192 /* 1024 Gigabytes */
40 
41 static int buf_ids[TOT_BUFS];
42 
43 /* return time in micro-seconds to randomly stride
44  (a fraction of a pagesize) through all bufs
45  normalized by the number of samples taken. */
46 static double time_random_accesses(char **bufs, int nbufs, double *dummy_sum)
47 {
48  struct timeval tv0, tv1;
49 #ifdef _SC_PAGESIZE
50  int pagesize = (int) sysconf(_SC_PAGESIZE);
51 #elif PAGESIZE
52  int pagesize = (int) sysconf(PAGESIZE);
53 #endif
54  unsigned long long i = random() % pagesize;
55  unsigned long long maxi = nbufs * BUF_SIZE;
56  int n = 1;
57 
58  gettimeofday(&tv0, 0);
59  double sum = 0;
60  while (i < maxi)
61  {
62  char testval = *(bufs[i/BUF_SIZE] + i%BUF_SIZE);
63  sum += ((double) ((int) testval));
64  *(bufs[i/BUF_SIZE] + i%BUF_SIZE) = 'M';
65  i += (random() % pagesize);
66  n++;
67  }
68  gettimeofday(&tv1, 0);
69  *dummy_sum = sum;
70 
71  return (double) (tv1.tv_sec*1e+6+tv1.tv_usec-(tv0.tv_sec*1e+6+tv0.tv_usec))/n;
72 }
73 
74 int main(int argc, char **argv)
75 {
76  char *bufs[TOT_BUFS];
77  size_t size = 0;
78  int done = 0, alldone;
79  int i = 0;
80  double mean=0, var=0;
81  int mpirank = 0;
82  int mpisize = 1;
83  int mpierr;
84  char outfname[64];
85  FILE *outf;
86 
87 #ifdef USE_MPI
88  MPI_Init(&argc, &argv);
89  MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
90  MPI_Comm_size(MPI_COMM_WORLD, &mpisize);
91  MPI_Comm_rank(MPI_COMM_WORLD, &mpirank);
92 #endif
93 
94  if (mpisize == 1)
95  snprintf(outfname, sizeof(outfname), "probe.txt");
96  else
97  snprintf(outfname, sizeof(outfname), "probe-%05d.txt", mpirank);
98  outf = fopen(outfname, "w");
99  setbuf(outf, 0);
100 
101  /* loop to allocate more memory and test time to randomly access it */
102  srandom(0xDeadBeef);
103  fprintf(outf, "Size(Gb)\tSpeed(us)\tMean \tStDev\n");
104  while (!alldone)
105  {
106  double speed, size, dummy, lmean, stdev;
107  int nlong = 0;
108  bufs[i] = (char*) calloc(BUF_SIZE,1);
109  if (!bufs[i])
110  {
111  int j;
112  for (j = 0; j < i; j++)
113  free(bufs[j]);
114  break;
115  }
116  /* why 2 calls? Mallocs above don't actually do anything. The
117  memory is only allocated when its written to. So, first call
118  ensures all mallocs are indeed allocated. Second call then
119  times access w/o costs of lazy allocation involved */
120  speed = time_random_accesses(bufs, i+1, &dummy);
121  dummy = 0;
122  speed = time_random_accesses(bufs, i+1, &dummy);
123  lmean = mean;
124  mean = mean + (speed-mean)/(i+1);
125  var = var + (speed-mean)*(speed-lmean);
126  stdev = sqrt(var/(i+1));
127  size = (double) (i+1) * (double) BUF_SIZE / pow(2,30);
128  fprintf(outf, "%8.4f\t%8.4f\t%8.4f\t%8.4f\n", size, speed, mean, stdev);
129  if (i > 3 && speed > mean + 1.5*stdev)
130  {
131  nlong++;
132  if (nlong > 1) done = 1;
133  }
134  else
135  {
136  nlong = 0;
137  }
138 #if USE_MPI
139  mpierr = MPI_Allreduce(&done, &alldone, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
140  if (mpierr != MPI_SUCCESS)
141  break;
142 #else
143  alldone = done;
144 #endif
145  i++;
146  }
147  fclose(outf);
148 
149 #if USE_MPI
150  MPI_Finalize();
151 #endif
152 
153 }
#define TOT_BUFS
Definition: probe.c:39
static double time_random_accesses(char **bufs, int nbufs, double *dummy_sum)
Definition: probe.c:46
static int dummy
int main(int argc, char **argv)
Definition: probe.c:74
#define BUF_SIZE
Definition: probe.c:38
static int buf_ids[TOT_BUFS]
Definition: probe.c:41