/* * (C) 2009 by Argonne National Laboratory. * See COPYRIGHT in top-level directory. */ #define _XOPEN_SOURCE 500 #define _GNU_SOURCE /* for tdestroy() */ #include "darshan-runtime-config.h" #include #ifdef HAVE_MNTENT_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "mpi.h" #include "darshan.h" #include "darshan-dynamic.h" #include "darshan-ext.h" extern char* __progname; /* maximum number of memory segments each process will write to the log */ #define CP_MAX_MEM_SEGMENTS 8 /* Some old versions of MPI don't provide all of these COMBINER definitions. * If any are missing then we define them to an arbitrary value just to * prevent compile errors in DATATYPE_INC(). */ #ifndef MPI_COMBINER_NAMED #define MPI_COMBINER_NAMED CP_COMBINER_NAMED #endif #ifndef MPI_COMBINER_DUP #define MPI_COMBINER_DUP CP_COMBINER_DUP #endif #ifndef MPI_COMBINER_CONTIGUOUS #define MPI_COMBINER_CONTIGUOUS CP_COMBINER_CONTIGUOUS #endif #ifndef MPI_COMBINER_VECTOR #define MPI_COMBINER_VECTOR CP_COMBINER_VECTOR #endif #ifndef MPI_COMBINER_HVECTOR_INTEGER #define MPI_COMBINER_HVECTOR_INTEGER CP_COMBINER_HVECTOR_INTEGER #endif #ifndef MPI_COMBINER_HVECTOR #define MPI_COMBINER_HVECTOR CP_COMBINER_HVECTOR #endif #ifndef MPI_COMBINER_INDEXED #define MPI_COMBINER_INDEXED CP_COMBINER_INDEXED #endif #ifndef MPI_COMBINER_HINDEXED_INTEGER #define MPI_COMBINER_HINDEXED_INTEGER CP_COMBINER_HINDEXED_INTEGER #endif #ifndef MPI_COMBINER_HINDEXED #define MPI_COMBINER_HINDEXED CP_COMBINER_HINDEXED #endif #ifndef MPI_COMBINER_INDEXED_BLOCK #define MPI_COMBINER_INDEXED_BLOCK CP_COMBINER_INDEXED_BLOCK #endif #ifndef MPI_COMBINER_STRUCT_INTEGER #define MPI_COMBINER_STRUCT_INTEGER CP_COMBINER_STRUCT_INTEGER #endif #ifndef MPI_COMBINER_STRUCT #define MPI_COMBINER_STRUCT CP_COMBINER_STRUCT #endif #ifndef MPI_COMBINER_SUBARRAY #define MPI_COMBINER_SUBARRAY CP_COMBINER_SUBARRAY #endif #ifndef MPI_COMBINER_DARRAY #define MPI_COMBINER_DARRAY CP_COMBINER_DARRAY #endif #ifndef MPI_COMBINER_F90_REAL #define MPI_COMBINER_F90_REAL CP_COMBINER_F90_REAL #endif #ifndef MPI_COMBINER_F90_COMPLEX #define MPI_COMBINER_F90_COMPLEX CP_COMBINER_F90_COMPLEX #endif #ifndef MPI_COMBINER_F90_INTEGER #define MPI_COMBINER_F90_INTEGER CP_COMBINER_F90_INTEGER #endif #ifndef MPI_COMBINER_RESIZED #define MPI_COMBINER_RESIZED CP_COMBINER_RESIZED #endif #define CP_DATATYPE_INC(__file, __datatype) do {\ int num_integers, num_addresses, num_datatypes, combiner, ret; \ ret = DARSHAN_MPI_CALL(PMPI_Type_get_envelope)(__datatype, &num_integers, \ &num_addresses, &num_datatypes, &combiner); \ if(ret == MPI_SUCCESS) { \ switch(combiner) { \ case MPI_COMBINER_NAMED:\ CP_INC(__file,CP_COMBINER_NAMED,1); break; \ case MPI_COMBINER_DUP:\ CP_INC(__file,CP_COMBINER_DUP,1); break; \ case MPI_COMBINER_CONTIGUOUS:\ CP_INC(__file,CP_COMBINER_CONTIGUOUS,1); break; \ case MPI_COMBINER_VECTOR:\ CP_INC(__file,CP_COMBINER_VECTOR,1); break; \ case MPI_COMBINER_HVECTOR_INTEGER:\ CP_INC(__file,CP_COMBINER_HVECTOR_INTEGER,1); break; \ case MPI_COMBINER_HVECTOR:\ CP_INC(__file,CP_COMBINER_HVECTOR,1); break; \ case MPI_COMBINER_INDEXED:\ CP_INC(__file,CP_COMBINER_INDEXED,1); break; \ case MPI_COMBINER_HINDEXED_INTEGER:\ CP_INC(__file,CP_COMBINER_HINDEXED_INTEGER,1); break; \ case MPI_COMBINER_HINDEXED:\ CP_INC(__file,CP_COMBINER_HINDEXED,1); break; \ case MPI_COMBINER_INDEXED_BLOCK:\ CP_INC(__file,CP_COMBINER_INDEXED_BLOCK,1); break; \ case MPI_COMBINER_STRUCT_INTEGER:\ CP_INC(__file,CP_COMBINER_STRUCT_INTEGER,1); break; \ case MPI_COMBINER_STRUCT:\ CP_INC(__file,CP_COMBINER_STRUCT,1); break; \ case MPI_COMBINER_SUBARRAY:\ CP_INC(__file,CP_COMBINER_SUBARRAY,1); break; \ case MPI_COMBINER_DARRAY:\ CP_INC(__file,CP_COMBINER_DARRAY,1); break; \ case MPI_COMBINER_F90_REAL:\ CP_INC(__file,CP_COMBINER_F90_REAL,1); break; \ case MPI_COMBINER_F90_COMPLEX:\ CP_INC(__file,CP_COMBINER_F90_COMPLEX,1); break; \ case MPI_COMBINER_F90_INTEGER:\ CP_INC(__file,CP_COMBINER_F90_INTEGER,1); break; \ case MPI_COMBINER_RESIZED:\ CP_INC(__file,CP_COMBINER_RESIZED,1); break; \ } \ } \ } while(0) #define CP_RECORD_MPI_WRITE(__ret, __fh, __count, __datatype, __counter, __tm1, __tm2) do { \ struct darshan_file_runtime* file; \ int size = 0; \ MPI_Aint extent = 0; \ if(__ret != MPI_SUCCESS) break; \ file = darshan_file_by_fh(__fh); \ if(!file) break; \ DARSHAN_MPI_CALL(PMPI_Type_size)(__datatype, &size); \ size = size * __count; \ DARSHAN_MPI_CALL(PMPI_Type_extent)(__datatype, &extent); \ CP_BUCKET_INC(file, CP_SIZE_WRITE_AGG_0_100, size); \ CP_BUCKET_INC(file, CP_EXTENT_WRITE_0_100, extent); \ CP_INC(file, __counter, 1); \ CP_DATATYPE_INC(file, __datatype); \ CP_F_INC_NO_OVERLAP(file, __tm1, __tm2, file->last_mpi_write_end, CP_F_MPI_WRITE_TIME); \ if(CP_F_VALUE(file, CP_F_WRITE_START_TIMESTAMP) == 0) \ CP_F_SET(file, CP_F_WRITE_START_TIMESTAMP, __tm1); \ CP_F_SET(file, CP_F_WRITE_END_TIMESTAMP, __tm2); \ } while(0) #define CP_RECORD_MPI_READ(__ret, __fh, __count, __datatype, __counter, __tm1, __tm2) do { \ struct darshan_file_runtime* file; \ int size = 0; \ MPI_Aint extent = 0; \ if(__ret != MPI_SUCCESS) break; \ file = darshan_file_by_fh(__fh); \ if(!file) break; \ DARSHAN_MPI_CALL(PMPI_Type_size)(__datatype, &size); \ size = size * __count; \ DARSHAN_MPI_CALL(PMPI_Type_extent)(__datatype, &extent); \ CP_BUCKET_INC(file, CP_SIZE_READ_AGG_0_100, size); \ CP_BUCKET_INC(file, CP_EXTENT_READ_0_100, extent); \ CP_INC(file, __counter, 1); \ CP_DATATYPE_INC(file, __datatype); \ CP_F_INC_NO_OVERLAP(file, __tm1, __tm2, file->last_mpi_read_end, CP_F_MPI_READ_TIME); \ if(CP_F_VALUE(file, CP_F_READ_START_TIMESTAMP) == 0) \ CP_F_SET(file, CP_F_READ_START_TIMESTAMP, __tm1); \ CP_F_SET(file, CP_F_READ_END_TIMESTAMP, __tm2); \ } while(0) static void cp_log_construct_indices(struct darshan_job_runtime* final_job, int rank, int* inout_count, int* lengths, void** pointers, char* trailing_data); static int cp_log_write(struct darshan_job_runtime* final_job, int rank, char* logfile_name, int count, int* lengths, void** pointers, double start_log_time); static void cp_log_record_hints_and_ver(struct darshan_job_runtime* final_job, int rank); static int cp_log_reduction(struct darshan_job_runtime* final_job, int rank, char* logfile_name, MPI_Offset* next_offset); static void darshan_file_reduce(void* infile_v, void* inoutfile_v, int *len, MPI_Datatype *datatype); static int cp_log_compress(struct darshan_job_runtime* final_job, int rank, int* inout_count, int* lengths, void** pointers); static int file_compare(const void* a, const void* b); static int darshan_file_variance( struct darshan_file *infile_array, struct darshan_file *outfile_array, int count, int rank); static void pairwise_variance_reduce ( void *invec, void *inoutvec, int *len, MPI_Datatype *dt); #if 0 static void debug_mounts(const char* mtab_file, const char* out_file); #endif static struct darshan_file_runtime* darshan_file_by_fh(MPI_File fh); static void darshan_file_close_fh(MPI_File fh); static struct darshan_file_runtime* darshan_file_by_name_setfh(const char* name, MPI_File fh); #define CP_MAX_MNTS 32 #define CP_MAX_MNT_PATH 256 #define CP_MAX_MNT_TYPE 32 struct mnt_data { int64_t hash; int64_t block_size; char path[CP_MAX_MNT_PATH]; char type[CP_MAX_MNT_TYPE]; }; static struct mnt_data mnt_data_array[CP_MAX_MNTS]; static int mnt_data_count = 0; struct variance_dt { double n; double T; double S; }; static int epoch_counter = 0; void darshan_mpi_initialize(int *argc, char ***argv) { int nprocs; int rank; int timing_flag = 0; double init_start, init_time, init_max; DARSHAN_MPI_CALL(PMPI_Comm_size)(MPI_COMM_WORLD, &nprocs); DARSHAN_MPI_CALL(PMPI_Comm_rank)(MPI_COMM_WORLD, &rank); if(getenv("DARSHAN_INTERNAL_TIMING")) timing_flag = 1; if(timing_flag) init_start = DARSHAN_MPI_CALL(PMPI_Wtime)(); if(argc && argv) { darshan_initialize(*argc, *argv, nprocs, rank); } else { /* we don't see argc and argv here in fortran */ darshan_initialize(0, NULL, nprocs, rank); } if(timing_flag) { init_time = DARSHAN_MPI_CALL(PMPI_Wtime)() - init_start; DARSHAN_MPI_CALL(PMPI_Reduce)(&init_time, &init_max, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD); if(rank == 0) { printf("#darshan:\t\t