📄 grph.c
字号:
#include <stdio.h>
#include "mpi.h"
extern int __NUMNODES, __MYPROCID;
#include "mpptest.h"
#include "getopts.h"
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
/*
This file contains routines to generate output from the mpptest programs
*/
/*
In order to simplify the generation of graphs of multiple data sets,
we want to allow the generated cit code to contain the necessary
window selection commands. To do this, we add arguments for
-wx i n windows in x, my # and total #
-wy i n windows in y, my # and total #
-lastwindow generate the wait/new page.
*/
typedef enum { GRF_X, GRF_EPS, GRF_PS, GRF_GIF } OutputForm;
struct _GraphData {
FILE *fp, *fpdata;
char *fname2;
void (*header)( GraphData, char *, char *, char *);
void (*dataout)( GraphData, int, int, int, int, double, double, double,
double, double );
void (*draw)( GraphData, int, int, double, double );
void (*endpage)( GraphData );
/* For collective operations */
void (*headergop)( GraphData, char *, char *, char * );
void (*dataoutgop)( GraphData, int, double, double, double, double,
double );
void (*drawgop)( GraphData, int, int, double, double, int, int *);
void (*endgraph)( GraphData );
/* Information about the graph */
int wxi, wxn, wyi, wyn, is_lastwindow;
int givedy;
int do_rate;
int do_fit;
int is_log;
char *title;
OutputForm output_type;
};
/* Forward refs */
void HeaderCIt( GraphData ctx, char *protocol_name, char *title_string,
char *units );
void HeaderForGopCIt( GraphData ctx, char *test_name, char *title_string,
char *units );
void DrawCIt( GraphData ctx, int first, int last, double s, double r );
void DrawGopCIt( GraphData ctx, int first, int last, double s, double r,
int nsizes, int *sizelist );
void EndPageCIt( GraphData ctx );
void HeaderGnuplot( GraphData ctx, char *protocol_name,
char *title_string, char *units );
void HeaderForGopGnuplot( GraphData ctx, char *protocol_name,
char *title_string, char *units );
void DrawGnuplot( GraphData ctx, int first, int last, double s, double r );
void DrawGopGnuplot( GraphData ctx, int first, int last, double s,
double r, int nsizes, int *sizelist );
void EndPageGnuplot( GraphData ctx );
void ChangeToRate( GraphData, int );
void EndGraphCIt( GraphData );
void EndGraphGnuplot( GraphData );
void PrintGraphHelp( void )
{
fprintf( stderr, "\n\
Output\n\
-cit Generate data for CIt (default)\n\
-gnuplot Generate data for GNUPLOT\n\
-gnuploteps Generate data for GNUPLOT in Encapsulated Postscript\n\
-gnuplotps Generate data for GNUPLOT in Postscript\n\
-givedy Give the range of data measurements\n\
-rate Generate rate instead of time\n\
-fname filename (default is stdout)\n\
(opened for append, not truncated)\n\
-noinfo Do not generate plotter command lines or rate estimate\n\
-wx i n windows in x, my # and total #\n\
-wy i n windows in y, my # and total #\n\
-title string Use string as the title instead of the default title\n\
-lastwindow generate the wait/new page (always for 1 window)\n" );
}
void HeaderCIt( GraphData ctx, char *protocol_name, char *title_string,
char *units )
{
char archname[20], hostname[256], date[30], *p;
int dummy;
if (!ctx) return;
fprintf( ctx->fp, "set default\nset font variable\n" );
fprintf( ctx->fp, "set curve window y 0.15 0.90\n" );
if (ctx->wxn > 1 || ctx->wyn > 1)
fprintf( ctx->fp, "set window x %d %d y %d %d\n",
ctx->wxi, ctx->wxn, ctx->wyi, ctx->wyn );
if (ctx->givedy) {
/*fprintf( ctx->fp, "set order d d d x y d d d\n" )*/;
}
else {
if (ctx->do_rate)
fputs( "set order d d d x d y\n", ctx->fp );
else
fprintf( ctx->fp, "set order d d d x y d\n" );
}
if (ctx->is_log)
fprintf( ctx->fp, "set scale x log y log\n" );
if (ctx->do_rate)
fprintf( ctx->fp, "title left 'Rate (MB/sec)', bottom 'Size %s',\n",
units );
else
fprintf( ctx->fp, "title left 'time (us)', bottom 'Size %s',\n", units );
strcpy(archname,"MPI" );
MPI_Get_processor_name(hostname,&dummy);
/* Must remove ' from hostname */
p = hostname;
while (*p) {
if (*p == '\'') *p = ' ';
p++;
}
strcpy(date , "Not available" );
if (ctx->title) {
/* Eventually could replace %D with date, %H with hostname */
fprintf( ctx->fp, "top '%s'\n", ctx->title );
}
else {
/* For systems without a date routine, just leave off the data */
if (!date[0] || strcmp( "Not available", date ) == 0) {
fprintf( ctx->fp,
" top 'Comm Perf for %s (%s)',\n 'type = %s'\n",
archname, hostname, protocol_name );
}
else {
fprintf( ctx->fp,
" top 'Comm Perf for %s (%s)',\n 'on %s',\n 'type = %s'\n",
archname, hostname, date, protocol_name );
}
}
fprintf( ctx->fp, "\n#p0\tp1\tdist\tlen\tave time (us)\trate\n");
fflush( ctx->fp );
}
void HeaderForGopCIt( GraphData ctx, char *test_name, char *title_string,
char *units )
{
char archname[20], hostname[256], date[30], *p;
int dummy;
if (!ctx) return;
fprintf( ctx->fp, "set default\nset font variable\n" );
fprintf( ctx->fp, "set curve window y 0.15 0.90\n" );
if (ctx->wxn > 1 || ctx->wyn > 1)
fprintf( ctx->fp, "set window x %d %d y %d %d\n",
ctx->wxi, ctx->wxn, ctx->wyi, ctx->wyn );
fprintf( ctx->fp, "title left 'time (us)', bottom 'Processes',\n" );
strcpy(archname,"MPI" );
MPI_Get_processor_name(hostname,&dummy);
/* Must remove ' from hostname */
p = hostname;
while (*p) {
if (*p == '\'') *p = ' ';
p++;
}
strcpy(date , "Not available" );
if (ctx->title) {
/* Eventually could replace %D with date, %H with hostname */
fprintf( ctx->fp, "top '%s'\n", ctx->title );
}
else {
/* For systems without a date routine, just leave off the data */
if (!date[0] || strcmp( "Not available", date ) == 0) {
fprintf( ctx->fp,
" top 'Comm Perf for %s (%s)',\n 'type = %s'\n",
archname, hostname, test_name );
}
else {
fprintf( ctx->fp,
" top 'Comm Perf for %s (%s)',\n 'on %s',\n 'type = %s'\n",
archname, hostname, date, test_name );
}
}
fprintf( ctx->fp, "\n#np time (us) for various sizes\n");
fflush( ctx->fp );
}
/* Time in usec */
void DataoutGraph( GraphData ctx, int proc1, int proc2, int distance,
int len, double t, double mean_time, double rate,
double tmean, double tmax )
{
if (!ctx) return;
if(ctx->givedy)
fprintf( ctx->fpdata, "%d\t%d\t%d\t%d\t%f\t%.2f\t%f\t%f\n",
proc1, proc2, distance, len, tmean * 1.0e6, rate,
mean_time*1.0e6, tmax * 1.0e6 );
else {
/* Update to use e3 or e6 for rate */
fprintf( ctx->fpdata, "%d\t%d\t%d\t%d\t%f\t",
proc1, proc2, distance, len, mean_time*1.0e6 );
if (rate > 1.0e6) {
fprintf( ctx->fpdata, "%.3fe+6\n", rate * 1.0e-6 );
}
else if (rate > 1.0e3) {
fprintf( ctx->fpdata, "%.3fe+3\n", rate * 1.0e-3 );
}
else {
fprintf( ctx->fpdata, "%.2f\n", rate );
}
}
}
void DataoutGraphForGop( GraphData ctx, int len, double t, double mean_time,
double rate, double tmean, double tmax )
{
if (!ctx) return;
fprintf( ctx->fpdata, "%f ", mean_time*1.0e6 );
fflush( ctx->fpdata );
}
void DataendForGop( GraphData ctx )
{
if (!ctx) return;
fprintf( ctx->fpdata, "\n" );
}
void DatabeginForGop( GraphData ctx, int np )
{
if (!ctx) return;
fprintf( ctx->fpdata, "%d ", np );
}
void RateoutputGraph( GraphData ctx, double sumlen, double sumtime,
double sumlentime, double sumlen2, double sumtime2,
int ntest, double *S, double *R )
{
double s, r;
double variance = 0.0;
if (!ctx) return;
PIComputeRate( sumlen, sumtime, sumlentime, sumlen2, ntest, &s, &r );
s = s * 0.5;
r = r * 0.5;
/* Do we need to wait until AFTER the variance to scale s, r ? */
if (ntest > 1) {
variance = (1.0 / (ntest - 1.0)) *
(sumtime2 - 2.0 * s * sumtime - 2.0 * r * sumlentime +
ntest * s * s + 2.0 * r * sumlen + r * r * sumlen2 );
}
if (ctx->do_fit) {
fprintf( ctx->fp, "# Model complexity is (%e + n * %e)\n", s, r );
fprintf( ctx->fp, "# startup = " );
if (s > 1.0e-3)
fprintf( ctx->fp, "%.2f msec ", s * 1.0e3 );
else
fprintf( ctx->fp, "%.2f usec ", s * 1.0e6 );
fprintf( ctx->fp, "and transfer rate = " );
if (r > 1.e-6)
fprintf( ctx->fp, "%.2f Kbytes/sec\n", 1.0e-3 / r );
else
fprintf( ctx->fp, "%.2f Mbytes/sec\n", 1.0e-6 / r );
if (ntest > 1)
fprintf( ctx->fp, "# Variance in fit = %f (smaller is better)\n",
variance );
}
*S = s;
*R = r;
}
void DrawCIt( GraphData ctx, int first, int last, double s, double r )
{
if (!ctx) return;
/* Convert to one-way performance */
if (ctx->givedy) {
fprintf( ctx->fp, "set order d d d x y d d d\n" );
if (ctx->do_rate)
fputs( "set change y 'x * 1.0e-6'\n", ctx->fp );
fprintf( ctx->fp, "plot\n" );
fprintf( ctx->fp, "set order d d d x d d y d\n" );
if (ctx->do_rate)
fputs( "set change y 'x * 1.0e-6'\n", ctx->fp );
fprintf( ctx->fp, "join\n" );
fprintf( ctx->fp, "set order d d d x d d d y\n" );
if (ctx->do_rate)
fputs( "set change y 'x * 1.0e-6'\n", ctx->fp );
fprintf( ctx->fp, "join\n" );
}
else {
if (ctx->do_rate)
fputs( "set change y 'x * 1.0e-6'\n", ctx->fp );
fprintf( ctx->fp, "plot square\njoin\n" );
}
/* fit some times fails in Gnuplot; use the s and r parmeters instead */
/* fit '1'+'x'\njoin dots\n */
if (!ctx->do_rate && ctx->do_fit) {
fprintf( ctx->fp, "set function x %d %d '%f+%f*x'\n",
first, last, s*1.0e6, r*1.0e6 );
fprintf( ctx->fp, "join dots\n" );
}
}
void DrawGopCIt( GraphData ctx, int first, int last, double s, double r,
int nsizes, int *sizelist )
{
int i, j;
if (!ctx) return;
/* Do this in reverse order to help keep the scales correct */
fprintf( ctx->fp, "set limits ymin 0\n" );
for (i=nsizes-1; i>=0; i--) {
fprintf( ctx->fp, "set order x" );
for (j=0; j<i; j++)
fprintf( ctx->fp, " d" );
fprintf( ctx->fp, " y" );
for (j=i+1; j<nsizes; j++)
fprintf( ctx->fp, " d" );
fprintf( ctx->fp, "\nplot square\njoin '%d'\n", sizelist[i] );
}
}
/*
Redisplay using rate instead of time (not used yet)
*/
void ChangeToRate( GraphData ctx, int n_particip )
{
if (!ctx) return;
fprintf( ctx->fp, "set order d d d x d d y\njoin\n" );
}
/*
Generate an end-of-page
*/
void EndPageCIt( GraphData ctx )
{
if (!ctx) return;
if (ctx->is_lastwindow)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -