1 /* 2 * 3 * This is the SyncIO library that uses MPI-IO collective functions to 4 * implement a flexible I/O checkpoint solution for a large number of 5 * processors. 6 * 7 * Previous developer: Ning Liu (liun2@cs.rpi.edu) 8 * Jing Fu (fuj@cs.rpi.edu) 9 * Current developers: Michel Rasquin (Michel.Rasquin@colorado.edu), 10 * Ben Matthews (benjamin.a.matthews@colorado.edu) 11 * 12 */ 13 14 #include <map> 15 #include <vector> 16 #include <string> 17 #include <cstdarg> 18 #include <string.h> 19 #include <ctype.h> 20 #include <stdlib.h> 21 #include <stdio.h> 22 #include <math.h> 23 #include <sstream> 24 #include "phastaIO.h" 25 #include "mpi.h" 26 #include "phiotmrc.h" 27 #include "phiostats.h" 28 #include <assert.h> 29 30 #define VERSION_INFO_HEADER_SIZE 8192 31 #define DB_HEADER_SIZE 1024 32 #define ONE_MEGABYTE 1048576 33 #define TWO_MEGABYTE 2097152 34 #define ENDIAN_TEST_NUMBER 12180 // Troy's Zip Code!! 35 #define MAX_PHASTA_FILES 64 36 #define MAX_PHASTA_FILE_NAME_LENGTH 1024 37 #define MAX_FIELDS_NUMBER ((VERSION_INFO_HEADER_SIZE/MAX_FIELDS_NAME_LENGTH)-4) // The meta data include - MPI_IO_Tag, nFields, nFields*names of the fields, nppf 38 // -3 for MPI_IO_Tag, nFields and nppf, -4 for extra security (former nFiles) 39 #define MAX_FIELDS_NAME_LENGTH 128 40 #define DefaultMHSize (4*ONE_MEGABYTE) 41 //#define DefaultMHSize (8350) //For test 42 #define LATEST_WRITE_VERSION 1 43 #define inv1024sq 953.674316406e-9 // = 1/1024/1024 44 int MasterHeaderSize = -1; 45 46 bool PRINT_PERF = false; // default print no perf results 47 int irank = -1; // global rank, should never be manually manipulated 48 int mysize = -1; 49 50 // Static variables are bad but used here to store the subcommunicator and associated variables 51 // Prevent MPI_Comm_split to be called more than once, especially on BGQ with the V1R2M1 driver (leak detected in MPI_Comm_split - IBM working on it) 52 static int s_assign_local_comm = 0; 53 static MPI_Comm s_local_comm; 54 static int s_local_size = -1; 55 static int s_local_rank = -1; 56 57 // the following defines are for debug printf 58 #define PHASTAIO_DEBUG 0 //default to not print any debugging info 59 60 void phprintf(const char* fmt, ...) { 61 (void)fmt; 62 #if PHASTAIO_DEBUG 63 char format[1024]; 64 snprintf(format, sizeof(format), "phastaIO debug: %s", fmt); 65 va_list ap; 66 va_start(ap,fmt); 67 vprintf(format,ap); 68 va_end(ap); 69 #endif 70 } 71 72 void phprintf_0(const char* fmt, ...) { 73 (void)fmt; 74 #if PHASTAIO_DEBUG 75 int rank = 0; 76 MPI_Comm_rank(MPI_COMM_WORLD, &rank); 77 if(rank == 0){ 78 char format[1024]; 79 snprintf(format, sizeof(format), "phastaIO debug: irank=0 %s", fmt); 80 va_list ap; 81 va_start(ap,fmt); 82 vprintf(format, ap); 83 va_end(ap); 84 } 85 #endif 86 } 87 88 enum PhastaIO_Errors 89 { 90 MAX_PHASTA_FILES_EXCEEDED = -1, 91 UNABLE_TO_OPEN_FILE = -2, 92 NOT_A_MPI_FILE = -3, 93 GPID_EXCEEDED = -4, 94 DATA_TYPE_ILLEGAL = -5 95 }; 96 97 using namespace std; 98 99 namespace{ 100 101 map<int, std::string> LastHeaderKey; 102 vector< FILE* > fileArray; 103 vector< bool > byte_order; 104 vector< int > header_type; 105 int DataSize=0; 106 bool LastHeaderNotFound = false; 107 bool Wrong_Endian = false ; 108 bool Strict_Error = false ; 109 bool binary_format = true; 110 111 /***********************************************************************/ 112 /***************** NEW PHASTA IO CODE STARTS HERE **********************/ 113 /***********************************************************************/ 114 115 typedef struct 116 { 117 char filename[MAX_PHASTA_FILE_NAME_LENGTH]; /* defafults to 1024 */ 118 unsigned long my_offset; 119 unsigned long next_start_address; 120 unsigned long **my_offset_table; 121 unsigned long **my_read_table; 122 123 double * double_chunk; 124 double * read_double_chunk; 125 126 int field_count; 127 int part_count; 128 int read_field_count; 129 int read_part_count; 130 int GPid; 131 int start_id; 132 133 int mhsize; 134 135 int myrank; 136 int numprocs; 137 int local_myrank; 138 int local_numprocs; 139 140 int nppp; 141 int nPPF; 142 int nFiles; 143 int nFields; 144 145 int * int_chunk; 146 int * read_int_chunk; 147 148 int Wrong_Endian; /* default to false */ 149 char * master_header; 150 MPI_File file_handle; 151 MPI_Comm local_comm; 152 } phastaio_file_t; 153 154 typedef struct 155 { 156 int nppf, nfields; 157 char * masterHeader; 158 }serial_file; 159 160 serial_file *SerialFile; 161 phastaio_file_t *PhastaIOActiveFiles[MAX_PHASTA_FILES]; 162 int PhastaIONextActiveIndex = 0; /* indicates next index to allocate */ 163 164 // the caller has the responsibility to delete the returned string 165 // TODO: StringStipper("nbc value? ") returns NULL? 166 char* StringStripper( const char istring[] ) { 167 int length = strlen( istring ); 168 char* dest = (char *)malloc( length + 1 ); 169 strcpy( dest, istring ); 170 dest[ length ] = '\0'; 171 if ( char* p = strpbrk( dest, " ") ) 172 *p = '\0'; 173 return dest; 174 } 175 176 inline int cscompare( const char teststring[], const char targetstring[] ) { 177 char* s1 = const_cast<char*>(teststring); 178 char* s2 = const_cast<char*>(targetstring); 179 180 while( *s1 == ' ') s1++; 181 while( *s2 == ' ') s2++; 182 while( ( *s1 ) 183 && ( *s2 ) 184 && ( *s2 != '?') 185 && ( tolower( *s1 )==tolower( *s2 ) ) ) { 186 s1++; 187 s2++; 188 while( *s1 == ' ') s1++; 189 while( *s2 == ' ') s2++; 190 } 191 if ( !( *s1 ) || ( *s1 == '?') ) return 1; 192 else return 0; 193 } 194 195 inline void isBinary( const char iotype[] ) { 196 char* fname = StringStripper( iotype ); 197 if ( cscompare( fname, "binary" ) ) binary_format = true; 198 else binary_format = false; 199 free (fname); 200 201 } 202 203 inline size_t typeSize( const char typestring[] ) { 204 char* ts1 = StringStripper( typestring ); 205 if ( cscompare( "integer", ts1 ) ) { 206 free (ts1); 207 return sizeof(int); 208 } else if ( cscompare( "double", ts1 ) ) { 209 free (ts1); 210 return sizeof( double ); 211 } else { 212 free (ts1); 213 fprintf(stderr,"unknown type : %s\n",ts1); 214 return 0; 215 } 216 } 217 218 int readHeader( 219 FILE* fileObject, 220 const char phrase[], 221 int* params, 222 int expect ) { 223 char* text_header; 224 char* token; 225 char Line[1024] = "\0"; 226 char junk; 227 bool FOUND = false ; 228 int real_length; 229 int skip_size, integer_value; 230 int rewind_count=0; 231 232 if( !fgets( Line, 1024, fileObject ) && feof( fileObject ) ) { 233 rewind( fileObject ); 234 clearerr( fileObject ); 235 rewind_count++; 236 fgets( Line, 1024, fileObject ); 237 } 238 239 while( !FOUND && ( rewind_count < 2 ) ) { 240 if ( ( Line[0] != '\n' ) && ( real_length = strcspn( Line, "#" )) ) { 241 text_header = (char *)malloc( real_length + 1 ); 242 strncpy( text_header, Line, real_length ); 243 text_header[ real_length ] =static_cast<char>(NULL); 244 token = strtok ( text_header, ":" ); 245 assert(token); 246 if( cscompare( phrase , token ) ) { 247 FOUND = true ; 248 token = strtok( NULL, " ,;<>" ); 249 assert(token); 250 skip_size = atoi( token ); 251 int i; 252 for( i=0; i < expect && ( token = strtok( NULL," ,;<>") ); i++) { 253 assert(token); 254 params[i] = atoi( token ); 255 } 256 if ( i < expect ) { 257 fprintf(stderr, 258 "Aloha Expected # of ints not found for: %s\n",phrase ); 259 } 260 } else if ( cscompare(token,"byteorder magic number") ) { 261 if ( binary_format ) { 262 fread((void*)&integer_value,sizeof(int),1,fileObject); 263 fread( &junk, sizeof(char), 1 , fileObject ); 264 if ( 362436 != integer_value ) Wrong_Endian = true; 265 } else{ 266 fscanf(fileObject, "%d\n", &integer_value ); 267 } 268 } else { 269 /* some other header, so just skip over */ 270 token = strtok( NULL, " ,;<>" ); 271 assert(token); 272 skip_size = atoi( token ); 273 if ( binary_format) 274 fseek( fileObject, skip_size, SEEK_CUR ); 275 else 276 for( int gama=0; gama < skip_size; gama++ ) 277 fgets( Line, 1024, fileObject ); 278 } 279 free (text_header); 280 } // end of if before while loop 281 282 if ( !FOUND ) 283 if( !fgets( Line, 1024, fileObject ) && feof( fileObject ) ) { 284 rewind( fileObject ); 285 clearerr( fileObject ); 286 rewind_count++; 287 fgets( Line, 1024, fileObject ); 288 } 289 } 290 291 if ( !FOUND ) { 292 //fprintf(stderr, "Error: Could not find: %s\n", phrase); 293 if(irank == 0) printf("WARNING: Could not find: %s\n", phrase); 294 return 1; 295 } 296 return 0; 297 } 298 299 } // end unnamed namespace 300 301 302 // begin of publicly visible functions 303 304 /** 305 * This function takes a long long pointer and assign (start) phiotmrc value to it 306 */ 307 void startTimer(double* start) { 308 if( !PRINT_PERF ) return; 309 MPI_Barrier(MPI_COMM_WORLD); 310 *start = phiotmrc(); 311 } 312 313 /** 314 * This function takes a long long pointer and assign (end) phiotmrc value to it 315 */ 316 void endTimer(double* end) { 317 if( !PRINT_PERF ) return; 318 *end = phiotmrc(); 319 MPI_Barrier(MPI_COMM_WORLD); 320 } 321 322 /** 323 * choose to print some performance results (or not) according to 324 * the PRINT_PERF macro 325 */ 326 void printPerf( 327 const char* func_name, 328 double start, 329 double end, 330 unsigned long datasize, 331 int printdatainfo, 332 const char* extra_msg) { 333 if( !PRINT_PERF ) return; 334 unsigned long data_size = datasize; 335 double time = end - start; 336 unsigned long isizemin,isizemax,isizetot; 337 double sizemin,sizemax,sizeavg,sizetot,rate; 338 double tmin, tmax, tavg, ttot; 339 340 MPI_Allreduce(&time, &tmin,1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); 341 MPI_Allreduce(&time, &tmax,1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); 342 MPI_Allreduce(&time, &ttot,1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); 343 tavg = ttot/mysize; 344 345 if(irank == 0) { 346 if ( PhastaIONextActiveIndex == 0 ) printf("** 1PFPP "); 347 else printf("** syncIO "); 348 printf("%s(): Tmax = %f sec, Tmin = %f sec, Tavg = %f sec", func_name, tmax, tmin, tavg); 349 } 350 351 if(printdatainfo == 1) { // if printdatainfo ==1, compute I/O rate and block size 352 MPI_Allreduce(&data_size,&isizemin,1,MPI_LONG_LONG_INT,MPI_MIN,MPI_COMM_WORLD); 353 MPI_Allreduce(&data_size,&isizemax,1,MPI_LONG_LONG_INT,MPI_MAX,MPI_COMM_WORLD); 354 MPI_Allreduce(&data_size,&isizetot,1,MPI_LONG_LONG_INT,MPI_SUM,MPI_COMM_WORLD); 355 356 sizemin=(double)(isizemin*inv1024sq); 357 sizemax=(double)(isizemax*inv1024sq); 358 sizetot=(double)(isizetot*inv1024sq); 359 sizeavg=(double)(1.0*sizetot/mysize); 360 rate=(double)(1.0*sizetot/tmax); 361 362 if( irank == 0) { 363 printf(", Rate = %f MB/s [%s] \n \t\t\t" 364 " block size: Min= %f MB; Max= %f MB; Avg= %f MB; Tot= %f MB\n", 365 rate, extra_msg, sizemin,sizemax,sizeavg,sizetot); 366 } 367 } 368 else { 369 if(irank == 0) { 370 printf(" \n"); 371 //printf(" (%s) \n", extra_msg); 372 } 373 } 374 } 375 376 /** 377 * This function is normally called at the beginning of a read operation, before 378 * init function. 379 * This function (uses rank 0) reads out nfields, nppf, master header size, 380 * endianess and allocates for masterHeader string. 381 * These values are essential for following read operations. Rank 0 will bcast 382 * these values to other ranks in the commm world 383 * 384 * If the file set is of old POSIX format, it would throw error and exit 385 */ 386 void queryphmpiio(const char filename[],int *nfields, int *nppf) 387 { 388 MPI_Comm_rank(MPI_COMM_WORLD, &irank); 389 MPI_Comm_size(MPI_COMM_WORLD, &mysize); 390 391 if(irank == 0) { 392 FILE * fileHandle; 393 char* fname = StringStripper( filename ); 394 395 double t0 = phiotmrc(); 396 fileHandle = fopen (fname,"rb"); 397 phastaio_addOpenTime(phiotmrc()-t0); 398 if (fileHandle == NULL ) { 399 printf("\nError: File %s doesn't exist! Please check!\n",fname); 400 } 401 else { 402 SerialFile =(serial_file *)calloc( 1, sizeof( serial_file) ); 403 int meta_size_limit = VERSION_INFO_HEADER_SIZE; 404 SerialFile->masterHeader = (char *)malloc( meta_size_limit ); 405 fread(SerialFile->masterHeader, 1, meta_size_limit, fileHandle); 406 407 char read_out_tag[MAX_FIELDS_NAME_LENGTH]; 408 char version[MAX_FIELDS_NAME_LENGTH/4]; 409 int mhsize; 410 char * token; 411 int magic_number; 412 413 memcpy( read_out_tag, 414 SerialFile->masterHeader, 415 MAX_FIELDS_NAME_LENGTH-1 ); 416 417 if ( cscompare ("MPI_IO_Tag",read_out_tag) ) { 418 // Test endianess ... 419 memcpy (&magic_number, 420 SerialFile->masterHeader + sizeof("MPI_IO_Tag : ")-1, //-1 sizeof returns the size of the string+1 for "\0" 421 sizeof(int) ); // masterheader should look like "MPI_IO_Tag : 12180 " with 12180 in binary format 422 423 if ( magic_number != ENDIAN_TEST_NUMBER ) { 424 printf("Endian is different!\n"); 425 // Will do swap later 426 } 427 428 // test version, old version, default masterheader size is 4M 429 // newer version masterheader size is read from first line 430 memcpy(version, 431 SerialFile->masterHeader + MAX_FIELDS_NAME_LENGTH/2, 432 MAX_FIELDS_NAME_LENGTH/4 - 1); //TODO: why -1? 433 434 if( cscompare ("version",version) ) { 435 // if there is "version" tag in the file, then it is newer format 436 // read master header size from here, otherwise use default 437 // Note: if version is "1", we know mhsize is at 3/4 place... 438 439 token = strtok(version, ":"); 440 token = strtok(NULL, " ,;<>" ); 441 int iversion = atoi(token); 442 443 if( iversion == 1) { 444 memcpy( &mhsize, 445 SerialFile->masterHeader + MAX_FIELDS_NAME_LENGTH/4*3 + sizeof("mhsize : ")-1, 446 sizeof(int)); 447 if ( magic_number != ENDIAN_TEST_NUMBER ) 448 SwapArrayByteOrder(&mhsize, sizeof(int), 1); 449 450 if( mhsize > DefaultMHSize ) { 451 //if actual headersize is larger than default, let's re-read 452 free(SerialFile->masterHeader); 453 SerialFile->masterHeader = (char *)malloc(mhsize); 454 fseek(fileHandle, 0, SEEK_SET); // reset the file stream position 455 fread(SerialFile->masterHeader,1,mhsize,fileHandle); 456 } 457 } 458 //TODO: check if this is a valid int?? 459 MasterHeaderSize = mhsize; 460 } 461 else { // else it's version 0's format w/o version tag, implicating MHSize=4M 462 MasterHeaderSize = DefaultMHSize; 463 } 464 465 memcpy( read_out_tag, 466 SerialFile->masterHeader+MAX_FIELDS_NAME_LENGTH+1, 467 MAX_FIELDS_NAME_LENGTH ); //TODO: why +1 468 469 // Read in # fields ... 470 token = strtok( read_out_tag, ":" ); 471 token = strtok( NULL," ,;<>" ); 472 *nfields = atoi( token ); 473 if ( *nfields > MAX_FIELDS_NUMBER) { 474 printf("Error queryphmpiio: nfields is larger than MAX_FIELDS_NUMBER!\n"); 475 } 476 SerialFile->nfields=*nfields; //TODO: sanity check of this int? 477 478 memcpy( read_out_tag, 479 SerialFile->masterHeader + MAX_FIELDS_NAME_LENGTH * 2 480 + *nfields * MAX_FIELDS_NAME_LENGTH, 481 MAX_FIELDS_NAME_LENGTH); 482 483 token = strtok( read_out_tag, ":" ); 484 token = strtok( NULL," ,;<>" ); 485 *nppf = atoi( token ); 486 SerialFile->nppf=*nppf; //TODO: sanity check of int 487 } // end of if("MPI_IO_TAG") 488 else { 489 printf("Error queryphmpiio: The file you opened is not of syncIO new format, please check! read_out_tag = %s\n",read_out_tag); 490 exit(1); 491 } 492 double t0 = phiotmrc(); 493 fclose(fileHandle); 494 phastaio_addCloseTime(phiotmrc()-t0); 495 free(SerialFile->masterHeader); 496 free(SerialFile); 497 } //end of else 498 free(fname); 499 } 500 501 // Bcast value to every one 502 MPI_Bcast( nfields, 1, MPI_INT, 0, MPI_COMM_WORLD ); 503 MPI_Bcast( nppf, 1, MPI_INT, 0, MPI_COMM_WORLD ); 504 MPI_Bcast( &MasterHeaderSize, 1, MPI_INT, 0, MPI_COMM_WORLD ); 505 phprintf("Info queryphmpiio: myrank = %d, MasterHeaderSize = %d\n", irank, MasterHeaderSize); 506 } 507 508 /** 509 * This function computes the right master header size (round to size of 2^n). 510 * This is only needed for file format version 1 in "write" mode. 511 */ 512 int computeMHSize(int nfields, int nppf, int version) { 513 int mhsize=0; 514 if(version == 1) { 515 //int meta_info_size = (2+nfields+1) * MAX_FIELDS_NAME_LENGTH; // 2 is MPI_IO_TAG and nFields, the others 1 is nppf 516 int meta_info_size = VERSION_INFO_HEADER_SIZE; 517 int actual_size = nfields * nppf * sizeof(unsigned long) + meta_info_size; 518 //printf("actual_size = %d, offset table size = %d\n", actual_size, nfields * nppf * sizeof(long long)); 519 if (actual_size > DefaultMHSize) { 520 mhsize = (int) ceil( (double) actual_size/DefaultMHSize); // it's rounded to ceiling of this value 521 mhsize *= DefaultMHSize; 522 } 523 else { 524 mhsize = DefaultMHSize; 525 } 526 } else { 527 int rank = 0; 528 MPI_Comm_rank(MPI_COMM_WORLD, &rank); 529 if(!rank) { 530 fprintf(stderr, 531 "ERROR invalid version passed to %s... exiting\n", __func__); 532 exit(EXIT_FAILURE); 533 } 534 } 535 return mhsize; 536 } 537 538 /** 539 * Computes correct color of a rank according to number of files. 540 */ 541 extern "C" int computeColor( int myrank, int numprocs, int nfiles) { 542 int color = 543 (int)(myrank / (numprocs / nfiles)); 544 return color; 545 } 546 547 548 /** 549 * Check the file descriptor. 550 */ 551 void checkFileDescriptor(const char fctname[], int* fileDescriptor ) { 552 if ( *fileDescriptor < 0 ) { 553 printf("Error: File descriptor = %d in %s\n",*fileDescriptor,fctname); 554 exit(1); 555 } 556 } 557 558 /** 559 * Initialize the file struct members and allocate space for file struct 560 * buffers. 561 * 562 * Note: this function is only called when we are using new format. Old POSIX 563 * format should skip this routine and call openfile() directly instead. 564 */ 565 int initphmpiio( int *nfields, int *nppf, int *nfiles, int *filehandle, const char mode[]) 566 { 567 // we init irank again in case query not called (e.g. syncIO write case) 568 MPI_Comm_rank(MPI_COMM_WORLD, &irank); 569 MPI_Comm_size(MPI_COMM_WORLD, &mysize); 570 571 phprintf("Info initphmpiio: entering function, myrank = %d, MasterHeaderSize = %d, nfields %d, nppf %d, nfiles %d\n", irank, MasterHeaderSize, *nfields, *nppf, *nfiles); 572 573 double timer_start, timer_end; 574 startTimer(&timer_start); 575 576 char* imode = StringStripper( mode ); 577 578 // Note: if it's read, we presume query was called prior to init and 579 // MasterHeaderSize is already set to correct value from parsing header 580 // otherwise it's write then it needs some computation to be set 581 if ( cscompare( "read", imode ) ) { 582 // do nothing 583 } 584 else if( cscompare( "write", imode ) ) { 585 MasterHeaderSize = computeMHSize(*nfields, *nppf, LATEST_WRITE_VERSION); 586 } 587 else { 588 printf("Error initphmpiio: can't recognize the mode %s", imode); 589 exit(1); 590 } 591 free ( imode ); 592 593 phprintf("Info initphmpiio: myrank = %d, MasterHeaderSize = %d\n", irank, MasterHeaderSize); 594 595 int i, j; 596 597 if( PhastaIONextActiveIndex == MAX_PHASTA_FILES ) { 598 printf("Error initphmpiio: PhastaIONextActiveIndex = MAX_PHASTA_FILES"); 599 endTimer(&timer_end); 600 printPerf("initphmpiio", timer_start, timer_end, 0, 0, ""); 601 return MAX_PHASTA_FILES_EXCEEDED; 602 } 603 // else if( PhastaIONextActiveIndex == 0 ) //Hang in debug mode on Intrepid 604 // { 605 // for( i = 0; i < MAX_PHASTA_FILES; i++ ); 606 // { 607 // PhastaIOActiveFiles[i] = NULL; 608 // } 609 // } 610 611 612 PhastaIOActiveFiles[PhastaIONextActiveIndex] = (phastaio_file_t *)calloc( 1, sizeof( phastaio_file_t) ); 613 614 i = PhastaIONextActiveIndex; 615 PhastaIONextActiveIndex++; 616 617 //PhastaIOActiveFiles[i]->next_start_address = 2*TWO_MEGABYTE; 618 619 PhastaIOActiveFiles[i]->next_start_address = MasterHeaderSize; // what does this mean??? TODO 620 621 PhastaIOActiveFiles[i]->Wrong_Endian = false; 622 623 PhastaIOActiveFiles[i]->nFields = *nfields; 624 PhastaIOActiveFiles[i]->nPPF = *nppf; 625 PhastaIOActiveFiles[i]->nFiles = *nfiles; 626 MPI_Comm_rank(MPI_COMM_WORLD, &(PhastaIOActiveFiles[i]->myrank)); 627 MPI_Comm_size(MPI_COMM_WORLD, &(PhastaIOActiveFiles[i]->numprocs)); 628 629 630 if( *nfiles > 1 ) { // split the ranks according to each mpiio file 631 632 if ( s_assign_local_comm == 0) { // call mpi_comm_split for the first (and only) time 633 634 if (PhastaIOActiveFiles[i]->myrank == 0) printf("Building subcommunicator\n"); 635 636 int color = computeColor(PhastaIOActiveFiles[i]->myrank, PhastaIOActiveFiles[i]->numprocs, PhastaIOActiveFiles[i]->nFiles); 637 MPI_Comm_split(MPI_COMM_WORLD, 638 color, 639 PhastaIOActiveFiles[i]->myrank, 640 &(PhastaIOActiveFiles[i]->local_comm)); 641 MPI_Comm_size(PhastaIOActiveFiles[i]->local_comm, 642 &(PhastaIOActiveFiles[i]->local_numprocs)); 643 MPI_Comm_rank(PhastaIOActiveFiles[i]->local_comm, 644 &(PhastaIOActiveFiles[i]->local_myrank)); 645 646 // back up now these variables so that we do not need to call comm_split again 647 s_local_comm = PhastaIOActiveFiles[i]->local_comm; 648 s_local_size = PhastaIOActiveFiles[i]->local_numprocs; 649 s_local_rank = PhastaIOActiveFiles[i]->local_myrank; 650 s_assign_local_comm = 1; 651 } 652 else { // recycle the subcommunicator 653 if (PhastaIOActiveFiles[i]->myrank == 0) printf("Recycling subcommunicator\n"); 654 PhastaIOActiveFiles[i]->local_comm = s_local_comm; 655 PhastaIOActiveFiles[i]->local_numprocs = s_local_size; 656 PhastaIOActiveFiles[i]->local_myrank = s_local_rank; 657 } 658 } 659 else { // *nfiles == 1 here - no need to call mpi_comm_split here 660 661 if (PhastaIOActiveFiles[i]->myrank == 0) printf("Bypassing subcommunicator\n"); 662 PhastaIOActiveFiles[i]->local_comm = MPI_COMM_WORLD; 663 PhastaIOActiveFiles[i]->local_numprocs = PhastaIOActiveFiles[i]->numprocs; 664 PhastaIOActiveFiles[i]->local_myrank = PhastaIOActiveFiles[i]->myrank; 665 666 } 667 668 PhastaIOActiveFiles[i]->nppp = 669 PhastaIOActiveFiles[i]->nPPF/PhastaIOActiveFiles[i]->local_numprocs; 670 671 PhastaIOActiveFiles[i]->start_id = PhastaIOActiveFiles[i]->nPPF * 672 (int)(PhastaIOActiveFiles[i]->myrank/PhastaIOActiveFiles[i]->local_numprocs) + 673 (PhastaIOActiveFiles[i]->local_myrank * PhastaIOActiveFiles[i]->nppp); 674 675 PhastaIOActiveFiles[i]->my_offset_table = 676 ( unsigned long ** ) calloc( MAX_FIELDS_NUMBER , sizeof( unsigned long *) ); 677 678 PhastaIOActiveFiles[i]->my_read_table = 679 ( unsigned long ** ) calloc( MAX_FIELDS_NUMBER , sizeof( unsigned long *) ); 680 681 for (j=0; j<*nfields; j++) 682 { 683 PhastaIOActiveFiles[i]->my_offset_table[j] = 684 ( unsigned long * ) calloc( PhastaIOActiveFiles[i]->nppp , sizeof( unsigned long) ); 685 686 PhastaIOActiveFiles[i]->my_read_table[j] = 687 ( unsigned long * ) calloc( PhastaIOActiveFiles[i]->nppp , sizeof( unsigned long) ); 688 } 689 *filehandle = i; 690 691 PhastaIOActiveFiles[i]->master_header = (char *)calloc(MasterHeaderSize,sizeof( char )); 692 PhastaIOActiveFiles[i]->double_chunk = (double *)calloc(1,sizeof( double )); 693 PhastaIOActiveFiles[i]->int_chunk = (int *)calloc(1,sizeof( int )); 694 PhastaIOActiveFiles[i]->read_double_chunk = (double *)calloc(1,sizeof( double )); 695 PhastaIOActiveFiles[i]->read_int_chunk = (int *)calloc(1,sizeof( int )); 696 697 // Time monitoring 698 endTimer(&timer_end); 699 printPerf("initphmpiio", timer_start, timer_end, 0, 0, ""); 700 701 phprintf_0("Info initphmpiio: quiting function"); 702 703 return i; 704 } 705 706 /** 707 * Destruct the file struct and free buffers allocated in init function. 708 */ 709 void finalizephmpiio( int *fileDescriptor ) 710 { 711 double timer_start, timer_end; 712 startTimer(&timer_start); 713 714 int i, j; 715 i = *fileDescriptor; 716 //PhastaIONextActiveIndex--; 717 718 /* //free the offset table for this phasta file */ 719 //for(j=0; j<MAX_FIELDS_NUMBER; j++) //Danger: undefined behavior for my_*_table.[j] not allocated or not initialized to NULL 720 for(j=0; j<PhastaIOActiveFiles[i]->nFields; j++) 721 { 722 free( PhastaIOActiveFiles[i]->my_offset_table[j]); 723 free( PhastaIOActiveFiles[i]->my_read_table[j]); 724 } 725 free ( PhastaIOActiveFiles[i]->my_offset_table ); 726 free ( PhastaIOActiveFiles[i]->my_read_table ); 727 free ( PhastaIOActiveFiles[i]->master_header ); 728 free ( PhastaIOActiveFiles[i]->double_chunk ); 729 free ( PhastaIOActiveFiles[i]->int_chunk ); 730 free ( PhastaIOActiveFiles[i]->read_double_chunk ); 731 free ( PhastaIOActiveFiles[i]->read_int_chunk ); 732 733 if( PhastaIOActiveFiles[i]->nFiles > 1 && s_assign_local_comm ) { // the comm was split 734 if (PhastaIOActiveFiles[i]->myrank == 0) printf("Freeing subcommunicator\n"); 735 s_assign_local_comm = 0; 736 MPI_Comm_free(&(PhastaIOActiveFiles[i]->local_comm)); 737 } 738 739 free( PhastaIOActiveFiles[i]); 740 741 endTimer(&timer_end); 742 printPerf("finalizempiio", timer_start, timer_end, 0, 0, ""); 743 744 PhastaIONextActiveIndex--; 745 } 746 747 748 /** 749 * Special init for M2N in order to create a subcommunicator for the reduced solution (requires PRINT_PERF to be false for now) 750 * Initialize the file struct members and allocate space for file struct buffers. 751 * 752 * Note: this function is only called when we are using new format. Old POSIX 753 * format should skip this routine and call openfile() directly instead. 754 */ 755 int initphmpiiosub( int *nfields, int *nppf, int *nfiles, int *filehandle, const char mode[],MPI_Comm my_local_comm) 756 { 757 // we init irank again in case query not called (e.g. syncIO write case) 758 759 MPI_Comm_rank(my_local_comm, &irank); 760 MPI_Comm_size(my_local_comm, &mysize); 761 762 phprintf("Info initphmpiio: entering function, myrank = %d, MasterHeaderSize = %d\n", irank, MasterHeaderSize); 763 764 double timer_start, timer_end; 765 startTimer(&timer_start); 766 767 char* imode = StringStripper( mode ); 768 769 // Note: if it's read, we presume query was called prior to init and 770 // MasterHeaderSize is already set to correct value from parsing header 771 // otherwise it's write then it needs some computation to be set 772 if ( cscompare( "read", imode ) ) { 773 // do nothing 774 } 775 else if( cscompare( "write", imode ) ) { 776 MasterHeaderSize = computeMHSize(*nfields, *nppf, LATEST_WRITE_VERSION); 777 } 778 else { 779 printf("Error initphmpiio: can't recognize the mode %s", imode); 780 exit(1); 781 } 782 free ( imode ); 783 784 phprintf("Info initphmpiio: myrank = %d, MasterHeaderSize = %d\n", irank, MasterHeaderSize); 785 786 int i, j; 787 788 if( PhastaIONextActiveIndex == MAX_PHASTA_FILES ) { 789 printf("Error initphmpiio: PhastaIONextActiveIndex = MAX_PHASTA_FILES"); 790 endTimer(&timer_end); 791 printPerf("initphmpiio", timer_start, timer_end, 0, 0, ""); 792 return MAX_PHASTA_FILES_EXCEEDED; 793 } 794 // else if( PhastaIONextActiveIndex == 0 ) //Hang in debug mode on Intrepid 795 // { 796 // for( i = 0; i < MAX_PHASTA_FILES; i++ ); 797 // { 798 // PhastaIOActiveFiles[i] = NULL; 799 // } 800 // } 801 802 803 PhastaIOActiveFiles[PhastaIONextActiveIndex] = (phastaio_file_t *)calloc( 1, sizeof( phastaio_file_t) ); 804 805 i = PhastaIONextActiveIndex; 806 PhastaIONextActiveIndex++; 807 808 //PhastaIOActiveFiles[i]->next_start_address = 2*TWO_MEGABYTE; 809 810 PhastaIOActiveFiles[i]->next_start_address = MasterHeaderSize; // what does this mean??? TODO 811 812 PhastaIOActiveFiles[i]->Wrong_Endian = false; 813 814 PhastaIOActiveFiles[i]->nFields = *nfields; 815 PhastaIOActiveFiles[i]->nPPF = *nppf; 816 PhastaIOActiveFiles[i]->nFiles = *nfiles; 817 MPI_Comm_rank(my_local_comm, &(PhastaIOActiveFiles[i]->myrank)); 818 MPI_Comm_size(my_local_comm, &(PhastaIOActiveFiles[i]->numprocs)); 819 820 int color = computeColor(PhastaIOActiveFiles[i]->myrank, PhastaIOActiveFiles[i]->numprocs, PhastaIOActiveFiles[i]->nFiles); 821 MPI_Comm_split(my_local_comm, 822 color, 823 PhastaIOActiveFiles[i]->myrank, 824 &(PhastaIOActiveFiles[i]->local_comm)); 825 MPI_Comm_size(PhastaIOActiveFiles[i]->local_comm, 826 &(PhastaIOActiveFiles[i]->local_numprocs)); 827 MPI_Comm_rank(PhastaIOActiveFiles[i]->local_comm, 828 &(PhastaIOActiveFiles[i]->local_myrank)); 829 PhastaIOActiveFiles[i]->nppp = 830 PhastaIOActiveFiles[i]->nPPF/PhastaIOActiveFiles[i]->local_numprocs; 831 832 PhastaIOActiveFiles[i]->start_id = PhastaIOActiveFiles[i]->nPPF * 833 (int)(PhastaIOActiveFiles[i]->myrank/PhastaIOActiveFiles[i]->local_numprocs) + 834 (PhastaIOActiveFiles[i]->local_myrank * PhastaIOActiveFiles[i]->nppp); 835 836 PhastaIOActiveFiles[i]->my_offset_table = 837 ( unsigned long ** ) calloc( MAX_FIELDS_NUMBER , sizeof( unsigned long *) ); 838 839 PhastaIOActiveFiles[i]->my_read_table = 840 ( unsigned long ** ) calloc( MAX_FIELDS_NUMBER , sizeof( unsigned long *) ); 841 842 for (j=0; j<*nfields; j++) 843 { 844 PhastaIOActiveFiles[i]->my_offset_table[j] = 845 ( unsigned long * ) calloc( PhastaIOActiveFiles[i]->nppp , sizeof( unsigned long) ); 846 847 PhastaIOActiveFiles[i]->my_read_table[j] = 848 ( unsigned long * ) calloc( PhastaIOActiveFiles[i]->nppp , sizeof( unsigned long) ); 849 } 850 *filehandle = i; 851 852 PhastaIOActiveFiles[i]->master_header = (char *)calloc(MasterHeaderSize,sizeof( char )); 853 PhastaIOActiveFiles[i]->double_chunk = (double *)calloc(1,sizeof( double )); 854 PhastaIOActiveFiles[i]->int_chunk = (int *)calloc(1,sizeof( int )); 855 PhastaIOActiveFiles[i]->read_double_chunk = (double *)calloc(1,sizeof( double )); 856 PhastaIOActiveFiles[i]->read_int_chunk = (int *)calloc(1,sizeof( int )); 857 858 // Time monitoring 859 endTimer(&timer_end); 860 printPerf("initphmpiiosub", timer_start, timer_end, 0, 0, ""); 861 862 phprintf_0("Info initphmpiiosub: quiting function"); 863 864 return i; 865 } 866 867 868 869 /** open file for both POSIX and MPI-IO syncIO format. 870 * 871 * If it's old POSIX format, simply call posix fopen(). 872 * 873 * If it's MPI-IO foramt: 874 * in "read" mode, it builds the header table that points to the offset of 875 * fields for parts; 876 * in "write" mode, it opens the file with MPI-IO open routine. 877 */ 878 void openfile(const char filename[], const char mode[], int* fileDescriptor ) 879 { 880 phprintf_0("Info: entering openfile"); 881 882 double timer_start, timer_end; 883 startTimer(&timer_start); 884 885 if ( PhastaIONextActiveIndex == 0 ) 886 { 887 FILE* file=NULL ; 888 *fileDescriptor = 0; 889 char* fname = StringStripper( filename ); 890 char* imode = StringStripper( mode ); 891 892 double t0 = phiotmrc(); 893 if ( cscompare( "read", imode ) ) file = fopen(fname, "rb" ); 894 else if( cscompare( "write", imode ) ) file = fopen(fname, "wb" ); 895 else if( cscompare( "append", imode ) ) file = fopen(fname, "ab" ); 896 phastaio_addOpenTime(phiotmrc()-t0); 897 898 if ( !file ){ 899 fprintf(stderr,"Error openfile: unable to open file %s\n",fname); 900 } else { 901 fileArray.push_back( file ); 902 byte_order.push_back( false ); 903 header_type.push_back( sizeof(int) ); 904 *fileDescriptor = fileArray.size(); 905 } 906 free (fname); 907 free (imode); 908 } 909 else // else it would be parallel I/O, opposed to posix io 910 { 911 char* fname = StringStripper( filename ); 912 char* imode = StringStripper( mode ); 913 int rc; 914 int i = *fileDescriptor; 915 checkFileDescriptor("openfile",&i); 916 char* token; 917 918 if ( cscompare( "read", imode ) ) 919 { 920 // if (PhastaIOActiveFiles[i]->myrank == 0) 921 // printf("\n **********\nRead open ... ... regular version\n"); 922 923 double t0 = phiotmrc(); 924 rc = MPI_File_open( PhastaIOActiveFiles[i]->local_comm, 925 fname, 926 MPI_MODE_RDONLY, 927 MPI_INFO_NULL, 928 &(PhastaIOActiveFiles[i]->file_handle) ); 929 phastaio_addOpenTime(phiotmrc()-t0); 930 931 if(rc) 932 { 933 *fileDescriptor = UNABLE_TO_OPEN_FILE; 934 int error_string_length; 935 char error_string[4096]; 936 MPI_Error_string(rc, error_string, &error_string_length); 937 fprintf(stderr, "Error openfile: Unable to open file %s! MPI reports \"%s\"\n",fname,error_string); 938 endTimer(&timer_end); 939 printPerf("openfile", timer_start, timer_end, 0, 0, ""); 940 return; 941 } 942 943 MPI_Status read_tag_status; 944 char read_out_tag[MAX_FIELDS_NAME_LENGTH]; 945 int j; 946 int magic_number; 947 948 if ( PhastaIOActiveFiles[i]->local_myrank == 0 ) { 949 MPI_File_read_at( PhastaIOActiveFiles[i]->file_handle, 950 0, 951 PhastaIOActiveFiles[i]->master_header, 952 MasterHeaderSize, 953 MPI_CHAR, 954 &read_tag_status ); 955 } 956 957 MPI_Bcast( PhastaIOActiveFiles[i]->master_header, 958 MasterHeaderSize, 959 MPI_CHAR, 960 0, 961 PhastaIOActiveFiles[i]->local_comm ); 962 963 memcpy( read_out_tag, 964 PhastaIOActiveFiles[i]->master_header, 965 MAX_FIELDS_NAME_LENGTH-1 ); 966 967 if ( cscompare ("MPI_IO_Tag",read_out_tag) ) 968 { 969 // Test endianess ... 970 memcpy ( &magic_number, 971 PhastaIOActiveFiles[i]->master_header+sizeof("MPI_IO_Tag : ")-1, //-1 sizeof returns the size of the string+1 for "\0" 972 sizeof(int) ); // masterheader should look like "MPI_IO_Tag : 12180 " with 12180 in binary format 973 974 if ( magic_number != ENDIAN_TEST_NUMBER ) 975 { 976 PhastaIOActiveFiles[i]->Wrong_Endian = true; 977 } 978 979 memcpy( read_out_tag, 980 PhastaIOActiveFiles[i]->master_header+MAX_FIELDS_NAME_LENGTH+1, // TODO: WHY +1??? 981 MAX_FIELDS_NAME_LENGTH ); 982 983 // Read in # fields ... 984 token = strtok ( read_out_tag, ":" ); 985 token = strtok( NULL," ,;<>" ); 986 PhastaIOActiveFiles[i]->nFields = atoi( token ); 987 988 unsigned long **header_table; 989 header_table = ( unsigned long ** )calloc(PhastaIOActiveFiles[i]->nFields, sizeof(unsigned long *)); 990 991 for ( j = 0; j < PhastaIOActiveFiles[i]->nFields; j++ ) 992 { 993 header_table[j]=( unsigned long * ) calloc( PhastaIOActiveFiles[i]->nPPF , sizeof( unsigned long)); 994 } 995 996 // Read in the offset table ... 997 for ( j = 0; j < PhastaIOActiveFiles[i]->nFields; j++ ) 998 { 999 if ( PhastaIOActiveFiles[i]->local_myrank == 0 ) { 1000 memcpy( header_table[j], 1001 PhastaIOActiveFiles[i]->master_header + 1002 VERSION_INFO_HEADER_SIZE + 1003 j * PhastaIOActiveFiles[i]->nPPF * sizeof(unsigned long), 1004 PhastaIOActiveFiles[i]->nPPF * sizeof(unsigned long) ); 1005 } 1006 1007 MPI_Scatter( header_table[j], 1008 PhastaIOActiveFiles[i]->nppp, 1009 MPI_LONG_LONG_INT, 1010 PhastaIOActiveFiles[i]->my_read_table[j], 1011 PhastaIOActiveFiles[i]->nppp, 1012 MPI_LONG_LONG_INT, 1013 0, 1014 PhastaIOActiveFiles[i]->local_comm ); 1015 1016 // Swap byte order if endianess is different ... 1017 if ( PhastaIOActiveFiles[i]->Wrong_Endian ) { 1018 SwapArrayByteOrder( PhastaIOActiveFiles[i]->my_read_table[j], 1019 sizeof(unsigned long), 1020 PhastaIOActiveFiles[i]->nppp ); 1021 } 1022 } 1023 1024 for ( j = 0; j < PhastaIOActiveFiles[i]->nFields; j++ ) { 1025 free ( header_table[j] ); 1026 } 1027 free (header_table); 1028 1029 } // end of if MPI_IO_TAG 1030 else //else not valid MPI file 1031 { 1032 *fileDescriptor = NOT_A_MPI_FILE; 1033 printf("Error openfile: The file %s you opened is not in syncIO new format, please check again! File descriptor = %d, MasterHeaderSize = %d, read_out_tag = %s\n",fname,*fileDescriptor,MasterHeaderSize,read_out_tag); 1034 //Printing MasterHeaderSize is useful to test a compiler bug on Intrepid BGP 1035 endTimer(&timer_end); 1036 printPerf("openfile", timer_start, timer_end, 0, 0, ""); 1037 return; 1038 } 1039 } // end of if "read" 1040 else if( cscompare( "write", imode ) ) 1041 { 1042 double t0 = phiotmrc(); 1043 rc = MPI_File_open( PhastaIOActiveFiles[i]->local_comm, 1044 fname, 1045 MPI_MODE_WRONLY | MPI_MODE_CREATE, 1046 MPI_INFO_NULL, 1047 &(PhastaIOActiveFiles[i]->file_handle) ); 1048 phastaio_addOpenTime(phiotmrc()-t0); 1049 if(rc != MPI_SUCCESS) 1050 { 1051 *fileDescriptor = UNABLE_TO_OPEN_FILE; 1052 int error_string_length; 1053 char error_string[4096]; 1054 MPI_Error_string(rc, error_string, &error_string_length); 1055 fprintf(stderr, "Error openfile: Unable to open file %s! MPI reports \"%s\"\n",fname,error_string); 1056 return; 1057 } 1058 } // end of if "write" 1059 free (fname); 1060 free (imode); 1061 } // end of if FileIndex != 0 1062 1063 endTimer(&timer_end); 1064 printPerf("openfile", timer_start, timer_end, 0, 0, ""); 1065 } 1066 1067 /** close file for both POSIX and MPI-IO syncIO format. 1068 * 1069 * If it's old POSIX format, simply call posix fclose(). 1070 * 1071 * If it's MPI-IO foramt: 1072 * in "read" mode, it simply close file with MPI-IO close routine. 1073 * in "write" mode, rank 0 in each group will re-assemble the master header and 1074 * offset table and write to the beginning of file, then close the file. 1075 */ 1076 void closefile( int* fileDescriptor, const char mode[] ) 1077 { 1078 double timer_start, timer_end; 1079 startTimer(&timer_start); 1080 1081 int i = *fileDescriptor; 1082 checkFileDescriptor("closefile",&i); 1083 1084 if ( PhastaIONextActiveIndex == 0 ) { 1085 char* imode = StringStripper( mode ); 1086 1087 if( cscompare( "write", imode ) 1088 || cscompare( "append", imode ) ) { 1089 fflush( fileArray[ *fileDescriptor - 1 ] ); 1090 } 1091 1092 double t0 = phiotmrc(); 1093 fclose( fileArray[ *fileDescriptor - 1 ] ); 1094 phastaio_addCloseTime(phiotmrc()-t0); 1095 free (imode); 1096 } 1097 else { 1098 char* imode = StringStripper( mode ); 1099 1100 //write master header here: 1101 if ( cscompare( "write", imode ) ) { 1102 // if ( PhastaIOActiveFiles[i]->nPPF * PhastaIOActiveFiles[i]->nFields < 2*ONE_MEGABYTE/8 ) //SHOULD BE CHECKED 1103 // MasterHeaderSize = 4*ONE_MEGABYTE; 1104 // else 1105 // MasterHeaderSize = 4*ONE_MEGABYTE + PhastaIOActiveFiles[i]->nPPF * PhastaIOActiveFiles[i]->nFields * 8 - 2*ONE_MEGABYTE; 1106 1107 MasterHeaderSize = computeMHSize( PhastaIOActiveFiles[i]->nFields, PhastaIOActiveFiles[i]->nPPF, LATEST_WRITE_VERSION); 1108 phprintf_0("Info closefile: myrank = %d, MasterHeaderSize = %d\n", PhastaIOActiveFiles[i]->myrank, MasterHeaderSize); 1109 1110 MPI_Status write_header_status; 1111 char mpi_tag[MAX_FIELDS_NAME_LENGTH]; 1112 char version[MAX_FIELDS_NAME_LENGTH/4]; 1113 char mhsize[MAX_FIELDS_NAME_LENGTH/4]; 1114 int magic_number = ENDIAN_TEST_NUMBER; 1115 1116 if ( PhastaIOActiveFiles[i]->local_myrank == 0 ) 1117 { 1118 bzero((void*)mpi_tag,MAX_FIELDS_NAME_LENGTH); 1119 sprintf(mpi_tag, "MPI_IO_Tag : "); 1120 memcpy(PhastaIOActiveFiles[i]->master_header, 1121 mpi_tag, 1122 MAX_FIELDS_NAME_LENGTH); 1123 1124 bzero((void*)version,MAX_FIELDS_NAME_LENGTH/4); 1125 // this version is "1", print version in ASCII 1126 sprintf(version, "version : %d",1); 1127 memcpy(PhastaIOActiveFiles[i]->master_header + MAX_FIELDS_NAME_LENGTH/2, 1128 version, 1129 MAX_FIELDS_NAME_LENGTH/4); 1130 1131 // master header size is computed using the formula above 1132 bzero((void*)mhsize,MAX_FIELDS_NAME_LENGTH/4); 1133 sprintf(mhsize, "mhsize : "); 1134 memcpy(PhastaIOActiveFiles[i]->master_header + MAX_FIELDS_NAME_LENGTH/4*3, 1135 mhsize, 1136 MAX_FIELDS_NAME_LENGTH/4); 1137 1138 bzero((void*)mpi_tag,MAX_FIELDS_NAME_LENGTH); 1139 sprintf(mpi_tag, 1140 "\nnFields : %d\n", 1141 PhastaIOActiveFiles[i]->nFields); 1142 memcpy(PhastaIOActiveFiles[i]->master_header+MAX_FIELDS_NAME_LENGTH, 1143 mpi_tag, 1144 MAX_FIELDS_NAME_LENGTH); 1145 1146 bzero((void*)mpi_tag,MAX_FIELDS_NAME_LENGTH); 1147 sprintf(mpi_tag, "\nnPPF : %d\n", PhastaIOActiveFiles[i]->nPPF); 1148 memcpy( PhastaIOActiveFiles[i]->master_header+ 1149 PhastaIOActiveFiles[i]->nFields * 1150 MAX_FIELDS_NAME_LENGTH + 1151 MAX_FIELDS_NAME_LENGTH * 2, 1152 mpi_tag, 1153 MAX_FIELDS_NAME_LENGTH); 1154 1155 memcpy( PhastaIOActiveFiles[i]->master_header+sizeof("MPI_IO_Tag : ")-1, //-1 sizeof returns the size of the string+1 for "\0" 1156 &magic_number, 1157 sizeof(int)); 1158 1159 memcpy( PhastaIOActiveFiles[i]->master_header+sizeof("mhsize : ") -1 + MAX_FIELDS_NAME_LENGTH/4*3, 1160 &MasterHeaderSize, 1161 sizeof(int)); 1162 } 1163 1164 int j = 0; 1165 unsigned long **header_table; 1166 header_table = ( unsigned long ** )calloc(PhastaIOActiveFiles[i]->nFields, sizeof(unsigned long *)); 1167 1168 for ( j = 0; j < PhastaIOActiveFiles[i]->nFields; j++ ) { 1169 header_table[j]=( unsigned long * ) calloc( PhastaIOActiveFiles[i]->nPPF , sizeof( unsigned long)); 1170 } 1171 1172 //if( irank == 0 ) printf("gonna mpi_gather, myrank = %d\n", irank); 1173 for ( j = 0; j < PhastaIOActiveFiles[i]->nFields; j++ ) { 1174 MPI_Gather( PhastaIOActiveFiles[i]->my_offset_table[j], 1175 PhastaIOActiveFiles[i]->nppp, 1176 MPI_LONG_LONG_INT, 1177 header_table[j], 1178 PhastaIOActiveFiles[i]->nppp, 1179 MPI_LONG_LONG_INT, 1180 0, 1181 PhastaIOActiveFiles[i]->local_comm ); 1182 } 1183 1184 if ( PhastaIOActiveFiles[i]->local_myrank == 0 ) { 1185 1186 //if( irank == 0 ) printf("gonna memcpy for every procs, myrank = %d\n", irank); 1187 for ( j = 0; j < PhastaIOActiveFiles[i]->nFields; j++ ) { 1188 memcpy ( PhastaIOActiveFiles[i]->master_header + 1189 VERSION_INFO_HEADER_SIZE + 1190 j * PhastaIOActiveFiles[i]->nPPF * sizeof(unsigned long), 1191 header_table[j], 1192 PhastaIOActiveFiles[i]->nPPF * sizeof(unsigned long) ); 1193 } 1194 1195 //if( irank == 0 ) printf("gonna file_write_at(), myrank = %d\n", irank); 1196 MPI_File_write_at( PhastaIOActiveFiles[i]->file_handle, 1197 0, 1198 PhastaIOActiveFiles[i]->master_header, 1199 MasterHeaderSize, 1200 MPI_CHAR, 1201 &write_header_status ); 1202 } 1203 1204 ////free(PhastaIOActiveFiles[i]->master_header); 1205 1206 for ( j = 0; j < PhastaIOActiveFiles[i]->nFields; j++ ) { 1207 free ( header_table[j] ); 1208 } 1209 free (header_table); 1210 } 1211 1212 //if( irank == 0 ) printf("gonna file_close(), myrank = %d\n", irank); 1213 double t0 = phiotmrc(); 1214 MPI_File_close( &( PhastaIOActiveFiles[i]->file_handle ) ); 1215 phastaio_addCloseTime(phiotmrc()-t0); 1216 free ( imode ); 1217 } 1218 1219 endTimer(&timer_end); 1220 printPerf("closefile_", timer_start, timer_end, 0, 0, ""); 1221 } 1222 1223 int readHeader( FILE* f, const char phrase[], 1224 int* params, int numParams, const char* iotype) { 1225 isBinary(iotype); 1226 return readHeader(f,phrase,params,numParams); 1227 } 1228 1229 void readheader( 1230 int* fileDescriptor, 1231 const char keyphrase[], 1232 void* valueArray, 1233 int* nItems, 1234 const char datatype[], 1235 const char iotype[] ) 1236 { 1237 double timer_start, timer_end; 1238 1239 startTimer(&timer_start); 1240 1241 int i = *fileDescriptor; 1242 checkFileDescriptor("readheader",&i); 1243 1244 if ( PhastaIONextActiveIndex == 0 ) { 1245 int filePtr = *fileDescriptor - 1; 1246 FILE* fileObject; 1247 int* valueListInt; 1248 1249 if ( *fileDescriptor < 1 || *fileDescriptor > (int)fileArray.size() ) { 1250 fprintf(stderr,"No file associated with Descriptor %d\n",*fileDescriptor); 1251 fprintf(stderr,"openfile_ function has to be called before \n") ; 1252 fprintf(stderr,"acessing the file\n ") ; 1253 fprintf(stderr,"fatal error: cannot continue, returning out of call\n"); 1254 endTimer(&timer_end); 1255 printPerf("readheader", timer_start, timer_end, 0, 0, ""); 1256 return; 1257 } 1258 1259 LastHeaderKey[filePtr] = std::string(keyphrase); 1260 LastHeaderNotFound = false; 1261 1262 fileObject = fileArray[ filePtr ] ; 1263 Wrong_Endian = byte_order[ filePtr ]; 1264 1265 isBinary( iotype ); 1266 typeSize( datatype ); //redundant call, just avoid a compiler warning. 1267 1268 // right now we are making the assumption that we will only write integers 1269 // on the header line. 1270 1271 valueListInt = static_cast< int* >( valueArray ); 1272 int ierr = readHeader( fileObject , 1273 keyphrase, 1274 valueListInt, 1275 *nItems ) ; 1276 1277 byte_order[ filePtr ] = Wrong_Endian ; 1278 1279 if ( ierr ) LastHeaderNotFound = true; 1280 1281 //return ; // don't return, go to the end to print perf 1282 } 1283 else { 1284 int* valueListInt; 1285 valueListInt = static_cast <int*>(valueArray); 1286 char* token = NULL; 1287 bool FOUND = false ; 1288 isBinary( iotype ); 1289 1290 MPI_Status read_offset_status; 1291 char read_out_tag[MAX_FIELDS_NAME_LENGTH]; 1292 memset(read_out_tag, '\0', MAX_FIELDS_NAME_LENGTH); 1293 char readouttag[MAX_FIELDS_NUMBER][MAX_FIELDS_NAME_LENGTH]; 1294 int j; 1295 1296 int string_length = strlen( keyphrase ); 1297 char* buffer = (char*) malloc ( string_length+1 ); 1298 1299 strcpy ( buffer, keyphrase ); 1300 buffer[ string_length ] = '\0'; 1301 1302 char* st2 = strtok ( buffer, "@" ); 1303 st2 = strtok (NULL, "@"); 1304 PhastaIOActiveFiles[i]->GPid = atoi(st2); 1305 if ( char* p = strpbrk(buffer, "@") ) 1306 *p = '\0'; 1307 1308 // Check if the user has input the right GPid 1309 if ( ( PhastaIOActiveFiles[i]->GPid <= 1310 PhastaIOActiveFiles[i]->myrank * 1311 PhastaIOActiveFiles[i]->nppp )|| 1312 ( PhastaIOActiveFiles[i]->GPid > 1313 ( PhastaIOActiveFiles[i]->myrank + 1 ) * 1314 PhastaIOActiveFiles[i]->nppp ) ) 1315 { 1316 *fileDescriptor = NOT_A_MPI_FILE; 1317 printf("Error readheader: The file is not in syncIO new format, please check! myrank = %d, GPid = %d, nppp = %d, keyphrase = %s\n", PhastaIOActiveFiles[i]->myrank, PhastaIOActiveFiles[i]->GPid, PhastaIOActiveFiles[i]->nppp, keyphrase); 1318 // It is possible atoi could not generate a clear integer from st2 because of additional garbage character in keyphrase 1319 endTimer(&timer_end); 1320 printPerf("readheader", timer_start, timer_end, 0, 0, ""); 1321 return; 1322 } 1323 1324 // Find the field we want ... 1325 //for ( j = 0; j<MAX_FIELDS_NUMBER; j++ ) 1326 for ( j = 0; j<PhastaIOActiveFiles[i]->nFields; j++ ) 1327 { 1328 memcpy( readouttag[j], 1329 PhastaIOActiveFiles[i]->master_header + j*MAX_FIELDS_NAME_LENGTH+MAX_FIELDS_NAME_LENGTH*2+1, 1330 MAX_FIELDS_NAME_LENGTH-1 ); 1331 } 1332 1333 for ( j = 0; j<PhastaIOActiveFiles[i]->nFields; j++ ) 1334 { 1335 token = strtok ( readouttag[j], ":" ); 1336 1337 //if ( cscompare( buffer, token ) ) 1338 if ( cscompare( token , buffer ) && cscompare( buffer, token ) ) 1339 // This double comparison is required for the field "number of nodes" and all the other fields that start with "number of nodes" (i.g. number of nodes in the mesh"). 1340 // Would be safer to rename "number of nodes" by "number of nodes in the part" so that the name are completely unique. But much more work to do that (Nspre, phParAdapt, etc). 1341 // Since the field name are unique in SyncIO (as it includes part ID), this should be safe and there should be no issue with the "?" trailing character. 1342 { 1343 PhastaIOActiveFiles[i]->read_field_count = j; 1344 FOUND = true; 1345 //printf("buffer: %s | token: %s | j: %d\n",buffer,token,j); 1346 break; 1347 } 1348 } 1349 free(buffer); 1350 1351 if (!FOUND) 1352 { 1353 //if(irank==0) printf("Warning readheader: Not found %s \n",keyphrase); //PhastaIOActiveFiles[i]->myrank is certainly initialized here. 1354 if(PhastaIOActiveFiles[i]->myrank == 0) printf("WARNING readheader: Not found %s\n",keyphrase); 1355 endTimer(&timer_end); 1356 printPerf("readheader", timer_start, timer_end, 0, 0, ""); 1357 return; 1358 } 1359 1360 // Find the part we want ... 1361 PhastaIOActiveFiles[i]->read_part_count = PhastaIOActiveFiles[i]->GPid - 1362 PhastaIOActiveFiles[i]->myrank * PhastaIOActiveFiles[i]->nppp - 1; 1363 1364 PhastaIOActiveFiles[i]->my_offset = 1365 PhastaIOActiveFiles[i]->my_read_table[PhastaIOActiveFiles[i]->read_field_count][PhastaIOActiveFiles[i]->read_part_count]; 1366 1367 // printf("****Rank %d offset is %d\n",PhastaIOActiveFiles[i]->myrank,PhastaIOActiveFiles[i]->my_offset); 1368 1369 // Read each datablock header here ... 1370 1371 MPI_File_read_at_all( PhastaIOActiveFiles[i]->file_handle, 1372 PhastaIOActiveFiles[i]->my_offset+1, 1373 read_out_tag, 1374 MAX_FIELDS_NAME_LENGTH-1, 1375 MPI_CHAR, 1376 &read_offset_status ); 1377 token = strtok ( read_out_tag, ":" ); 1378 1379 // printf("&&&&Rank %d read_out_tag is %s\n",PhastaIOActiveFiles[i]->myrank,read_out_tag); 1380 1381 if( cscompare( keyphrase , token ) ) //No need to compare also token with keyphrase like above. We should already have the right one. Otherwise there is a problem. 1382 { 1383 FOUND = true ; 1384 token = strtok( NULL, " ,;<>" ); 1385 for( j=0; j < *nItems && ( token = strtok( NULL," ,;<>") ); j++ ) 1386 valueListInt[j] = atoi( token ); 1387 1388 if ( j < *nItems ) 1389 { 1390 fprintf( stderr, "Expected # of ints not found for: %s\n", keyphrase ); 1391 } 1392 } 1393 else { 1394 //if(irank==0) 1395 if(PhastaIOActiveFiles[i]->myrank == 0) 1396 // If we enter this if, there is a problem with the name of some fields 1397 { 1398 printf("Error readheader: Unexpected mismatch between keyphrase = %s and token = %s\n",keyphrase,token); 1399 } 1400 } 1401 } 1402 1403 endTimer(&timer_end); 1404 printPerf("readheader", timer_start, timer_end, 0, 0, ""); 1405 1406 } 1407 1408 void readDataBlock( 1409 FILE* fileObject, 1410 void* valueArray, 1411 int nItems, 1412 const char datatype[], 1413 const char iotype[] ) 1414 { 1415 isBinary(iotype); 1416 size_t type_size = typeSize( datatype ); 1417 double t0 = phiotmrc(); 1418 if ( binary_format ) { 1419 char junk = '\0'; 1420 fread( valueArray, type_size, nItems, fileObject ); 1421 fread( &junk, sizeof(char), 1 , fileObject ); 1422 if ( Wrong_Endian ) SwapArrayByteOrder( valueArray, type_size, nItems ); 1423 } else { 1424 char* ts1 = StringStripper( datatype ); 1425 if ( cscompare( "integer", ts1 ) ) { 1426 for( int n=0; n < nItems ; n++ ) 1427 fscanf(fileObject, "%d\n",(int*)((int*)valueArray+n) ); 1428 } else if ( cscompare( "double", ts1 ) ) { 1429 for( int n=0; n < nItems ; n++ ) 1430 fscanf(fileObject, "%lf\n",(double*)((double*)valueArray+n) ); 1431 } 1432 free (ts1); 1433 } 1434 phastaio_addReadTime(phiotmrc()-t0); 1435 phastaio_addReadBytes(nItems*type_size); 1436 } 1437 1438 void readdatablock( 1439 int* fileDescriptor, 1440 const char keyphrase[], 1441 void* valueArray, 1442 int* nItems, 1443 const char datatype[], 1444 const char iotype[] ) 1445 { 1446 //if(irank == 0) printf("entering readdatablock()\n"); 1447 unsigned long data_size = 0; 1448 double timer_start, timer_end; 1449 startTimer(&timer_start); 1450 1451 int i = *fileDescriptor; 1452 checkFileDescriptor("readdatablock",&i); 1453 1454 if ( PhastaIONextActiveIndex == 0 ) { 1455 int filePtr = *fileDescriptor - 1; 1456 FILE* fileObject; 1457 1458 if ( *fileDescriptor < 1 || *fileDescriptor > (int)fileArray.size() ) { 1459 fprintf(stderr,"No file associated with Descriptor %d\n",*fileDescriptor); 1460 fprintf(stderr,"openfile_ function has to be called before\n") ; 1461 fprintf(stderr,"acessing the file\n ") ; 1462 fprintf(stderr,"fatal error: cannot continue, returning out of call\n"); 1463 endTimer(&timer_end); 1464 printPerf("readdatablock", timer_start, timer_end, 0, 0, ""); 1465 return; 1466 } 1467 1468 // error check.. 1469 // since we require that a consistant header always preceed the data block 1470 // let us check to see that it is actually the case. 1471 1472 if ( ! cscompare( LastHeaderKey[ filePtr ].c_str(), keyphrase ) ) { 1473 fprintf(stderr, "Header not consistant with data block\n"); 1474 fprintf(stderr, "Header: %s\n", LastHeaderKey[ filePtr ].c_str() ); 1475 fprintf(stderr, "DataBlock: %s\n ", keyphrase ); 1476 fprintf(stderr, "Please recheck read sequence \n"); 1477 if( Strict_Error ) { 1478 fprintf(stderr, "fatal error: cannot continue, returning out of call\n"); 1479 endTimer(&timer_end); 1480 printPerf("readdatablock", timer_start, timer_end, 0, 0, ""); 1481 return; 1482 } 1483 } 1484 1485 if ( LastHeaderNotFound ) { 1486 endTimer(&timer_end); 1487 printPerf("readdatablock", timer_start, timer_end, 0, 0, ""); 1488 return; 1489 } 1490 fileObject = fileArray[ filePtr ]; 1491 Wrong_Endian = byte_order[ filePtr ]; 1492 LastHeaderKey.erase(filePtr); 1493 readDataBlock(fileObject,valueArray,*nItems,datatype,iotype); 1494 1495 //return; 1496 } 1497 else { 1498 // printf("read data block\n"); 1499 MPI_Status read_data_status; 1500 size_t type_size = typeSize( datatype ); 1501 int nUnits = *nItems; 1502 isBinary( iotype ); 1503 1504 // read datablock then 1505 //MR CHANGE 1506 // if ( cscompare ( datatype, "double")) 1507 char* ts2 = StringStripper( datatype ); 1508 if ( cscompare ( "double" , ts2)) 1509 //MR CHANGE END 1510 { 1511 1512 double t0 = phiotmrc(); 1513 MPI_File_read_at_all_begin( PhastaIOActiveFiles[i]->file_handle, 1514 PhastaIOActiveFiles[i]->my_offset + DB_HEADER_SIZE, 1515 valueArray, 1516 nUnits, 1517 MPI_DOUBLE ); 1518 MPI_File_read_at_all_end( PhastaIOActiveFiles[i]->file_handle, 1519 valueArray, 1520 &read_data_status ); 1521 data_size=8*nUnits; 1522 phastaio_addReadTime(phiotmrc()-t0); 1523 phastaio_addReadBytes(nUnits*sizeof(double)); 1524 } 1525 //MR CHANGE 1526 // else if ( cscompare ( datatype, "integer")) 1527 else if ( cscompare ( "integer" , ts2)) 1528 //MR CHANGE END 1529 { 1530 double t0 = phiotmrc(); 1531 MPI_File_read_at_all_begin(PhastaIOActiveFiles[i]->file_handle, 1532 PhastaIOActiveFiles[i]->my_offset + DB_HEADER_SIZE, 1533 valueArray, 1534 nUnits, 1535 MPI_INT ); 1536 MPI_File_read_at_all_end( PhastaIOActiveFiles[i]->file_handle, 1537 valueArray, 1538 &read_data_status ); 1539 data_size=4*nUnits; 1540 phastaio_addReadTime(phiotmrc()-t0); 1541 phastaio_addReadBytes(nUnits*sizeof(int)); 1542 } 1543 else 1544 { 1545 *fileDescriptor = DATA_TYPE_ILLEGAL; 1546 printf("readdatablock - DATA_TYPE_ILLEGAL - %s\n",datatype); 1547 endTimer(&timer_end); 1548 printPerf("readdatablock", timer_start, timer_end, 0, 0, ""); 1549 return; 1550 } 1551 free(ts2); 1552 1553 1554 // printf("%d Read finishe\n",PhastaIOActiveFiles[i]->myrank); 1555 1556 // Swap data byte order if endianess is different ... 1557 if ( PhastaIOActiveFiles[i]->Wrong_Endian ) 1558 { 1559 SwapArrayByteOrder( valueArray, type_size, nUnits ); 1560 } 1561 } 1562 1563 endTimer(&timer_end); 1564 char extra_msg[1024]; 1565 memset(extra_msg, '\0', 1024); 1566 char* key = StringStripper(keyphrase); 1567 sprintf(extra_msg, " field is %s ", key); 1568 printPerf("readdatablock", timer_start, timer_end, data_size, 1, extra_msg); 1569 free(key); 1570 1571 } 1572 1573 void writeHeader( 1574 FILE* f, 1575 const char keyphrase[], 1576 const void* valueArray, 1577 const int nItems, 1578 const int ndataItems, 1579 const char datatype[], 1580 const char iotype[]) 1581 { 1582 isBinary( iotype ); 1583 1584 const int _newline = 1585 ( ndataItems > 0 ) ? sizeof( char ) : 0; 1586 int size_of_nextblock = 1587 ( binary_format ) ? typeSize(datatype) * ndataItems + _newline : ndataItems; 1588 1589 fprintf( f, "%s : < %d > ", keyphrase, size_of_nextblock ); 1590 for( int i = 0; i < nItems; i++ ) 1591 fprintf( f, "%d ", *((int*)((int*)valueArray+i))); 1592 fprintf( f, "\n"); 1593 } 1594 1595 void writeheader( 1596 const int* fileDescriptor, 1597 const char keyphrase[], 1598 const void* valueArray, 1599 const int* nItems, 1600 const int* ndataItems, 1601 const char datatype[], 1602 const char iotype[]) 1603 { 1604 1605 //if(irank == 0) printf("entering writeheader()\n"); 1606 1607 double timer_start, timer_end; 1608 startTimer(&timer_start); 1609 1610 int i = *fileDescriptor; 1611 checkFileDescriptor("writeheader",&i); 1612 1613 if ( PhastaIONextActiveIndex == 0 ) { 1614 int filePtr = *fileDescriptor - 1; 1615 if ( *fileDescriptor < 1 || *fileDescriptor > (int)fileArray.size() ) { 1616 fprintf(stderr,"No file associated with Descriptor %d\n",*fileDescriptor); 1617 fprintf(stderr,"openfile_ function has to be called before \n") ; 1618 fprintf(stderr,"acessing the file\n ") ; 1619 fprintf(stderr,"fatal error: cannot continue, returning out of call\n"); 1620 endTimer(&timer_end); 1621 printPerf("writeheader", timer_start, timer_end, 0, 0, ""); 1622 return; 1623 } 1624 1625 LastHeaderKey[filePtr] = std::string(keyphrase); 1626 DataSize = *ndataItems; 1627 FILE* fileObject = fileArray[ filePtr ] ; 1628 header_type[ filePtr ] = typeSize( datatype ); 1629 writeHeader(fileObject,keyphrase,valueArray,*nItems, 1630 *ndataItems,datatype,iotype); 1631 } 1632 else { // else it's parallel I/O 1633 DataSize = *ndataItems; 1634 size_t type_size = typeSize( datatype ); 1635 isBinary( iotype ); 1636 char mpi_tag[MAX_FIELDS_NAME_LENGTH]; 1637 1638 int string_length = strlen( keyphrase ); 1639 char* buffer = (char*) malloc ( string_length+1 ); 1640 1641 strcpy ( buffer, keyphrase); 1642 buffer[ string_length ] = '\0'; 1643 1644 char* st2 = strtok ( buffer, "@" ); 1645 st2 = strtok (NULL, "@"); 1646 PhastaIOActiveFiles[i]->GPid = atoi(st2); 1647 1648 if ( char* p = strpbrk(buffer, "@") ) 1649 *p = '\0'; 1650 1651 bzero((void*)mpi_tag,MAX_FIELDS_NAME_LENGTH); 1652 sprintf(mpi_tag, "\n%s : %d\n", buffer, PhastaIOActiveFiles[i]->field_count); 1653 unsigned long offset_value; 1654 1655 int temp = *ndataItems; 1656 unsigned long number_of_items = (unsigned long)temp; 1657 MPI_Barrier(PhastaIOActiveFiles[i]->local_comm); 1658 1659 MPI_Scan( &number_of_items, 1660 &offset_value, 1661 1, 1662 MPI_LONG_LONG_INT, 1663 MPI_SUM, 1664 PhastaIOActiveFiles[i]->local_comm ); 1665 1666 offset_value = (offset_value - number_of_items) * type_size; 1667 1668 offset_value += PhastaIOActiveFiles[i]->local_myrank * 1669 DB_HEADER_SIZE + 1670 PhastaIOActiveFiles[i]->next_start_address; 1671 // This offset is the starting address of each datablock header... 1672 PhastaIOActiveFiles[i]->my_offset = offset_value; 1673 1674 // Write in my offset table ... 1675 PhastaIOActiveFiles[i]->my_offset_table[PhastaIOActiveFiles[i]->field_count][PhastaIOActiveFiles[i]->part_count] = 1676 PhastaIOActiveFiles[i]->my_offset; 1677 1678 // Update the next-start-address ... 1679 PhastaIOActiveFiles[i]->next_start_address = offset_value + 1680 number_of_items * type_size + 1681 DB_HEADER_SIZE; 1682 MPI_Bcast( &(PhastaIOActiveFiles[i]->next_start_address), 1683 1, 1684 MPI_LONG_LONG_INT, 1685 PhastaIOActiveFiles[i]->local_numprocs-1, 1686 PhastaIOActiveFiles[i]->local_comm ); 1687 1688 // Prepare datablock header ... 1689 int _newline = (*ndataItems>0)?sizeof(char):0; 1690 unsigned int size_of_nextblock = type_size * (*ndataItems) + _newline; 1691 1692 //char datablock_header[255]; 1693 //bzero((void*)datablock_header,255); 1694 char datablock_header[DB_HEADER_SIZE]; 1695 bzero((void*)datablock_header,DB_HEADER_SIZE); 1696 1697 PhastaIOActiveFiles[i]->GPid = PhastaIOActiveFiles[i]->nppp*PhastaIOActiveFiles[i]->myrank+PhastaIOActiveFiles[i]->part_count; 1698 sprintf( datablock_header, 1699 "\n%s : < %u >", 1700 keyphrase, 1701 size_of_nextblock ); 1702 1703 for ( int j = 0; j < *nItems; j++ ) 1704 { 1705 sprintf( datablock_header, 1706 "%s %d ", 1707 datablock_header, 1708 *((int*)((int*)valueArray+j))); 1709 } 1710 sprintf( datablock_header, 1711 "%s\n ", 1712 datablock_header ); 1713 1714 // Write datablock header ... 1715 //MR CHANGE 1716 // if ( cscompare(datatype,"double") ) 1717 char* ts1 = StringStripper( datatype ); 1718 if ( cscompare("double",ts1) ) 1719 //MR CHANGE END 1720 { 1721 free ( PhastaIOActiveFiles[i]->double_chunk ); 1722 PhastaIOActiveFiles[i]->double_chunk = ( double * )malloc( (sizeof( double )*number_of_items+ DB_HEADER_SIZE)); 1723 1724 double * aa = ( double * )datablock_header; 1725 memcpy(PhastaIOActiveFiles[i]->double_chunk, aa, DB_HEADER_SIZE); 1726 } 1727 //MR CHANGE 1728 // if ( cscompare(datatype,"integer") ) 1729 else if ( cscompare("integer",ts1) ) 1730 //MR CHANGE END 1731 { 1732 free ( PhastaIOActiveFiles[i]->int_chunk ); 1733 PhastaIOActiveFiles[i]->int_chunk = ( int * )malloc( (sizeof( int )*number_of_items+ DB_HEADER_SIZE)); 1734 1735 int * aa = ( int * )datablock_header; 1736 memcpy(PhastaIOActiveFiles[i]->int_chunk, aa, DB_HEADER_SIZE); 1737 } 1738 else { 1739 // *fileDescriptor = DATA_TYPE_ILLEGAL; 1740 printf("writeheader - DATA_TYPE_ILLEGAL - %s\n",datatype); 1741 endTimer(&timer_end); 1742 printPerf("writeheader", timer_start, timer_end, 0, 0, ""); 1743 return; 1744 } 1745 free(ts1); 1746 1747 PhastaIOActiveFiles[i]->part_count++; 1748 if ( PhastaIOActiveFiles[i]->part_count == PhastaIOActiveFiles[i]->nppp ) { 1749 //A new field will be written 1750 if ( PhastaIOActiveFiles[i]->local_myrank == 0 ) { 1751 memcpy( PhastaIOActiveFiles[i]->master_header + 1752 PhastaIOActiveFiles[i]->field_count * 1753 MAX_FIELDS_NAME_LENGTH + 1754 MAX_FIELDS_NAME_LENGTH * 2, 1755 mpi_tag, 1756 MAX_FIELDS_NAME_LENGTH-1); 1757 } 1758 PhastaIOActiveFiles[i]->field_count++; 1759 PhastaIOActiveFiles[i]->part_count=0; 1760 } 1761 free(buffer); 1762 } 1763 1764 endTimer(&timer_end); 1765 printPerf("writeheader", timer_start, timer_end, 0, 0, ""); 1766 } 1767 1768 void writeDataBlock( 1769 FILE* f, 1770 const void* valueArray, 1771 const int nItems, 1772 const char datatype[], 1773 const char iotype[] ) 1774 { 1775 isBinary( iotype ); 1776 size_t type_size = typeSize( datatype ); 1777 double t0 = phiotmrc(); 1778 if ( binary_format ) { 1779 fwrite( valueArray, type_size, nItems, f ); 1780 fprintf( f,"\n"); 1781 } else { 1782 char* ts1 = StringStripper( datatype ); 1783 if ( cscompare( "integer", ts1 ) ) { 1784 const int* vals = (int*) valueArray; 1785 for( int n=0; n < nItems ; n++ ) 1786 fprintf(f,"%d\n",vals[n]); 1787 } else if ( cscompare( "double", ts1 ) ) { 1788 const double* vals = (double*) valueArray; 1789 for( int n=0; n < nItems ; n++ ) 1790 fprintf(f,"%f\n",vals[n]); 1791 } 1792 free (ts1); 1793 } 1794 phastaio_addWriteTime(phiotmrc()-t0); 1795 phastaio_addWriteBytes(nItems*type_size); 1796 } 1797 1798 void writedatablock( 1799 const int* fileDescriptor, 1800 const char keyphrase[], 1801 const void* valueArray, 1802 const int* nItems, 1803 const char datatype[], 1804 const char iotype[] ) 1805 { 1806 //if(irank == 0) printf("entering writedatablock()\n"); 1807 1808 unsigned long data_size = 0; 1809 double timer_start, timer_end; 1810 startTimer(&timer_start); 1811 1812 int i = *fileDescriptor; 1813 checkFileDescriptor("writedatablock",&i); 1814 1815 if ( PhastaIONextActiveIndex == 0 ) { 1816 int filePtr = *fileDescriptor - 1; 1817 1818 if ( *fileDescriptor < 1 || *fileDescriptor > (int)fileArray.size() ) { 1819 fprintf(stderr,"No file associated with Descriptor %d\n",*fileDescriptor); 1820 fprintf(stderr,"openfile_ function has to be called before \n") ; 1821 fprintf(stderr,"acessing the file\n ") ; 1822 fprintf(stderr,"fatal error: cannot continue, returning out of call\n"); 1823 endTimer(&timer_end); 1824 printPerf("writedatablock", timer_start, timer_end, 0, 0, ""); 1825 return; 1826 } 1827 // since we require that a consistant header always preceed the data block 1828 // let us check to see that it is actually the case. 1829 1830 if ( ! cscompare( LastHeaderKey[ filePtr ].c_str(), keyphrase ) ) { 1831 fprintf(stderr, "Header not consistant with data block\n"); 1832 fprintf(stderr, "Header: %s\n", LastHeaderKey[ filePtr ].c_str() ); 1833 fprintf(stderr, "DataBlock: %s\n ", keyphrase ); 1834 fprintf(stderr, "Please recheck write sequence \n"); 1835 if( Strict_Error ) { 1836 fprintf(stderr, "fatal error: cannot continue, returning out of call\n"); 1837 endTimer(&timer_end); 1838 printPerf("writedatablock", timer_start, timer_end, 0, 0, ""); 1839 return; 1840 } 1841 } 1842 1843 FILE* fileObject = fileArray[ filePtr ] ; 1844 size_t type_size=typeSize( datatype ); 1845 isBinary( iotype ); 1846 1847 LastHeaderKey.erase(filePtr); 1848 1849 if ( header_type[filePtr] != (int)type_size ) { 1850 fprintf(stderr,"header and datablock differ on typeof data in the block for\n"); 1851 fprintf(stderr,"keyphrase : %s\n", keyphrase); 1852 if( Strict_Error ) { 1853 fprintf(stderr,"fatal error: cannot continue, returning out of call\n" ); 1854 endTimer(&timer_end); 1855 printPerf("writedatablock", timer_start, timer_end, 0, 0, ""); 1856 return; 1857 } 1858 } 1859 1860 int nUnits = *nItems; 1861 1862 if ( nUnits != DataSize ) { 1863 fprintf(stderr,"header and datablock differ on number of data items for\n"); 1864 fprintf(stderr,"keyphrase : %s\n", keyphrase); 1865 if( Strict_Error ) { 1866 fprintf(stderr,"fatal error: cannot continue, returning out of call\n" ); 1867 endTimer(&timer_end); 1868 printPerf("writedatablock", timer_start, timer_end, 0, 0, ""); 1869 return; 1870 } 1871 } 1872 writeDataBlock(fileObject,valueArray,*nItems,datatype,iotype); 1873 } 1874 else { // syncIO case 1875 MPI_Status write_data_status; 1876 isBinary( iotype ); 1877 int nUnits = *nItems; 1878 1879 //MR CHANGE 1880 // if ( cscompare(datatype,"double") ) 1881 char* ts1 = StringStripper( datatype ); 1882 if ( cscompare("double",ts1) ) 1883 //MR CHANGE END 1884 { 1885 memcpy((PhastaIOActiveFiles[i]->double_chunk+DB_HEADER_SIZE/sizeof(double)), valueArray, nUnits*sizeof(double)); 1886 double t0 = phiotmrc(); 1887 MPI_File_write_at_all_begin( PhastaIOActiveFiles[i]->file_handle, 1888 PhastaIOActiveFiles[i]->my_offset, 1889 PhastaIOActiveFiles[i]->double_chunk, 1890 //BLOCK_SIZE/sizeof(double), 1891 nUnits+DB_HEADER_SIZE/sizeof(double), 1892 MPI_DOUBLE ); 1893 MPI_File_write_at_all_end( PhastaIOActiveFiles[i]->file_handle, 1894 PhastaIOActiveFiles[i]->double_chunk, 1895 &write_data_status ); 1896 data_size=8*nUnits; 1897 phastaio_addWriteTime(phiotmrc()-t0); 1898 phastaio_addWriteBytes((nUnits*sizeof(double))+DB_HEADER_SIZE); 1899 } 1900 //MR CHANGE 1901 // else if ( cscompare ( datatype, "integer")) 1902 else if ( cscompare("integer",ts1) ) 1903 //MR CHANGE END 1904 { 1905 memcpy((PhastaIOActiveFiles[i]->int_chunk+DB_HEADER_SIZE/sizeof(int)), valueArray, nUnits*sizeof(int)); 1906 double t0 = phiotmrc(); 1907 MPI_File_write_at_all_begin( PhastaIOActiveFiles[i]->file_handle, 1908 PhastaIOActiveFiles[i]->my_offset, 1909 PhastaIOActiveFiles[i]->int_chunk, 1910 nUnits+DB_HEADER_SIZE/sizeof(int), 1911 MPI_INT ); 1912 MPI_File_write_at_all_end( PhastaIOActiveFiles[i]->file_handle, 1913 PhastaIOActiveFiles[i]->int_chunk, 1914 &write_data_status ); 1915 data_size=4*nUnits; 1916 phastaio_addWriteTime(phiotmrc()-t0); 1917 phastaio_addWriteBytes((nUnits*sizeof(int))+DB_HEADER_SIZE); 1918 } 1919 else { 1920 printf("Error: writedatablock - DATA_TYPE_ILLEGAL - %s\n",datatype); 1921 endTimer(&timer_end); 1922 printPerf("writedatablock", timer_start, timer_end, 0, 0, ""); 1923 return; 1924 } 1925 free(ts1); 1926 } 1927 1928 endTimer(&timer_end); 1929 char extra_msg[1024]; 1930 memset(extra_msg, '\0', 1024); 1931 char* key = StringStripper(keyphrase); 1932 sprintf(extra_msg, " field is %s ", key); 1933 printPerf("writedatablock", timer_start, timer_end, data_size, 1, extra_msg); 1934 free(key); 1935 1936 } 1937 1938 void SwapArrayByteOrder( void* array, int nbytes, int nItems ) 1939 { 1940 /* This swaps the byte order for the array of nItems each 1941 of size nbytes , This will be called only locally */ 1942 int i,j; 1943 unsigned char* ucDst = (unsigned char*)array; 1944 for(i=0; i < nItems; i++) { 1945 for(j=0; j < (nbytes/2); j++) 1946 std::swap( ucDst[j] , ucDst[(nbytes - 1) - j] ); 1947 ucDst += nbytes; 1948 } 1949 } 1950 1951 void writestring( int* fileDescriptor, const char inString[] ) 1952 { 1953 int filePtr = *fileDescriptor - 1; 1954 FILE* fileObject = fileArray[filePtr] ; 1955 fprintf(fileObject,"%s",inString ); 1956 return; 1957 } 1958 1959 void Gather_Headers( int* fileDescriptor, vector< string >& headers ) 1960 { 1961 FILE* fileObject; 1962 char Line[1024]; 1963 1964 fileObject = fileArray[ (*fileDescriptor)-1 ]; 1965 1966 while( !feof(fileObject) ) { 1967 fgets( Line, 1024, fileObject); 1968 if ( Line[0] == '#' ) { 1969 headers.push_back( Line ); 1970 } else { 1971 break; 1972 } 1973 } 1974 rewind( fileObject ); 1975 clearerr( fileObject ); 1976 } 1977 1978 void isWrong( void ) { 1979 (Wrong_Endian) ? fprintf(stdout,"YES\n") : fprintf(stdout,"NO\n"); 1980 } 1981 1982 void togglestrictmode( void ) { Strict_Error = !Strict_Error; } 1983 1984 int isLittleEndian( void ) 1985 { 1986 // this function returns a 1 if the current running architecture is 1987 // LittleEndian Byte Ordered, else it returns a zero 1988 union { 1989 long a; 1990 char c[sizeof( long )]; 1991 } endianUnion; 1992 endianUnion.a = 1 ; 1993 if ( endianUnion.c[sizeof(long)-1] != 1 ) return 1 ; 1994 else return 0; 1995 } 1996 1997 namespace PHASTA { 1998 const char* const PhastaIO_traits<int>::type_string = "integer"; 1999 const char* const PhastaIO_traits<double>::type_string = "double"; 2000 } 2001