|
Sierra Toolkit
Version of the Day
|
00001 /* ------------------------------------------------------------------ */ 00002 /* Copyright 2000 Sandia Corporation, Albuquerque, NM. */ 00003 /* ------------------------------------------------------------------ */ 00004 00005 #ifndef STK_UTIL_PARALLEL_mpi_filebuf_hpp 00006 #define STK_UTIL_PARALLEL_mpi_filebuf_hpp 00007 00008 #include <ios> 00009 #include <iostream> 00010 #include <cstdio> 00011 #include <mpi.h> 00012 00013 //: Specialize the ANSI Standard C++ streambuf class 00014 //: for a parallel file buffer. The actual file is 00015 //: only touched by the root processor. 00016 // 00017 // READ MODE: The file is read on the root processor and 00018 // broadcast one buffer at a time to the remaining processors. 00019 // 00020 // WRITE MODE: Each processor has a buffer that is locally 00021 // filled. When the buffer is full on the root processor the 00022 // buffer is written to the output file. When the buffer is 00023 // full on any other processor the size of the buffer is doubled. 00024 // The 'mpi_filebuf::flush' method gathers all buffers on the 00025 // root processor and writes the buffers to the output file. 00026 // 00027 // GLOBAL: Calls to the 'open', 'flush', 'close', destructor, 00028 // and 'underflow' methods are global; these calls must be 00029 // made on all processors. The 'underflow' method is called 00030 // by the 'istream' that uses the 'mpi_filebuf' object when 00031 // ever the input buffer is empty. Thus reading from an 'istream' 00032 // that uses an 'mpi_filebuf' must be globally consistent. 00033 00034 class mpi_filebuf : public std::streambuf { 00035 public: 00036 00037 //: Construct an MPI-parallel input/output file buffer 00038 mpi_filebuf(); 00039 00040 //: GLOBAL: Open a file. 00041 // The file name is only significant on the root processsor. 00042 // May only be opened as ios::in, ios::out, ios:app. 00043 mpi_filebuf * open( 00044 MPI_Comm communicator , /* All processors */ 00045 const int root_processor , /* All processors */ 00046 const std::ios_base::openmode file_mode , /* All processors */ 00047 const char * const file_name = NULL ); /* Root processor */ 00048 00049 //: GLOBAL: Close the file. 00050 // If output mode then flush the output. 00051 mpi_filebuf * close(); 00052 00053 //: GLOBAL: Flush the buffered output to the file. 00054 // Sends all buffers to the root processor, 00055 // write to the file, and flushes the file. 00056 mpi_filebuf * flush(); 00057 00058 //: GLOBAL: Destructor 00059 // Close and then reclaim memory. 00060 virtual ~mpi_filebuf(); 00061 00062 //: Query if open, a local operations 00063 int is_open() const ; 00064 00065 //: When the file buffer is in the 'closed' state set the buffer length, 00066 // The input argument must be consistent on all processors; however, 00067 // this condition is not checked until the next 'open' operation. 00068 mpi_filebuf * set_buffer_length( const size_t buffer_length ); 00069 00070 //: Query the current buffer 00071 void get_buffer( const char * & , size_t & ) const ; 00072 00073 //: Query wall-clock time spent communicating. 00074 double wtime() const ; 00075 00076 protected: 00077 00078 //: Called to refill the input buffer 00079 virtual int underflow(); 00080 00081 //: Called when output buffer is filled 00082 virtual int overflow( int c = EOF ); 00083 00084 //: Sync is a no-op 00085 virtual int sync(); 00086 00087 //: Setbuf is a no-op 00088 virtual std::streambuf * setbuf( char * s , std::streamsize n ); 00089 00090 private: 00091 00092 mpi_filebuf( const mpi_filebuf & ); // Not allowed 00093 mpi_filebuf & operator = ( const mpi_filebuf & ); // Not allowed 00094 00095 MPI_Comm comm ; // Communicator 00096 int comm_root ; // Rank of root processor 00097 std::FILE * comm_root_fp ; // Root processor's file 00098 int comm_output ; // Output file 00099 char * comm_buffer ; // local buffer 00100 size_t comm_buffer_len ; // length of buffer 00101 double comm_time ; // wall-time spent communicating 00102 }; 00103 00104 /*--------------------------------------------------------------------*/ 00105 00106 inline int mpi_filebuf::is_open() const { return NULL != comm_buffer ; } 00107 00108 /* The SUN has the 'streambuf::pptr()' as a non-const method, 00109 which violates the ISO/ANSI standard specification. 00110 Therefore, must cast away the const. */ 00111 00112 inline void mpi_filebuf::get_buffer( const char * & b , size_t & n ) const 00113 { b = comm_buffer ; n = ((mpi_filebuf*)this)->pptr() - comm_buffer ; } 00114 00115 inline double mpi_filebuf::wtime() const { return comm_time ; } 00116 00117 #endif // STK_UTIL_PARALLEL_mpi_filebuf_hpp