mirror of
https://github.com/HDFGroup/hdf5.git
synced 2024-11-27 02:10:55 +08:00
237fc48acb
Update code Description: Incorporate Pablo support patches from Dan Wells Platforms tested: FreeBSD 4.8 (sleipnir) h5committest
1687 lines
59 KiB
C
1687 lines
59 KiB
C
/* This file is part of the Pablo Performance Analysis Environment
|
|
//
|
|
// (R)
|
|
// The Pablo Performance Analysis Environment software is NOT in
|
|
// the public domain. However, it is freely available without fee for
|
|
// education, research, and non-profit purposes. By obtaining copies
|
|
// of this and other files that comprise the Pablo Performance Analysis
|
|
// Environment, you, the Licensee, agree to abide by the following
|
|
// conditions and understandings with respect to the copyrighted software:
|
|
//
|
|
// 1. The software is copyrighted in the name of the Board of Trustees
|
|
// of the University of Illinois (UI), and ownership of the software
|
|
// remains with the UI.
|
|
//
|
|
// 2. Permission to use, copy, and modify this software and its documentation
|
|
// for education, research, and non-profit purposes is hereby granted
|
|
// to Licensee, provided that the copyright notice, the original author's
|
|
// names and unit identification, and this permission notice appear on
|
|
// all such copies, and that no charge be made for such copies. Any
|
|
// entity desiring permission to incorporate this software into commercial
|
|
// products should contact:
|
|
//
|
|
// Professor Daniel A. Reed reed@cs.uiuc.edu
|
|
// University of Illinois
|
|
// Department of Computer Science
|
|
// 2413 Digital Computer Laboratory
|
|
// 1304 West Springfield Avenue
|
|
// Urbana, Illinois 61801
|
|
// USA
|
|
//
|
|
// 3. Licensee may not use the name, logo, or any other symbol of the UI
|
|
// nor the names of any of its employees nor any adaptation thereof in
|
|
// advertizing or publicity pertaining to the software without specific
|
|
// prior written approval of the UI.
|
|
//
|
|
// 4. THE UI MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE
|
|
// SOFTWARE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS
|
|
// OR IMPLIED WARRANTY.
|
|
//
|
|
// 5. The UI shall not be liable for any damages suffered by Licensee from
|
|
// the use of this software.
|
|
//
|
|
// 6. The software was developed under agreements between the UI and the
|
|
// Federal Government which entitle the Government to certain rights.
|
|
//
|
|
// *************************************************************************
|
|
//
|
|
// Developed by: The Pablo Research Group
|
|
// University of Illinois at Urbana-Champaign
|
|
// Department of Computer Science
|
|
// 1304 W. Springfield Avenue
|
|
// Urbana, IL 61801
|
|
//
|
|
// http://www-pablo.cs.uiuc.edu
|
|
//
|
|
// Send comments to: pablo-feedback@guitar.cs.uiuc.edu
|
|
//
|
|
// Copyright (c) 1987-1998
|
|
// The University of Illinois Board of Trustees.
|
|
// All Rights Reserved.
|
|
//
|
|
// PABLO is a registered trademark of
|
|
// The Board of Trustees of the University of Illinois
|
|
// registered in the U.S. Patent and Trademark Office.
|
|
//
|
|
// Project Manager and Principal Investigator:
|
|
// Daniel A. Reed (reed@cs.uiuc.edu)
|
|
//
|
|
// Funded in part by the Defense Advanced Research Projects Agency
|
|
// under DARPA contracts DABT63-94-C0049 (SIO Initiative),
|
|
// F30602-96-C-0161, and DABT63-96-C-0027 by the National Science
|
|
// Foundation under the PACI program and grants NSF CDA 94-01124 and
|
|
// ASC 97-20202, and by the Department of Energy under contracts
|
|
// DOE B-341494, W-7405-ENG-48, and 1-B-333164.
|
|
*/
|
|
/*======================================================================*
|
|
// File: PabloHDF_RT *
|
|
// Purpose: support use of Pablo trace library to analyze HDF *
|
|
// performance *
|
|
// Contents: *
|
|
// HDFinitTrace_RT : initialize real-time tracing *
|
|
// HDFendTrace_RT : complete trace *
|
|
// initHDFProcTrace_RT : sets up data structures at init time. *
|
|
// initproctracert_() : fortran interface *
|
|
// HDFtraceEvent_RT : called to record event information *
|
|
// HDFrecordSum : adds fields of one record to those of *
|
|
// another *
|
|
// HDFnodeInit : initializes linked list node *
|
|
// HDFrecordFileName : records named HDF identifiers *
|
|
// BeginIOEventRecord : initialize before I/O call *
|
|
// EndIOEventRecord : finalize after I/O call *
|
|
// BeginMPIOEventRecord : initialize before MPI-I/O call *
|
|
// EndMPIOEventRecord : finalize after MPI-I/O call *
|
|
// BeginHDFEventRecord : initialize before HDF call *
|
|
// EndHDFEventRecord : finalizie after HDF call *
|
|
// HDFrecordFileName : record named identifier information *
|
|
// HDFassignPabloIDs : assigns a number to named identifiers *
|
|
// writeHDFNamePacketsRT : write SDDF packets for identifier names *
|
|
// HDFupdateProcLists : adds records in queue to entries in *
|
|
// tables *
|
|
// HDFupdateProcs : called by HDFupdateProcLists to do *
|
|
// addition *
|
|
// HDFSummarySDDF : write SDDF event summary packets *
|
|
// HDFnodeInit : initialize event node *
|
|
// HDFrecordSum : add one event record to another *
|
|
// getHDFFieldIndex : get Field Index for counts and times *
|
|
// getHDFByteFieldIndex : get field index for bytes *
|
|
// writeHDFRecDescrptrsRT : write HDF Record Descriptor packets *
|
|
// printFileMappingsRT : print map of named identifiers *
|
|
// _hdfNameDescriptor() : writes SDDF descriptor packet for names *
|
|
//======================================================================*/
|
|
#ifndef PCF_BUILD
|
|
#ifdef _HDF5_
|
|
#include "H5config.h"
|
|
#endif
|
|
#include "SystemDepend.h"
|
|
#include "Trace.h"
|
|
#include "TraceParam.h"
|
|
#include "ProcIDs.h"
|
|
#include "IO_TraceParams.h"
|
|
#include "IOTrace.h"
|
|
#include "HDFTrace.h"
|
|
#include "SDDFparam.h"
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <fcntl.h>
|
|
/*======================================================================*
|
|
// on ipsc/860 don't include this or you'll get multiply defined SEEK_ *
|
|
//======================================================================*/
|
|
#ifndef __NX
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#ifndef SUCCESS
|
|
#define SUCCESS 0
|
|
#define FAILURE 1
|
|
#endif
|
|
|
|
#ifndef TRUE
|
|
#define TRUE 1
|
|
#define FALSE 0
|
|
#endif
|
|
#define NEG_THREAD_ID -999
|
|
|
|
#include "HDFrecord_RT.h"
|
|
|
|
#ifdef H5_HAVE_MPIOTRACE
|
|
#include "mpi.h"
|
|
#include "MPIO_EventArgs.h"
|
|
#endif
|
|
|
|
#ifndef TRgetThreadID
|
|
#define TRgetThreadID TRgetNode
|
|
#endif
|
|
|
|
#ifndef TRnumNodes
|
|
#define TRnumNodes 1
|
|
#endif
|
|
|
|
#define AllThreads -1
|
|
|
|
/*======================================================================*
|
|
// User output file pointer. *
|
|
//======================================================================*/
|
|
FILE *outP;
|
|
/*======================================================================*
|
|
// Data Structures: *
|
|
// *
|
|
// HDFQueues: an array of linked list. Each list corresponds to an *
|
|
// HDF event and contains an entry for each different *
|
|
// thread and data set referenced by a call to that event *
|
|
// *
|
|
// CallStack: a stack of HDFnode_t objects. At any given time, the *
|
|
// stack represents the calling stack of the HDF routines *
|
|
// *
|
|
// HDFfileList: a linked list of named identifiers and identifier *
|
|
// numbers. This is processed later to assign a single *
|
|
// numbers to identifiers with the same name. *
|
|
//======================================================================*/
|
|
HDFnode_t **HDFQueues;
|
|
HDFnode_t *CallStack;
|
|
HDFnode_t *TagQueue;
|
|
fileRec_t *HDFfileList;
|
|
/*======================================================================*
|
|
// Internal Function prototypes *
|
|
//======================================================================*/
|
|
void HDFinitTrace_RT( char *, int, int );
|
|
void HDFendTrace_RT();
|
|
int initproctracert_( void );
|
|
int initHDFProcTrace_RT( void );
|
|
void HDFtraceEvent_RT( int , char *, unsigned ) ;
|
|
void BeginIOEventRecord ( int, CLOCK , void * );
|
|
void EndIOEventRecord ( int , CLOCK , void * );
|
|
void BeginMPIOEventRecord ( int, CLOCK , void *, int );
|
|
void EndMPIOEventRecord ( int , CLOCK , void *, int);
|
|
void BeginHDFEventRecord( int , CLOCK );
|
|
void EndHDFEventRecord ( CLOCK ,void *);
|
|
void HDFrecordFileName( HDFsetInfo * );
|
|
void HDFassignPabloIDs( int *, char *** );
|
|
void writeHDFNamePacketsRT( char **, int );
|
|
void HDFupdateProcLists( void );
|
|
void HDFupdateProcs( HDFnode_t * );
|
|
void HDFSummarySDDF( HDFnode_t *, int );
|
|
void HDFnodeInit ( HDFnode_t * ) ;
|
|
void HDFrecordSum ( HDFrec_t *, HDFrec_t * );
|
|
int getHDFFieldIndex( int );
|
|
int getHDFByteFieldIndex( int );
|
|
void writeHDFRecDescrptrsRT( void );
|
|
void printFileMappingsRT( char *, char **, int );
|
|
void _hdfNameDescriptor( void );
|
|
void _hdfDescriptorRT( char *, char *, int );
|
|
void HDFfinalTimeStamp( void );
|
|
void getHDFprocName( int index, char buff[41] );
|
|
void IOtraceInit( char*, int, int );
|
|
/*======================================================================*
|
|
// Global variables *
|
|
//======================================================================*/
|
|
HDFnode_t InitNode; /* Node used in initialization */
|
|
HDFrec_t Tally; /* Node used to get total */
|
|
char *FileName; /* Name of Trace file */
|
|
HDFsetInfo openInfo; /* Info about file opened */
|
|
char openName[256]; /* Name of opened file */
|
|
extern char *hdfRecordPointer;
|
|
extern char HDFprocNames[][40];
|
|
/*======================================================================*
|
|
// NAME *
|
|
// HDFinitTrace_RT-- initialize HDF real-time tracing *
|
|
// USAGE *
|
|
// VOID HDFinitTrace_RT( fileName ) *
|
|
// *
|
|
// char *fileName; IN: name of output file *
|
|
// RETURNS *
|
|
// None. *
|
|
//======================================================================*/
|
|
void HDFinitTrace_RT( char *fileName, int procNum, int OUTSW )
|
|
{
|
|
int error;
|
|
TRgetClock( &epoch );
|
|
error = initHDFProcTrace_RT() ;
|
|
if ( error != SUCCESS )
|
|
{
|
|
fprintf (stderr,"Unable to Initialize properly. Exiting program\n");
|
|
exit(-1);
|
|
}
|
|
FileName = ( char * ) malloc ( strlen( fileName ) + 10 );
|
|
/*===================================================================*
|
|
// Here the library was built to linked with the MPI and MPIO *
|
|
// libraries. However, the use may chose not to run with MPI. *
|
|
// A check is made to see if MPI has been initialized. If so, *
|
|
// a trace file is assigned to the current node with the number *
|
|
// of the node as a suffix; if not, only one file is opened *
|
|
// and it is not given a suffix. *
|
|
//===================================================================*/
|
|
IOtraceInit( fileName, procNum, OUTSW );
|
|
}
|
|
/*======================================================================*
|
|
// NAME *
|
|
// HDFendTrace-- end HDF tracing *
|
|
// USAGE *
|
|
// VOID HDFendTrace_RT(void) *
|
|
// RETURNS *
|
|
// None. *
|
|
//======================================================================*/
|
|
void HDFendTrace_RT( )
|
|
{
|
|
int j, numSetIDs;
|
|
HDFnode_t *P;
|
|
char **Names;
|
|
|
|
HDFfinalTimeStamp();
|
|
/*===================================================================*
|
|
// Assing pablo ids to named identifiers and tag records *
|
|
//===================================================================*/
|
|
HDFassignPabloIDs( &numSetIDs, &Names );
|
|
/*===================================================================*
|
|
// Create a file name for the File map file. *
|
|
// Disable for now. *
|
|
//===================================================================*/
|
|
/* mapFile = (char *)malloc( strlen(FileName) + 4 );
|
|
strcpy(mapFile,FileName);
|
|
strcat(mapFile,".map"); */
|
|
/*===================================================================*
|
|
// print the file mappings. *
|
|
//===================================================================*/
|
|
/* printFileMappingsRT( mapFile, Names, numSetIDs ); */
|
|
/*===================================================================*
|
|
// Print SDDF summary records *
|
|
//===================================================================*/
|
|
writeHDFRecDescrptrsRT();
|
|
writeHDFNamePacketsRT( Names, numSetIDs );
|
|
for ( j = 0; j < NumHDFProcs; ++j ) {
|
|
HDFSummarySDDF( HDFQueues[j], j );
|
|
}
|
|
endTracing();
|
|
}
|
|
/*======================================================================*
|
|
// initHFDProcTrace_RT *
|
|
// This function initializes data structures specific to *
|
|
// the HDF real-time procedure entry/exit tracing extensions of *
|
|
// the Pablo instrumentation library. *
|
|
//======================================================================*/
|
|
int initproctracert_( void )
|
|
|
|
{
|
|
return initHDFProcTrace_RT();
|
|
}
|
|
|
|
int initHDFProcTrace_RT( void )
|
|
{
|
|
int i;
|
|
int j;
|
|
int size;
|
|
int numProcs = NumHDFProcs;
|
|
|
|
if ( traceProcessorNumber == -1 )
|
|
{
|
|
traceProcessorNumber = TRgetDefaultProcessor();
|
|
}
|
|
/*===================================================================*
|
|
// Initialize InitNode used for node initialization. *
|
|
//===================================================================*/
|
|
InitNode.ptr = NULL;
|
|
InitNode.eventID = 0;
|
|
InitNode.lastIOtime = zeroClock;
|
|
InitNode.record.nCalls = 0;
|
|
InitNode.record.lastCall = zeroClock;
|
|
InitNode.record.incDur = zeroClock;
|
|
InitNode.record.excDur = zeroClock;
|
|
InitNode.record.hdfID = 0;
|
|
InitNode.record.xRef = 0;
|
|
for ( j = 0; j < nTallyFields; ++j )
|
|
{
|
|
InitNode.record.times[j] = zeroClock;
|
|
}
|
|
for ( j = 0; j < nTallyFields; ++j )
|
|
{
|
|
InitNode.record.counts[j] = 0;
|
|
}
|
|
for ( j = 0; j < nByteFields; ++j )
|
|
{
|
|
InitNode.record.bytes[j] = 0;
|
|
}
|
|
for ( i = 0; i < nByteFields; ++i )
|
|
{
|
|
for ( j = 0; j < nBkts; ++j )
|
|
{
|
|
InitNode.record.Hists[i][j] = 0;
|
|
}
|
|
}
|
|
/*===================================================================*
|
|
// initialize linked list used to keep track of named hdf *
|
|
// identifiers. *
|
|
//===================================================================*/
|
|
HDFfileList = NULL;
|
|
/*===================================================================*
|
|
// Allocate a one dimensional array of pointers to queues of *
|
|
// HDFnodes. There is one queue for each thread and one for *
|
|
// each HDF procedure. Each queue will be a list of summary *
|
|
// records distinquished by file type and *
|
|
//===================================================================*/
|
|
size = (int)(numProcs*sizeof( HDFnode_t * ));
|
|
HDFQueues = (HDFnode_t **)malloc( size );
|
|
if ( HDFQueues == NULL )
|
|
{
|
|
fprintf(stderr,"Failed to allocate HDFQueues in initHDFProcTrace\n");
|
|
return FAILURE;
|
|
}
|
|
for ( j = 0; j < numProcs; ++j )
|
|
{
|
|
HDFQueues[j] = NULL;
|
|
}
|
|
/*===================================================================*
|
|
// Initialize call stack to a dummy node and TagQueue to NULL *
|
|
//===================================================================*/
|
|
CallStack = (HDFnode_t *)malloc( sizeof(HDFnode_t) );
|
|
*CallStack = InitNode;
|
|
TagQueue = NULL ;
|
|
return SUCCESS;
|
|
}
|
|
/*======================================================================*
|
|
// This is called from the HDF and I/O routines when real-time summary *
|
|
// tracing is used. It sets up a call stack for the specific thread in *
|
|
// use if no stack is yet set up. It then calls calls a routine to *
|
|
// handle the event based on whether it is an I/O or HDF call. *
|
|
//======================================================================*/
|
|
void HDFtraceEvent_RT( int eventType, char *dataPtr, unsigned dataLen )
|
|
{
|
|
CLOCK seconds;
|
|
|
|
seconds = getClock();
|
|
|
|
if ( isBeginIOEvent ( eventType ) || eventType == ID_malloc )
|
|
{
|
|
BeginIOEventRecord ( eventType, seconds, dataPtr ) ;
|
|
}
|
|
else if ( isEndIOEvent( eventType ) || eventType == -ID_malloc)
|
|
{
|
|
EndIOEventRecord ( eventType, seconds, dataPtr );
|
|
}
|
|
else if ( isBeginHDFEvent( eventType ) )
|
|
{
|
|
BeginHDFEventRecord ( eventType , seconds ) ;
|
|
}
|
|
else if ( isEndHDFEvent( eventType ) )
|
|
{
|
|
EndHDFEventRecord ( seconds, dataPtr );
|
|
#ifdef H5_HAVE_MPIOTRACE
|
|
}
|
|
else if ( isBeginMPIOEvent( eventType ) )
|
|
{
|
|
BeginMPIOEventRecord ( eventType, seconds, dataPtr, dataLen ) ;
|
|
}
|
|
else if ( isEndMPIOEvent( eventType ) )
|
|
{
|
|
EndMPIOEventRecord ( eventType, seconds, dataPtr, dataLen );
|
|
#endif /* H5_HAVE_MPIOTRACE */
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr,"eventType %d, dataLen = %u\n",eventType,dataLen);
|
|
}
|
|
}
|
|
/*======================================================================*
|
|
// BeginIOEventRecord: *
|
|
// This routine simply records the time in the record on the top of *
|
|
// the stack. *
|
|
//======================================================================*/
|
|
void BeginIOEventRecord ( int eventType, CLOCK seconds, void *dataPtr )
|
|
{
|
|
char *name;
|
|
/*===================================================================*
|
|
// save the time value temporarily in top of stack *
|
|
// When the end record is received, the duration can be computed. *
|
|
//===================================================================*/
|
|
CallStack->lastIOtime = seconds;
|
|
/*===================================================================*
|
|
// get the ID or name of the file accessed from the structure *
|
|
// passed as dataPtr. *
|
|
//===================================================================*/
|
|
switch ( eventType )
|
|
{
|
|
case fopenBeginID:
|
|
case openBeginID:
|
|
{
|
|
name = (char *)(dataPtr) + 2*sizeof(int);
|
|
strcpy( openName, name );
|
|
break;
|
|
}
|
|
case fcloseBeginID:
|
|
case closeBeginID:
|
|
{
|
|
CallStack->record.hdfID = *( long *)dataPtr;
|
|
break;
|
|
}
|
|
case readBeginID:
|
|
case freadBeginID:
|
|
case writeBeginID:
|
|
case fwriteBeginID:
|
|
case lseekBeginID:
|
|
case fseekBeginID:
|
|
case fsetposBeginID:
|
|
case rewindBeginID:
|
|
{
|
|
CallStack->record.hdfID = *(int *)dataPtr;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
/*======================================================================*
|
|
// EndIOEventRecord: *
|
|
// This routine retrieves the entry time saved on the top of the stack *
|
|
// and computes the duration of the I/O event. This is added to the *
|
|
// record field corresponding to this type of I/O. The Bytes field in *
|
|
// the record is updated if this is a read or write operation. *
|
|
//======================================================================*/
|
|
void EndIOEventRecord ( int eventType, CLOCK secs, void *dataPtr )
|
|
{
|
|
CLOCK incDur;
|
|
int i, Field, ByteField, bytes;
|
|
|
|
incDur = clockSubtract(secs,CallStack->lastIOtime) ;
|
|
Field = getHDFFieldIndex( eventType ) ;
|
|
CallStack->record.times[Field]
|
|
= clockAdd ( CallStack->record.times[Field] , incDur ) ;
|
|
++CallStack->record.counts[Field];
|
|
ByteField = getHDFByteFieldIndex( Field ) ;
|
|
switch ( eventType )
|
|
{
|
|
case readEndID:
|
|
case freadEndID:
|
|
case writeEndID:
|
|
case fwriteEndID:
|
|
case -ID_malloc:
|
|
{
|
|
bytes = *((int *)dataPtr);
|
|
CallStack->record.bytes[ByteField] += bytes;
|
|
/*======================================================
|
|
// update histogram *
|
|
//=====================================================*/
|
|
i = -1;
|
|
while ( bytes >= BktLim[i+1] ) ++i ;
|
|
if ( i >= 0 ) ++CallStack->record.Hists[ByteField][i];
|
|
break;
|
|
}
|
|
case fopenEndID:
|
|
case openEndID:
|
|
{
|
|
openInfo.setName = openName;
|
|
openInfo.setID = (int)(*((long *)dataPtr));
|
|
CallStack->record.hdfID = openInfo.setID;
|
|
HDFrecordFileName ( &openInfo );
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
#ifdef H5_HAVE_MPIOTRACE
|
|
/*======================================================================*
|
|
// BeginMPIOEventRecord: *
|
|
// This routine simply records the time in the record on the top of *
|
|
// the stack. *
|
|
//======================================================================*/
|
|
void BeginMPIOEventRecord( int eventType,
|
|
CLOCK seconds,
|
|
void *data,
|
|
int dataLen )
|
|
{
|
|
HDFsetInfo *dataPtr;
|
|
dataPtr = (HDFsetInfo *)data;
|
|
/*===================================================================*
|
|
// save the time value temporarily in top of stack *
|
|
// When the end record is received, the duration can be *
|
|
// computed. *
|
|
//===================================================================*/
|
|
CallStack->lastIOtime = seconds;
|
|
/*===================================================================*
|
|
// get useful info from the structure pointed to by dataPtr. *
|
|
// Form most cases, this is the file ID. For mpiOpen, it is the *
|
|
// name of the file. For mpiDelete, no information is of any *
|
|
// use. *
|
|
//===================================================================*/
|
|
if ( dataLen == 0 ) return;
|
|
CallStack->record.hdfID = dataPtr->setID;
|
|
switch ( eventType )
|
|
{
|
|
case HDFmpiOpenID:
|
|
{
|
|
strcpy( openName, dataPtr->setName );
|
|
break;
|
|
}
|
|
case HDFmpiReadAtID:
|
|
{
|
|
CallStack->record.bytes[MPIOreadBytesReq] += dataPtr->numBytes;
|
|
break;
|
|
}
|
|
case HDFmpiReadAtAllID:
|
|
{
|
|
CallStack->record.bytes[MPIOreadAllBytesReq] += dataPtr->numBytes;
|
|
break;
|
|
}
|
|
case HDFmpiWriteAtID:
|
|
{
|
|
CallStack->record.bytes[MPIOwriteBytesReq] += dataPtr->numBytes;
|
|
break;
|
|
}
|
|
case HDFmpiWriteAtAllID:
|
|
{
|
|
CallStack->record.bytes[MPIOwriteAllBytesReq] += dataPtr->numBytes;
|
|
break;
|
|
}
|
|
case HDFmpiIreadAtID:
|
|
{
|
|
CallStack->record.bytes[MPIOiReadBytesReq] += dataPtr->numBytes;
|
|
break;
|
|
}
|
|
case HDFmpiIwriteAtID:
|
|
{
|
|
CallStack->record.bytes[MPIOiWriteBytesReq] += dataPtr->numBytes;
|
|
break;
|
|
}
|
|
case HDFmpiReadID:
|
|
{
|
|
CallStack->record.bytes[MPIOreadBytesReq] += dataPtr->numBytes;
|
|
break;
|
|
}
|
|
case HDFmpiReadAllID:
|
|
{
|
|
CallStack->record.bytes[MPIOreadAllBytesReq] += dataPtr->numBytes;
|
|
break;
|
|
}
|
|
case HDFmpiWriteID:
|
|
{
|
|
CallStack->record.bytes[MPIOwriteBytesReq] += dataPtr->numBytes;
|
|
break;
|
|
}
|
|
case HDFmpiWriteAllID:
|
|
{
|
|
CallStack->record.bytes[MPIOwriteAllBytesReq] += dataPtr->numBytes;
|
|
break;
|
|
}
|
|
case HDFmpiIreadID:
|
|
{
|
|
CallStack->record.bytes[MPIOiReadBytesReq] += dataPtr->numBytes;
|
|
break;
|
|
}
|
|
case HDFmpiIwriteID:
|
|
{
|
|
CallStack->record.bytes[MPIOiWriteBytesReq] += dataPtr->numBytes;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
/*======================================================================*
|
|
// EndMPIOEventRecord: *
|
|
// This routine retrieves the entry time saved on the top of the stack *
|
|
// and computes the duration of the MPI-I/O event. This is added to *
|
|
// the record field corresponding MPI-I/O. *
|
|
//======================================================================*/
|
|
void EndMPIOEventRecord ( int eventType,
|
|
CLOCK secs,
|
|
void *data,
|
|
int dataLen )
|
|
{
|
|
CLOCK incDur;
|
|
|
|
HDFsetInfo* dataPtr;
|
|
incDur = clockSubtract(secs,CallStack->lastIOtime) ;
|
|
CallStack->record.times[MPI]
|
|
= clockAdd ( CallStack->record.times[MPI], incDur );
|
|
++CallStack->record.counts[MPI];
|
|
if ( dataLen == 0 )
|
|
{
|
|
return;
|
|
}
|
|
dataPtr = (HDFsetInfo *)data;
|
|
switch ( eventType )
|
|
{
|
|
case -HDFmpiOpenID:
|
|
{
|
|
/*===========================================================*
|
|
// open and record the information. *
|
|
//===========================================================*/
|
|
openInfo.setName = openName;
|
|
openInfo.setID = dataPtr->setID;
|
|
CallStack->record.hdfID = openInfo.setID;
|
|
HDFrecordFileName ( &openInfo );
|
|
break;
|
|
}
|
|
case -HDFmpiReadAtID:
|
|
{
|
|
++CallStack->record.counts[MPIOread] ;
|
|
CallStack->record.times[MPIOread]
|
|
= clockAdd ( CallStack->record.times[MPIOread], incDur );
|
|
CallStack->record.bytes[MPIOreadBytesTrans] += dataPtr->numBytes;
|
|
break;
|
|
}
|
|
case -HDFmpiReadAtAllID:
|
|
{
|
|
++CallStack->record.counts[MPIOreadAll] ;
|
|
CallStack->record.times[MPIOreadAll]
|
|
= clockAdd ( CallStack->record.times[MPIOreadAll], incDur );
|
|
CallStack->record.bytes[MPIOreadAllBytesTrans] += dataPtr->numBytes;
|
|
break;
|
|
}
|
|
case -HDFmpiWriteAtID:
|
|
{
|
|
++CallStack->record.counts[MPIOwrite] ;
|
|
CallStack->record.times[MPIOwrite]
|
|
= clockAdd ( CallStack->record.times[MPIOwrite], incDur );
|
|
CallStack->record.bytes[MPIOwriteBytesTrans] += dataPtr->numBytes;
|
|
break;
|
|
}
|
|
case -HDFmpiWriteAtAllID:
|
|
{
|
|
++CallStack->record.counts[MPIOwriteAll] ;
|
|
CallStack->record.times[MPIOwriteAll]
|
|
= clockAdd ( CallStack->record.times[MPIOwriteAll], incDur );
|
|
CallStack->record.bytes[MPIOwriteAllBytesTrans] += dataPtr->numBytes;
|
|
break;
|
|
}
|
|
case -HDFmpiIreadAtID:
|
|
{
|
|
++CallStack->record.counts[MPIOiRead] ;
|
|
CallStack->record.times[MPIOiRead]
|
|
= clockAdd ( CallStack->record.times[MPIOiRead], incDur );
|
|
break;
|
|
}
|
|
case -HDFmpiIwriteAtID:
|
|
{
|
|
++CallStack->record.counts[MPIOiWrite] ;
|
|
CallStack->record.times[MPIOiWrite]
|
|
= clockAdd ( CallStack->record.times[MPIOiWrite], incDur );
|
|
break;
|
|
}
|
|
case -HDFmpiReadID:
|
|
{
|
|
++CallStack->record.counts[MPIOread] ;
|
|
CallStack->record.times[MPIOread]
|
|
= clockAdd ( CallStack->record.times[MPIOread], incDur );
|
|
CallStack->record.bytes[MPIOreadBytesTrans] += dataPtr->numBytes;
|
|
break;
|
|
}
|
|
case -HDFmpiReadAllID:
|
|
{
|
|
++CallStack->record.counts[MPIOreadAll] ;
|
|
CallStack->record.times[MPIOreadAll]
|
|
= clockAdd ( CallStack->record.times[MPIOreadAll], incDur );
|
|
CallStack->record.bytes[MPIOreadAllBytesTrans] += dataPtr->numBytes;
|
|
break;
|
|
}
|
|
case -HDFmpiWriteID:
|
|
{
|
|
++CallStack->record.counts[MPIOwrite] ;
|
|
CallStack->record.times[MPIOwrite]
|
|
= clockAdd ( CallStack->record.times[MPIOwrite], incDur );
|
|
CallStack->record.bytes[MPIOwriteBytesTrans] += dataPtr->numBytes;
|
|
break;
|
|
}
|
|
case -HDFmpiWriteAllID:
|
|
{
|
|
++CallStack->record.counts[MPIOwriteAll] ;
|
|
CallStack->record.times[MPIOwriteAll]
|
|
= clockAdd ( CallStack->record.times[MPIOwriteAll], incDur );
|
|
CallStack->record.bytes[MPIOwriteAllBytesTrans] += dataPtr->numBytes;
|
|
break;
|
|
}
|
|
case -HDFmpiIreadID:
|
|
{
|
|
++CallStack->record.counts[MPIOiRead] ;
|
|
CallStack->record.times[MPIOiRead]
|
|
= clockAdd ( CallStack->record.times[MPIOiRead], incDur );
|
|
break;
|
|
}
|
|
case -HDFmpiIwriteID:
|
|
{
|
|
++CallStack->record.counts[MPIOiWrite] ;
|
|
CallStack->record.times[MPIOiWrite]
|
|
= clockAdd ( CallStack->record.times[MPIOiWrite], incDur );
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
++CallStack->record.counts[MPIOother] ;
|
|
CallStack->record.times[MPIOother]
|
|
= clockAdd ( CallStack->record.times[MPIOiWrite], incDur );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif /* H5_HAVE_MPIOTRACE */
|
|
/*======================================================================*
|
|
// BeginHDFEventRecord: *
|
|
// This function puts a trace record on the stack corresponding to *
|
|
// this thread. If no stack exists, one is created. If no record *
|
|
// exist, a record is created. *
|
|
//======================================================================*/
|
|
void BeginHDFEventRecord( int eventID, CLOCK secs )
|
|
{
|
|
HDFnode_t *HDFrec;
|
|
/*==============================================================*
|
|
// Create a record. Push it onto the call stack. *
|
|
//==============================================================*/
|
|
HDFrec = (HDFnode_t *)malloc( sizeof(HDFnode_t) );
|
|
HDFnodeInit( HDFrec ) ;
|
|
HDFrec->eventID = eventID;
|
|
HDFrec->ptr = CallStack;
|
|
CallStack = HDFrec ;
|
|
/*==============================================================*
|
|
// save time stamp in record. *
|
|
//==============================================================*/
|
|
HDFrec->record.lastCall = secs;
|
|
}
|
|
/*======================================================================*
|
|
// EndHDFEventRecord: *
|
|
// This routine pops the HDF record from the top of the stack *
|
|
// corresponding to this thread and computes the inclusive duration *
|
|
// and adds it to the inclusive duration field of this record and to *
|
|
// the HDF time field of the calling routines record. *
|
|
//======================================================================*/
|
|
void EndHDFEventRecord ( CLOCK secs, void *dataPtr )
|
|
{
|
|
HDFsetInfo *info;
|
|
HDFnode_t *HDFrec;
|
|
CLOCK incSecs;
|
|
static int dummyIDs = -4;
|
|
/*==============================================================*
|
|
// pop record from top of the stack, compute inclusive duration *
|
|
// and set the corresponding record field and increment nCalls. *
|
|
//==============================================================*/
|
|
HDFrec = CallStack;
|
|
CallStack = CallStack->ptr;
|
|
if ( CallStack == NULL ) {
|
|
fprintf(stderr,">>> EndHDFEventRecord: Call Stack is empty. <<<\n");
|
|
return;
|
|
}
|
|
incSecs = clockSubtract(secs,HDFrec->record.lastCall) ;
|
|
|
|
HDFrec->record.incDur = incSecs;
|
|
++HDFrec->record.nCalls;
|
|
/*==============================================================*
|
|
// add old record to chain to have its xRef field tagged. *
|
|
//==============================================================*/
|
|
HDFrec->ptr = TagQueue;
|
|
TagQueue = HDFrec;
|
|
/*==============================================================*
|
|
// Add set ID information. *
|
|
//==============================================================*/
|
|
if ( dataPtr != NULL ) {
|
|
info = (HDFsetInfo *)dataPtr;
|
|
if ( info->setName != NULL ) {
|
|
if ( info->setID == 0 ) {
|
|
info->setID = dummyIDs--;
|
|
}
|
|
HDFrecordFileName ( info );
|
|
}
|
|
HDFrec->record.hdfID = info->setID;
|
|
}
|
|
/*==============================================================*
|
|
// Update the HDF totals for the calling program. *
|
|
//==============================================================*/
|
|
CallStack->record.times[ HDF_ ]
|
|
= clockAdd( CallStack->record.times[ HDF_ ] , incSecs ) ;
|
|
++CallStack->record.counts[ HDF_ ] ;
|
|
/*==============================================================*
|
|
// If the stack has only one record it represents the main *
|
|
// program. Tag all of the records on the TagQueue and tally *
|
|
// them up. *
|
|
//==============================================================*/
|
|
if ( CallStack->ptr == NULL ) {
|
|
HDFupdateProcLists( );
|
|
}
|
|
}
|
|
/*======================================================================*
|
|
// This routine keeps track of the identifier names and tags. Some *
|
|
// names may be associated with more than one tag. This will be *
|
|
// rectified when final tallies are done. *
|
|
//======================================================================*/
|
|
void HDFrecordFileName( HDFsetInfo *info )
|
|
{
|
|
fileRec_t *P;
|
|
char *t;
|
|
int match;
|
|
long id;
|
|
P = HDFfileList;
|
|
match = FALSE;
|
|
id = info->setID;
|
|
while ( P != NULL && match == FALSE ) {
|
|
if ( strcmp( P->fileName, info->setName ) != 0 && P->hdfID == id ) {
|
|
match = TRUE;
|
|
} else {
|
|
P = P->ptr;
|
|
}
|
|
}
|
|
if ( match == FALSE ) {
|
|
P = ( fileRec_t *) malloc( sizeof( fileRec_t ) );
|
|
P->ptr = HDFfileList;
|
|
HDFfileList = P;
|
|
t = (char *)malloc( strlen( info->setName ) + 1 );
|
|
strcpy ( t, info->setName ) ;
|
|
P->fileName = t;
|
|
P->hdfID = info->setID;
|
|
P->PabloID = 0;
|
|
}
|
|
}
|
|
/*======================================================================*
|
|
// This routine assigns a unique Pablo ID to each unique name *
|
|
// regardless of the HDF tag. *
|
|
// It then goes through the HDFRecordQueue and marks each record with *
|
|
// the PabloID corresponding to the hdfID and xRef fields or 0. *
|
|
//======================================================================*/
|
|
void HDFassignPabloIDs( int *nSetIDs, char ***Names )
|
|
{
|
|
fileRec_t *F, *G;
|
|
HDFnode_t *P;
|
|
int j;
|
|
long PabloID = 1;
|
|
long hdfID, xRef;
|
|
char *fName, **T;
|
|
|
|
F = HDFfileList;
|
|
/*==============================================================*
|
|
// Assign the same ID to identical names. *
|
|
//==============================================================*/
|
|
while ( F != NULL ) {
|
|
if ( F->PabloID == 0 ) {
|
|
F->PabloID = PabloID++;
|
|
fName = F->fileName;
|
|
G = F->ptr;
|
|
while ( G != NULL ) {
|
|
if ( strcmp( G->fileName , fName ) == 0 ) {
|
|
G->PabloID = F->PabloID;
|
|
}
|
|
G = G->ptr;
|
|
}
|
|
}
|
|
F = F->ptr;
|
|
}
|
|
*nSetIDs = (int)(PabloID - 1);
|
|
if ( *nSetIDs <= 0 ) return;
|
|
/*==============================================================*
|
|
// Repace hdfID and xRef fields with corresponding Pablo ID *
|
|
//==============================================================*/
|
|
for ( j = 0; j < NumHDFProcs; ++j ) {
|
|
P = HDFQueues[j] ;
|
|
while ( P != NULL ) {
|
|
hdfID = P->record.hdfID;
|
|
if ( hdfID != 0 ) {
|
|
PabloID = 0;
|
|
F = HDFfileList;
|
|
while ( F != NULL && PabloID == 0 ) {
|
|
if ( hdfID == F->hdfID ) {
|
|
PabloID = F->PabloID;
|
|
}
|
|
F = F->ptr;
|
|
}
|
|
P->record.hdfID = PabloID;
|
|
}
|
|
xRef = P->record.xRef;
|
|
if ( xRef != 0 ) {
|
|
PabloID = 0;
|
|
F = HDFfileList;
|
|
while ( F != NULL && PabloID == 0 ) {
|
|
if ( xRef == F->hdfID ) {
|
|
PabloID = F->PabloID;
|
|
}
|
|
F = F->ptr;
|
|
}
|
|
P->record.xRef = PabloID;
|
|
}
|
|
P = P->ptr;
|
|
} /* end while ( P != NULL ) */
|
|
} /* end for */
|
|
/*==============================================================*
|
|
// get a list of all the unique names and order them according *
|
|
// to their Pablo IDs. *
|
|
//==============================================================*/
|
|
T = ( char ** )malloc( (*nSetIDs+1) * sizeof( char * ) );
|
|
for ( j = 0; j <= *nSetIDs; ++j ) {
|
|
T[j] = NULL;
|
|
}
|
|
F = HDFfileList;
|
|
while ( F != NULL ) {
|
|
PabloID = F->PabloID ;
|
|
if ( T[PabloID] == NULL ) {
|
|
T[PabloID] = ( char * )malloc( strlen( F->fileName ) + 1 );
|
|
strcpy( T[PabloID], F->fileName ) ;
|
|
}
|
|
free((void *)(F->fileName));
|
|
G = F;
|
|
F = F->ptr;
|
|
free ( (void *)G );
|
|
}
|
|
*Names = T;
|
|
}
|
|
/*======================================================================*
|
|
// This routine writes SDDF packets to SDDF file containing information *
|
|
// about the named identifiers found in the program. *
|
|
//======================================================================*/
|
|
void writeHDFNamePacketsRT( char **Names, int numSetIDs )
|
|
{
|
|
int j;
|
|
HDFNamePacket_t NamePkt;
|
|
char *BUFF, *fName;
|
|
int buffSize;
|
|
/*==============================================================*
|
|
// Allocate a buffer to hold the packet. Allow 80 chars for *
|
|
// identifier name. *
|
|
//==============================================================*/
|
|
buffSize = sizeof(HDFNamePacket_t) + 80;
|
|
BUFF = (char *)malloc(buffSize);
|
|
/*==============================================================*
|
|
// Fill in constant information *
|
|
//==============================================================*/
|
|
NamePkt.packetType = PKT_DATA;
|
|
NamePkt.packetTag = FAMILY_NAME;
|
|
/*==============================================================*
|
|
// Fill in named identifier information and write to SDDF file *
|
|
//==============================================================*/
|
|
for ( j = 1; j <= numSetIDs; ++j ) {
|
|
fName = Names[j];
|
|
NamePkt.packetLength = (int)(sizeof(NamePkt) + strlen(fName));
|
|
NamePkt.fileType = 0; /* not currently used */
|
|
NamePkt.fileID = j;
|
|
NamePkt.nameLen = (int)strlen(fName) ;
|
|
if ( buffSize < NamePkt.packetLength ) {
|
|
free((void *)BUFF) ;
|
|
buffSize = NamePkt.packetLength + 80;
|
|
BUFF = (char *)malloc( buffSize ) ;
|
|
}
|
|
/*===========================================================*
|
|
// Copy packet data and tack on identifier name *
|
|
//===========================================================*/
|
|
memcpy( BUFF, &NamePkt, sizeof(NamePkt) );
|
|
memcpy( BUFF + sizeof(NamePkt) , fName, strlen(fName) );
|
|
putBytes( BUFF , NamePkt.packetLength ) ;
|
|
}
|
|
free((void *)BUFF);
|
|
}
|
|
/*======================================================================*
|
|
// Tag xRef field of all records in this queue with the hdfID of the *
|
|
// highest level caller. Also *
|
|
// This routine takes the records after they have been tagged and adds *
|
|
// their fields to the apporopriate position in the HDFQueues structure *
|
|
//======================================================================*/
|
|
void HDFupdateProcLists( void )
|
|
{
|
|
HDFnode_t *P, *Q;
|
|
long hdfID;
|
|
|
|
hdfID = TagQueue->record.hdfID;
|
|
P = TagQueue;
|
|
while ( P != NULL ) {
|
|
P->record.xRef = hdfID;
|
|
Q = P->ptr;
|
|
HDFupdateProcs( P );
|
|
P = Q;
|
|
}
|
|
TagQueue = NULL;
|
|
}
|
|
/*======================================================================*
|
|
// This routine takes as input a node pointer P and looks for a Total *
|
|
// record with this same eventID, hdfID and xRef. If such a record *
|
|
// exists, P is added to the record, otherwise a record is created and *
|
|
// its values are set to P's. *
|
|
//======================================================================*/
|
|
void HDFupdateProcs( HDFnode_t *P )
|
|
{
|
|
int procIndex, eventID;
|
|
long hdfID, xRef;
|
|
HDFnode_t *Q;
|
|
eventID = P->eventID;
|
|
procIndex = ProcIndexForHDFEntry( eventID );
|
|
hdfID = P->record.hdfID;
|
|
xRef = P->record.xRef;
|
|
Q = HDFQueues[ procIndex ];
|
|
/*==============================================================*
|
|
// First determine if a tally node exists that matches the *
|
|
// eventID, hdfID and xRef of P. *
|
|
//==============================================================*/
|
|
while ( Q != NULL &&
|
|
(( Q->record.hdfID != hdfID ) || ( Q->record.xRef != xRef )) ) {
|
|
Q = Q->ptr;
|
|
}
|
|
if ( Q == NULL ) {
|
|
/*===========================================================*
|
|
// No tally record matches the hdfID and xRef so put P in *
|
|
// the queue. *
|
|
//===========================================================*/
|
|
P->ptr = HDFQueues[ procIndex ];
|
|
HDFQueues[ procIndex ] = P;
|
|
} else {
|
|
/*===========================================================*
|
|
// add P to the exiting record and free it. *
|
|
//===========================================================*/
|
|
HDFrecordSum ( &Q->record , &P->record );
|
|
free((void *)P);
|
|
}
|
|
}
|
|
/*======================================================================*
|
|
// Print SDDF records for all records in this linked list. *
|
|
//======================================================================*/
|
|
void HDFSummarySDDF( HDFnode_t *P, int procIndex )
|
|
{
|
|
int i, j, arrayLen, nodeID, nCalls;
|
|
int allIOCount;
|
|
CLOCK allIOTime, excDur;
|
|
double t;
|
|
char buff[1024];
|
|
char *Packet;
|
|
HDFnode_t *Q;
|
|
struct
|
|
{
|
|
int packetLen;
|
|
int packetType;
|
|
int packetTag;
|
|
int eventID;
|
|
double Seconds;
|
|
double IncDur;
|
|
double ExcDur;
|
|
long HDFid;
|
|
long XREFid;
|
|
} Header;
|
|
|
|
Header.packetLen = sizeof(Header)
|
|
+ sizeof(int) /* n Calls */
|
|
+ sizeof(int) /* array len */
|
|
+ nTallyFields*sizeof(double) /* times array */
|
|
+ sizeof(int) /* array len */
|
|
+ nTallyFields*sizeof(int) /* count array */
|
|
+ sizeof(int) /* array len */
|
|
+ nByteFields*sizeof(int) /* bytes array */
|
|
+ nHistFields*sizeof(int) /* array lens */
|
|
+ nHistFields*nBkts*sizeof(int) /* byte hist */
|
|
+ sizeof(int); /* nodeID */
|
|
Header.packetTag = HDF_SUMMARY_FAMILY +
|
|
( procIndex + 1 )*8 + RECORD_TRACE ;
|
|
Header.packetType = PKT_DATA;
|
|
nodeID = TRgetNode();
|
|
while ( P != NULL ) {
|
|
Q = P->ptr;
|
|
/*===========================================================*
|
|
// Total the I/O time and counts *
|
|
//===========================================================*/
|
|
allIOTime = zeroClock;
|
|
for ( j = FirstIO; j <= LastIO; ++j ) {
|
|
allIOTime = clockAdd( allIOTime, P->record.times[j] );
|
|
}
|
|
P->record.times[AllIO] = allIOTime;
|
|
|
|
allIOCount = 0;
|
|
for ( j = FirstIO; j <= LastIO; ++j ) {
|
|
allIOCount += P->record.counts[j];
|
|
}
|
|
P->record.counts[AllIO] = allIOCount;
|
|
/*===========================================================*
|
|
// compute exclusive duration. *
|
|
//===========================================================*/
|
|
excDur = clockSubtract(P->record.incDur,allIOTime);
|
|
excDur = clockSubtract(excDur,P->record.times[HDF_]);
|
|
excDur = clockSubtract(excDur,P->record.times[MPI]);
|
|
/*===========================================================*
|
|
// print header information. *
|
|
//===========================================================*/
|
|
Header.eventID = P->eventID;
|
|
Header.Seconds = clockToSeconds(P->record.lastCall);
|
|
Header.IncDur = clockToSeconds( P->record.incDur );
|
|
Header.ExcDur = clockToSeconds(excDur);
|
|
Header.HDFid = P->record.hdfID;
|
|
Header.XREFid = P->record.xRef;
|
|
Packet = buff;
|
|
memcpy( Packet, &Header, sizeof(Header) );
|
|
Packet += sizeof(Header);
|
|
/*===========================================================*
|
|
// copy number of calls to Packet. *
|
|
//===========================================================*/
|
|
nCalls = P->record.nCalls;
|
|
memcpy( Packet, &nCalls, sizeof(int) );
|
|
Packet += sizeof(int);
|
|
/*===========================================================*
|
|
// copy length of times array and times array to Packet. *
|
|
//===========================================================*/
|
|
arrayLen = nTallyFields;
|
|
memcpy( Packet, &arrayLen, sizeof(int) );
|
|
Packet += sizeof(int);
|
|
for ( j = 0; j < nTallyFields; ++j ) {
|
|
t = clockToSeconds(P->record.times[j]);
|
|
memcpy( Packet, &t, sizeof(double) );
|
|
Packet += sizeof(double);
|
|
}
|
|
/*===========================================================*
|
|
// copy length of counts array and counts array to Packet. *
|
|
//===========================================================*/
|
|
arrayLen = nTallyFields;
|
|
memcpy( Packet, &arrayLen, sizeof(int) );
|
|
Packet += sizeof(int);
|
|
memcpy( Packet, P->record.counts, nTallyFields*sizeof(int) );
|
|
Packet += nTallyFields*sizeof(int);
|
|
/*===========================================================*
|
|
// copy length of bytes array and bytes array to Packet. *
|
|
//===========================================================*/
|
|
arrayLen = nByteFields;
|
|
memcpy( Packet, &arrayLen, sizeof(int) );
|
|
Packet += sizeof(int);
|
|
memcpy( Packet, P->record.bytes, nByteFields*sizeof(int) );
|
|
Packet += nByteFields*sizeof(int);
|
|
/*===========================================================*
|
|
// copy length of historgram arrays and arrays to Packet. *
|
|
//===========================================================*/
|
|
arrayLen = nBkts;
|
|
for ( i = 0; i < nHistFields; ++i )
|
|
{
|
|
memcpy( Packet, &arrayLen, sizeof(int) );
|
|
Packet += sizeof(int);
|
|
memcpy( Packet, P->record.Hists[i], nBkts*sizeof(int) );
|
|
Packet += nBkts*sizeof(int);
|
|
}
|
|
memcpy( Packet, &nodeID, sizeof(int) );
|
|
Packet += sizeof(int);
|
|
arrayLen = Packet-buff;
|
|
memcpy(buff,&arrayLen,sizeof(int));
|
|
putBytes( buff, Packet-buff );
|
|
P = Q;
|
|
}
|
|
}
|
|
/*======================================================================*
|
|
// Initialize a node. *
|
|
//======================================================================*/
|
|
void HDFnodeInit ( HDFnode_t *S )
|
|
{
|
|
*S = InitNode;
|
|
}
|
|
/*======================================================================*
|
|
// Compute IO totals, exclusive durations of the input record T *
|
|
// then add the fields of T to that of S. *
|
|
//======================================================================*/
|
|
void HDFrecordSum ( HDFrec_t *S, HDFrec_t *T )
|
|
{
|
|
int i;
|
|
int j;
|
|
|
|
S->nCalls += T->nCalls;
|
|
if ( clockCompare ( S->lastCall, T->lastCall ) < 0 )
|
|
{
|
|
S->lastCall = T->lastCall ;
|
|
}
|
|
S->incDur = clockAdd ( S->incDur, T->incDur );
|
|
for ( j = 0; j < nTallyFields; ++j )
|
|
{
|
|
S->times[j] = clockAdd( S->times[j] , T->times[j] ) ;
|
|
}
|
|
for ( j = 0; j < nTallyFields; ++j )
|
|
{
|
|
S->counts[j] += T->counts[j] ;
|
|
}
|
|
for ( j = 0; j < nByteFields; ++j )
|
|
{
|
|
S->bytes[j] += T->bytes[j] ;
|
|
}
|
|
for ( j = 0; j < nHistFields; ++j )
|
|
{
|
|
for ( i = 0; i < nBkts; ++i )
|
|
{
|
|
S->Hists[j][i] += T->Hists[j][i] ;
|
|
}
|
|
}
|
|
}
|
|
/*======================================================================*
|
|
// Return the field index corresponding to an IO event ID. The fields *
|
|
// are specified in an enum statement in an include file. *
|
|
//======================================================================*/
|
|
int getHDFFieldIndex( int eventID )
|
|
{
|
|
int result = -1;
|
|
switch ( eventID )
|
|
{
|
|
case ID_malloc:
|
|
case -ID_malloc:
|
|
{
|
|
result = Malloc;
|
|
break;
|
|
}
|
|
case openBeginID:
|
|
case openEndID:
|
|
case fopenBeginID:
|
|
case fopenEndID:
|
|
{
|
|
result = Open;
|
|
break;
|
|
}
|
|
case closeBeginID:
|
|
case closeEndID:
|
|
case fcloseBeginID:
|
|
case fcloseEndID:
|
|
{
|
|
result = Close;
|
|
break;
|
|
}
|
|
case readBeginID:
|
|
case readEndID:
|
|
case freadBeginID:
|
|
case freadEndID:
|
|
{
|
|
result = Read;
|
|
break;
|
|
}
|
|
case lseekBeginID:
|
|
case lseekEndID:
|
|
case fseekBeginID:
|
|
case fseekEndID:
|
|
{
|
|
result = Seek;
|
|
break;
|
|
}
|
|
case writeBeginID:
|
|
case writeEndID:
|
|
case fwriteBeginID:
|
|
case fwriteEndID:
|
|
{
|
|
result = Write;
|
|
break;
|
|
}
|
|
case fflushBeginID:
|
|
case fflushEndID:
|
|
case flushBeginID:
|
|
case flushEndID:
|
|
{
|
|
result = Misc;
|
|
break;
|
|
}
|
|
case rewindBeginID:
|
|
case rewindEndID:
|
|
case fsetposBeginID:
|
|
case fsetposEndID:
|
|
{
|
|
result = Misc;
|
|
break;
|
|
}
|
|
#ifdef creadBeginID
|
|
case creadBeginID:
|
|
case creadEndID:
|
|
case creadvBeginID:
|
|
case creadvEndID:
|
|
{
|
|
result = Read;
|
|
break;
|
|
}
|
|
case cwriteBeginID:
|
|
case cwriteEndID:
|
|
case cwritevBeginID:
|
|
case cwritevEndID:
|
|
{
|
|
result = Write;
|
|
break;
|
|
}
|
|
case ireadBeginID:
|
|
case ireadEndID:
|
|
case ireadvBeginID:
|
|
case ireadvEndID:
|
|
{
|
|
result = Aread;
|
|
break;
|
|
}
|
|
case iwriteBeginID:
|
|
case iwriteEndID:
|
|
case iwritevBeginID:
|
|
case iwritevEndID:
|
|
{
|
|
result = Awrite;
|
|
break;
|
|
}
|
|
case iowaitBeginID:
|
|
case iowaitEndID:
|
|
{
|
|
result = Wait;
|
|
break;
|
|
}
|
|
case iodoneBeginID:
|
|
case iodoneEndID:
|
|
{
|
|
result = Misc;
|
|
break;
|
|
}
|
|
case gopenBeginID:
|
|
case gopenEndID:
|
|
{
|
|
result = Open;
|
|
break;
|
|
}
|
|
case iomodeBeginID:
|
|
case iomodeEndID:
|
|
case setiomodeBeginID:
|
|
case setiomodeEndID:
|
|
case lsizeBeginID:
|
|
case lsizeEndID:
|
|
case forflushBeginID:
|
|
case forflushEndID:
|
|
{
|
|
result = Misc;
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
return result;
|
|
}
|
|
/*======================================================================*
|
|
// This routine determines the field index in the bytes array of the *
|
|
// HDF records which correspond to a given IO operation. If the *
|
|
// operation does not transfer bytes, (e.g., open operation), -1 is *
|
|
// returned. *
|
|
//======================================================================*/
|
|
int getHDFByteFieldIndex( int Operation )
|
|
{
|
|
int result;
|
|
switch ( Operation )
|
|
{
|
|
case Malloc:
|
|
{
|
|
result = MallocBytes;
|
|
break;
|
|
}
|
|
case Read:
|
|
{
|
|
result = ReadBytes;
|
|
break;
|
|
}
|
|
case Write:
|
|
{
|
|
result = WriteBytes;
|
|
break;
|
|
}
|
|
case Aread:
|
|
{
|
|
result = AreadBytes;
|
|
break;
|
|
}
|
|
case Awrite:
|
|
{
|
|
result = AwriteBytes;
|
|
break;
|
|
}
|
|
case MPIOread:
|
|
{
|
|
result = MPIOreadBytesReq;
|
|
break;
|
|
}
|
|
case MPIOwrite:
|
|
{
|
|
result = MPIOwriteBytesReq;
|
|
break;
|
|
}
|
|
case MPIOreadAll:
|
|
{
|
|
result = MPIOreadAllBytesReq;
|
|
break;
|
|
}
|
|
case MPIOwriteAll:
|
|
{
|
|
result = MPIOwriteAllBytesReq;
|
|
break;
|
|
}
|
|
case MPIOiRead:
|
|
{
|
|
result = MPIOiReadBytesReq;
|
|
break;
|
|
}
|
|
case MPIOiWrite:
|
|
{
|
|
result = MPIOiWriteBytesReq;
|
|
break;
|
|
}
|
|
case MPIOreadTrans:
|
|
{
|
|
result = MPIOreadBytesTrans;
|
|
break;
|
|
}
|
|
case MPIOwriteTrans:
|
|
{
|
|
result = MPIOwriteBytesTrans;
|
|
break;
|
|
}
|
|
case MPIOreadAllTrans:
|
|
{
|
|
result = MPIOreadAllBytesTrans;
|
|
break;
|
|
}
|
|
case MPIOwriteAllTrans:
|
|
{
|
|
result = MPIOwriteAllBytesTrans;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
result = -1;
|
|
break;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
/*======================================================================*
|
|
// This routine writes the SDDF packet descriptors for the HDF summary *
|
|
// records to the output file. *
|
|
//======================================================================*/
|
|
void _hdfDescriptorRT( char *recordName, char *recordDescription,
|
|
int recordFamily )
|
|
{
|
|
static char recordBuffer[ 4096 ];
|
|
int recordLength;
|
|
|
|
hdfRecordPointer = recordBuffer;
|
|
/*==================================================================*
|
|
// Allow space at the beginning of the record for the packet *
|
|
//length which will be computed after the packet is complete. *
|
|
//==================================================================*/
|
|
sddfWriteInteger( &hdfRecordPointer, 0 );
|
|
/*==================================================================*
|
|
// The record type, tag, and name *
|
|
//==================================================================*/
|
|
sddfWriteInteger( &hdfRecordPointer, PKT_DESCRIPTOR );
|
|
sddfWriteInteger( &hdfRecordPointer, ( recordFamily | RECORD_TRACE ) );
|
|
sddfWriteString( &hdfRecordPointer, recordName );
|
|
/*==================================================================*
|
|
// The record attribute count and string pair *
|
|
//==================================================================*/
|
|
sddfWriteInteger( &hdfRecordPointer, 1 );
|
|
sddfWriteString( &hdfRecordPointer, "description" );
|
|
sddfWriteString( &hdfRecordPointer, recordDescription );
|
|
/*==================================================================*
|
|
// The record field count *
|
|
//==================================================================*/
|
|
sddfWriteInteger( &hdfRecordPointer, 16 );
|
|
WRITE_HDF_FIELD( "Event Identifier",
|
|
"Event ID",
|
|
"Corresponding Event",
|
|
INTEGER, 0 );
|
|
WRITE_HDF_FIELD( "Seconds",
|
|
"Seconds",
|
|
"Floating Point Timestamp",
|
|
DOUBLE, 0 );
|
|
WRITE_HDF_FIELD( "Inclusive Duration",
|
|
"Inclusive Duration",
|
|
"Inclusive Duration of this Procedure",
|
|
DOUBLE, 0 );
|
|
WRITE_HDF_FIELD( "Exclusive Duration",
|
|
"Exclusive Duration",
|
|
"Excludes IO, MPI-IO and other HDF calls",
|
|
DOUBLE, 0 );
|
|
WRITE_HDF_FIELD2("HDF ID",
|
|
"HDF ID", "Identifier number",
|
|
"0", "No HDF ID specified",
|
|
LONG, 0 );
|
|
WRITE_HDF_FIELD( "Xref ID",
|
|
"Cross Reference",
|
|
"Index of related HDF ID or 0 if none",
|
|
LONG, 0 );
|
|
WRITE_HDF_FIELD( "N Calls",
|
|
"N Calls",
|
|
"Number of Calls to this Proc",
|
|
INTEGER, 0 );
|
|
WRITE_HDF_FIELD( "Times Array",
|
|
"Times Array",
|
|
"Array of Total Operation Times",
|
|
DOUBLE, 1 );
|
|
WRITE_HDF_FIELD( "Counts Array",
|
|
"Counts Array",
|
|
"Array of Total Operation Counts",
|
|
INTEGER, 1 );
|
|
WRITE_HDF_FIELD( "Bytes Array",
|
|
"Bytes Array",
|
|
"Array of Total Bytes Transferred",
|
|
INTEGER, 1 );
|
|
WRITE_HDF_FIELD( "Malloc Histogram",
|
|
"Malloc Histogram",
|
|
"Historgram of size Malloc Requests",
|
|
INTEGER, 1 );
|
|
WRITE_HDF_FIELD( "Read Histogram",
|
|
"Read Histogram",
|
|
"Historgram of size Read Requests",
|
|
INTEGER, 1 );
|
|
WRITE_HDF_FIELD( "Write Histogram",
|
|
"Write Histogram",
|
|
"Historgram of size Write Requests",
|
|
INTEGER, 1 );
|
|
WRITE_HDF_FIELD( "Aread Histogram",
|
|
"Aread Histogram",
|
|
"Historgram of size Asynch Read Requests",
|
|
INTEGER, 1 );
|
|
WRITE_HDF_FIELD( "Awrite Histogram",
|
|
"Awrite Histogram",
|
|
"Historgram of size Asynch Write Requests",
|
|
INTEGER, 1 );
|
|
WRITE_HDF_FIELD( "Processor Number",
|
|
"Node",
|
|
"Processor number",
|
|
INTEGER, 0 );
|
|
/*===================================================================
|
|
// The entire record descriptor packet has been written. *
|
|
// Compute and update the record length. *
|
|
// Write the completed record. *
|
|
//==================================================================*/
|
|
recordLength = (int)(hdfRecordPointer - recordBuffer);
|
|
|
|
hdfRecordPointer = recordBuffer;
|
|
sddfWriteInteger( &hdfRecordPointer, recordLength );
|
|
|
|
putBytes( recordBuffer, (unsigned) recordLength );
|
|
}
|
|
|
|
/*======================================================================*
|
|
// Internal Routine: writeHDFRecDescrptrsRT *
|
|
// Writes record descriptors for the HDF events. *
|
|
//======================================================================*/
|
|
void writeHDFRecDescrptrsRT( void )
|
|
{
|
|
int j, FAMILY;
|
|
char BUF1[256], BUF2[256] ;
|
|
char buff[41];
|
|
_hdfNameDescriptor(); /* Descriptor for named identifiers */
|
|
for ( j = 0; j < NumHDFProcs; ++j ) {
|
|
if ( HDFQueues[j] != NULL ) {
|
|
getHDFprocName( j, buff );
|
|
strcpy( BUF2, "HDF ");
|
|
strcat( BUF2, buff );
|
|
strcat( BUF2, " Procedure Summary");
|
|
strcpy( BUF1, BUF2 );
|
|
strcat( BUF1, " Trace");
|
|
FAMILY = HDF_SUMMARY_FAMILY + (j + 1)*8;
|
|
_hdfDescriptorRT( BUF1, BUF2, FAMILY );
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
/*======================================================================*
|
|
// This routine prints the Pablo IDs assigned to named HDF identifiers *
|
|
//======================================================================*/
|
|
void printFileMappingsRT( char *mapFile, char **Names, int nPabloIDs )
|
|
{
|
|
int i;
|
|
FILE *ptr;
|
|
ptr = fopen( mapFile, "w" );
|
|
|
|
if ( ptr == NULL ) {
|
|
fprintf(stderr,
|
|
"Couldn't open map file %s - none created.\n",mapFile);
|
|
return;
|
|
}
|
|
|
|
fprintf(ptr,"\n\nPablo ID to HDF Name mappings:\n");
|
|
fprintf(ptr,"------------------------------\n");
|
|
for ( i = 1; i <= nPabloIDs; i++ ) {
|
|
fprintf(ptr,"%4d %s\n",i,Names[i] );
|
|
}
|
|
fprintf(ptr,"\n\n");
|
|
fclose( ptr );
|
|
}
|
|
/************************************************************************/
|
|
/* _hdfNameDescriptor */
|
|
/* Generate a SDDF binary format record descriptor for the */
|
|
/* named identifiers used during execution. */
|
|
/************************************************************************/
|
|
void _hdfNameDescriptor( void )
|
|
{
|
|
static char recordBuffer[ 4096 ];
|
|
int recordLength;
|
|
|
|
#ifdef PABLODEBUG
|
|
fprintf( debugFile, "_hdfExitTraceDescriptor entered\n" );
|
|
fflush( debugFile );
|
|
#endif /* PABLODEBUG */
|
|
hdfRecordPointer = recordBuffer;
|
|
/********************************************************************/
|
|
/* Allow space at the beginning of the record for the packet */
|
|
/*length which will be computed after the packet is complete. */
|
|
/********************************************************************/
|
|
sddfWriteInteger( &hdfRecordPointer, 0 );
|
|
/********************************************************************/
|
|
/* The record type, tag, and name */
|
|
/********************************************************************/
|
|
sddfWriteInteger( &hdfRecordPointer, PKT_DESCRIPTOR );
|
|
sddfWriteInteger( &hdfRecordPointer, ( FAMILY_NAME ) );
|
|
sddfWriteString( &hdfRecordPointer, "HDF Name Identifier Record" );
|
|
/********************************************************************/
|
|
/* The record attribute count and string pair */
|
|
/********************************************************************/
|
|
sddfWriteInteger( &hdfRecordPointer, 1 );
|
|
sddfWriteString( &hdfRecordPointer, "description" );
|
|
sddfWriteString( &hdfRecordPointer, "HDF Name Identifier Record" );
|
|
/********************************************************************/
|
|
/* The record field count */
|
|
/********************************************************************/
|
|
sddfWriteInteger( &hdfRecordPointer, 3);
|
|
/********************************************************************/
|
|
/* Create fields */
|
|
/********************************************************************/
|
|
WRITE_HDF_FIELD( "Identifier Type",
|
|
"Data Set Type",
|
|
"Data Set Identifier Type",
|
|
INTEGER, 0 );
|
|
WRITE_HDF_FIELD2( "HDF ID",
|
|
"HDF ID", "File, Data Set or Dim Identifier number",
|
|
"0", "No HDF ID specified",
|
|
INTEGER, 0 );
|
|
WRITE_HDF_FIELD( "HDF Name",
|
|
"HDF Name", "Name of File, Data Set or Dim",
|
|
CHARACTER, 1 );
|
|
|
|
recordLength = (int)(hdfRecordPointer - recordBuffer);
|
|
|
|
hdfRecordPointer = recordBuffer;
|
|
sddfWriteInteger( &hdfRecordPointer, recordLength );
|
|
|
|
putBytes( recordBuffer, (unsigned) recordLength );
|
|
}
|
|
#endif /* PCF_BUILD */
|