MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
InfoOut_mpiFileBuffer Class Reference

Customized buffer to facilitate MPI I/O usage for a single file for all domains within an MPI communicator. More...

#include <infoout.h>

Inheritance diagram for InfoOut_mpiFileBuffer:
[legend]
Collaboration diagram for InfoOut_mpiFileBuffer:
[legend]

Public Member Functions

 InfoOut_mpiFileBuffer ()
 Generic constructor is used when no information is provided during declaration. More...
 
 InfoOut_mpiFileBuffer (const MString &filename, const MString &projectName, MPI_Comm mpiComm=MPI_COMM_WORLD)
 This constructor yields a new instance that can immediately be used to write messages to an MPI file. More...
 
 ~InfoOut_mpiFileBuffer ()
 Destructor calls close() to close the MPI file (if opened) and deletes the MPI write buffer. More...
 
void open (const MString &filename, const MString &projectName, MPI_Comm mpiComm=MPI_COMM_WORLD)
 Initialization of the MPI I/O environment. More...
 
void close (MBool forceClose=false)
 Closes the MPI file. More...
 
MInt setMinFlushSize (MInt minFlushSize)
 Sets the minimum buffer length that has to be reached before the buffer is flushed. More...
 
- Public Member Functions inherited from InfoOut_buffer
 InfoOut_buffer ()
 Generic constructor is used when no information is provided during declaration. More...
 
virtual MBool setRootOnly (MBool rootOnly=true)
 Sets interal state of whether only the root domain (rank 0) should write to file. More...
 
virtual MInt setMinFlushSize (MInt minFlushSize)
 Sets the minimum buffer length that has to be reached before the buffer is flushed. More...
 

Protected Member Functions

virtual MInt sync ()
 Flushes the buffer if flushing conditions are met. More...
 
virtual void flushBuffer ()
 Flushes the buffer by writing the contents to the MPI file. More...
 
- Protected Member Functions inherited from InfoOut_buffer
virtual MString encodeXml (const std::string &str)
 Parses the string input and returns the string with XML entities escaped. More...
 
virtual MString getXmlHeader ()
 Return an XML header that should written at the beginning of each log file. More...
 
virtual MString getXmlFooter ()
 Return an XML footer that should written at the end of each log file. More...
 
virtual void createPrefixMessage ()
 Creates an XML prefix using the domain id that is prepended to each message. More...
 
virtual void createSuffixMessage ()
 Creates an XML suffix that is appended to each message. More...
 
virtual void flushBuffer ()=0
 

Private Member Functions

MInt setMpiWriteBuffer (MInt newBufferSize)
 Delete the current MPI write buffer and allocate a new one. More...
 

Private Attributes

MInt m_maxMessageLength
 Maximum message length (excluding formatting) More...
 
MInt m_mpiWriteBufferSize
 Size of the MPI write buffer. More...
 
MCharm_mpiWriteBuffer
 MPI write buffer. More...
 
MBool m_isOpen
 Stores whether the MPI file was already opened. More...
 
MString m_filename
 Filename on disk. More...
 
MPI_Comm m_mpiComm
 MPI communicator group. More...
 
MPI_File m_mpiFileHandle
 MPI file handle. More...
 
MPI_Request m_mpiRequest
 MPI request object (nonblocking I/O) More...
 

Static Private Attributes

static const MInt m_maxStringLength = 8192
 Maximum string length (including formatting, default: 4096) More...
 

Additional Inherited Members

- Protected Attributes inherited from InfoOut_buffer
MBool m_rootOnly
 Stores whether only the root domain writes a log file. More...
 
MInt m_domainId
 Contains the MPI rank (= domain id) of this process. More...
 
MInt m_noDomains
 Contains the MPI rank count (= number of domains) More...
 
MInt m_minFlushSize
 Minimum length of the internal buffer before flushing. More...
 
MString m_prefixMessage
 Stores the prefix that is prepended to each output. More...
 
MString m_suffixMessage
 Stores the suffix that is apended to each output. More...
 
std::ostringstream m_tmpBuffer
 Temporary buffer to hold string until flushing. More...
 
MString m_projectName
 Name of the current Project. More...
 
std::vector< std::pair< MString, MString > > m_prefixAttributes
 
- Static Protected Attributes inherited from InfoOut_buffer
static const MInt m_fileFormatVersion = 1
 

Detailed Description

Author
Michael Schlottke
Date
June 2012

This class can be used as a regular string buffer, as it inherits from stringbuf. On flushing the buffer, the contents of the buffer are written to a file using MPI I/O. The entire MPI communication is hidden from the user, so that the underlying algorithms can be changed/optimized without affecting current implementations.

Internally, an XML file is created to store all messages with each processor's MPI rank so that each message can be attributed to the origin. The XML format ensures that fast and easy-to-develop post processing tools may be used (e.g. extractdomainlog.py). Additionally, meta information about the total number of domains as well as the creation/closing date of the file is saved.

Definition at line 114 of file infoout.h.

Constructor & Destructor Documentation

◆ InfoOut_mpiFileBuffer() [1/2]

InfoOut_mpiFileBuffer::InfoOut_mpiFileBuffer ( )
Author
Michael Schlottke
Date
June 2012

Definition at line 504 of file infoout.cpp.

508 m_isOpen(false),
509 m_filename(),
510 m_mpiComm(),
512 m_mpiRequest(MPI_REQUEST_NULL) {
513 // Nothing here
514}
MChar * m_mpiWriteBuffer
MPI write buffer.
Definition: infoout.h:119
MBool m_isOpen
Stores whether the MPI file was already opened.
Definition: infoout.h:120
MInt m_mpiWriteBufferSize
Size of the MPI write buffer.
Definition: infoout.h:118
MPI_Request m_mpiRequest
MPI request object (nonblocking I/O)
Definition: infoout.h:124
MInt m_maxMessageLength
Maximum message length (excluding formatting)
Definition: infoout.h:117
MString m_filename
Filename on disk.
Definition: infoout.h:121
MPI_File m_mpiFileHandle
MPI file handle.
Definition: infoout.h:123
MPI_Comm m_mpiComm
MPI communicator group.
Definition: infoout.h:122

◆ InfoOut_mpiFileBuffer() [2/2]

InfoOut_mpiFileBuffer::InfoOut_mpiFileBuffer ( const MString filename,
const MString projectName,
MPI_Comm  mpiComm = MPI_COMM_WORLD 
)
Author
Michael Schlottke
Date
April 2012

Internally, this constructor just passes the parameters to open() (see open() for more details).

Parameters
[in]filenameFilename that should be used for the MPI file.
[in]mpiCommMPI communicator for which the file should be opened.
[in]m_projectNameProjectname given.

Definition at line 526 of file infoout.cpp.

530 m_isOpen(false),
531 m_filename(),
532 m_mpiComm(),
534 m_mpiRequest(MPI_REQUEST_NULL) {
535 open(filename, projectName, mpiComm);
536}
void open(const MString &filename, const MString &projectName, MPI_Comm mpiComm=MPI_COMM_WORLD)
Initialization of the MPI I/O environment.
Definition: infoout.cpp:566

◆ ~InfoOut_mpiFileBuffer()

InfoOut_mpiFileBuffer::~InfoOut_mpiFileBuffer ( )
Author
Michael Schlottke
Date
April 2012

The MPI write buffer m_mpiWriteBuffer is deleted as well, since it could be that the buffer is allocated using setMinFlushSize() but never opened with open() (and thus not deleted within close()).

Definition at line 545 of file infoout.cpp.

545 {
546 // Close the file
547 close();
548
549 // Delete write buffer
550 delete[] m_mpiWriteBuffer;
551}
void close(MBool forceClose=false)
Closes the MPI file.
Definition: infoout.cpp:629

Member Function Documentation

◆ close()

void InfoOut_mpiFileBuffer::close ( MBool  forceClose = false)
Author
Michael Schlottke
Date
April 2012

Any subsequent write statements to the MPI file stream are discarded after this method is called. NOTE: If the MPI file is not closed using this function before MPI_Finalize() is called, an MPI error occurs!

     After close() is called, the MPI root process first writes an XML footer to the file. Then the file is

closed on all ranks.

Definition at line 629 of file infoout.cpp.

629 {
630 // Only perform finalization if this instance was initialized before
631 if(m_isOpen) {
632 // Only perform cleanup if forceClose is not set to true
633 if(!forceClose) {
634 // Force flushing of the internal buffer
635 flushBuffer();
636
637 // Call MPI_Wait to make sure everything was written to disk
638 MPI_Wait(&m_mpiRequest, MPI_STATUS_IGNORE, AT_);
639
640 // Make sure that all processes have finished writing, so that the footer can be written before the file is closed
642
643 // Write root information to log file (only on MPI root)
644 if(m_domainId == 0) {
645 // Copy buffer string to MPI buffer
646 MInt mpiStringLength = getXmlFooter().copy(m_mpiWriteBuffer, m_mpiWriteBufferSize);
647
648 // Write to MPI file
649 MPI_File_write_shared(m_mpiFileHandle, m_mpiWriteBuffer, mpiStringLength, MPI_CHAR, MPI_STATUS_IGNORE, AT_);
650 }
651
652 // Close MPI file
654 }
655
656 // Delete MPI write buffer
657 delete[] m_mpiWriteBuffer;
658
659 // Set pointer to null to avoid problems when the destructor calls delete again
661
662 // Reset state variable
663 m_isOpen = false;
664 }
665}
MInt m_domainId
Contains the MPI rank (= domain id) of this process.
Definition: infoout.h:47
virtual MString getXmlFooter()
Return an XML footer that should written at the end of each log file.
Definition: infoout.cpp:299
virtual void flushBuffer()
Flushes the buffer by writing the contents to the MPI file.
Definition: infoout.cpp:714
int32_t MInt
Definition: maiatypes.h:62
int MPI_Barrier(MPI_Comm comm, const MString &name)
same as MPI_Barrier
int MPI_Wait(MPI_Request *request, MPI_Status *status, const MString &name)
same as MPI_Wait
int MPI_File_close(MPI_File *mpi_fh, const MString &name)
same as MPI_File_close
int MPI_File_write_shared(MPI_File mpi_fh, const void *buf, int count, MPI_Datatype datatype, MPI_Status *status, const MString &name)
same as MPI_File_write_shared

◆ flushBuffer()

void InfoOut_mpiFileBuffer::flushBuffer ( )
inlineprotectedvirtual
Author
Michael Schlottke
Date
June 2012

This method flushes the buffer (i.e. copy the buffer to the MPI write buffer, issue the MPI commands etc.) if the file is open, and if this processor is supposed to write to the file. It ignores any settings for the minimum flush size, and assumes that all string formatting was already performed.

Implements InfoOut_buffer.

Definition at line 714 of file infoout.cpp.

714 {
715 // Only write to MPI if the MPI file was already opened, and only if we're supposed to on this domain
716 if(m_isOpen && !(m_rootOnly && m_domainId != 0)) {
717 // Before copying the new string into the write buffer, make sure that the previous MPI write has finished
718 MPI_Wait(&m_mpiRequest, MPI_STATUS_IGNORE, AT_);
719
720 // Retrieve actual string length while copying the string from the temporary buffer to the write buffer.
721 // The copy command is invoked with the current buffer size to ensure that there is no buffer overflow.
722 MInt mpiStringLength = m_tmpBuffer.str().copy(m_mpiWriteBuffer, m_mpiWriteBufferSize);
723
724 // Reset temporary buffer
725 m_tmpBuffer.str("");
726
727 // Write mpiStringLength characters to file using nonblocking MPI I/O
728 MPI_File_iwrite_shared(m_mpiFileHandle, m_mpiWriteBuffer, mpiStringLength, MPI_CHAR, &m_mpiRequest, AT_);
729 }
730}
std::ostringstream m_tmpBuffer
Temporary buffer to hold string until flushing.
Definition: infoout.h:52
MBool m_rootOnly
Stores whether only the root domain writes a log file.
Definition: infoout.h:46
int MPI_File_iwrite_shared(MPI_File mpi_fh, const void *buf, int count, MPI_Datatype datatype, MPI_Request *request, const MString &name)
same as MPI_File_iwrite_shared

◆ open()

void InfoOut_mpiFileBuffer::open ( const MString filename,
const MString projectName,
MPI_Comm  mpiComm = MPI_COMM_WORLD 
)
Author
Michael Schlottke
Date
April 2012

After a successful call to this method the MPI file stream is ready to use. Any previous information written to the buffer is lost when open is called. This function creates a new file as specified in #filename (deleting any existing files with the same name) and creates the XML prefixes and suffixes used for each message. The root process also writes the necessary XML header information to the file.

Parameters
[in]filenameName of the file to open.
[in]mpiCommMPI communicator for which to open the file.
[in]projectNameProjectname given.

Definition at line 566 of file infoout.cpp.

566 {
567 // Open file only if it was not yet done
568 if(!m_isOpen) {
569 // Set MPI communicator group
570 m_mpiComm = mpiComm;
571
572 // Get domain id and number of domains
573 MPI_Comm_rank(m_mpiComm, &m_domainId);
574 MPI_Comm_size(m_mpiComm, &m_noDomains);
575
576 // Set filename
577 m_filename = filename;
578
579 // Set projectName
580 m_projectName = projectName;
581
582 // Delete log file if one exists
583 MPI_File_delete((MChar*)m_filename.c_str(), MPI_INFO_NULL);
584
585 // Set MPI config values
586 MInt amode = MPI_MODE_CREATE | MPI_MODE_WRONLY;
587
588 // Open MPI file
589 MPI_File_open(m_mpiComm, (MChar*)m_filename.c_str(), amode, MPI_INFO_NULL, &m_mpiFileHandle, AT_);
590
591 // Clear internal buffer in order to dismiss any previous input
592 str("");
593
594 // Create prefix and suffix messages and calculate the maximum length for a message
598
599 // Create new write buffer with the following size: length before flushing + max MPI string length
601
602 // Write root and meta information to log file (only on MPI root, i.e. domain id == 0)
603 if(m_domainId == 0) {
604 // Copy buffer string to MPI buffer
605 MInt mpiStringLength = getXmlHeader().copy(m_mpiWriteBuffer, m_mpiWriteBufferSize);
606
607 // Write to MPI file
608 MPI_File_write_shared(m_mpiFileHandle, m_mpiWriteBuffer, mpiStringLength, MPI_CHAR, MPI_STATUS_IGNORE, AT_);
609 }
610
611 // Make sure that initial message is written before file is used
613
614 // Set state variable
615 m_isOpen = true;
616 }
617}
MInt m_minFlushSize
Minimum length of the internal buffer before flushing.
Definition: infoout.h:49
MString m_prefixMessage
Stores the prefix that is prepended to each output.
Definition: infoout.h:50
MString m_suffixMessage
Stores the suffix that is apended to each output.
Definition: infoout.h:51
virtual void createSuffixMessage()
Creates an XML suffix that is appended to each message.
Definition: infoout.cpp:162
virtual MString getXmlHeader()
Return an XML header that should written at the beginning of each log file.
Definition: infoout.cpp:199
virtual void createPrefixMessage()
Creates an XML prefix using the domain id that is prepended to each message.
Definition: infoout.cpp:138
MInt m_noDomains
Contains the MPI rank count (= number of domains)
Definition: infoout.h:48
MString m_projectName
Name of the current Project.
Definition: infoout.h:53
MInt setMpiWriteBuffer(MInt newBufferSize)
Delete the current MPI write buffer and allocate a new one.
Definition: infoout.cpp:765
static const MInt m_maxStringLength
Maximum string length (including formatting, default: 4096)
Definition: infoout.h:116
char MChar
Definition: maiatypes.h:56
int MPI_File_open(MPI_Comm comm, const char *filename, int amode, MPI_Info info, MPI_File *mpi_fh, const MString &name)
same as MPI_File_open

◆ setMinFlushSize()

MInt InfoOut_mpiFileBuffer::setMinFlushSize ( MInt  minFlushSize)
inlinevirtual
Author
Michael Schlottke
Date
June 2012

This calls InfoOut_buffer::setMinFlushSize and then adds some code to change the size of the MPI write buffer m_mpiWriteBuffer along with the minFlushSize.

\params[in] minFlushSize Minimum buffer length.

Returns
The previous value of the minimum flush size.

Reimplemented from InfoOut_buffer.

Definition at line 742 of file infoout.cpp.

742 {
743 // Call base class method for general stuff
744 MInt previousValue = InfoOut_buffer::setMinFlushSize(minFlushSize);
745
746 // Flush current buffer
747 flushBuffer();
748
749 // Create new write buffer with the following size: length before flushing + max MPI string length
751
752 return previousValue;
753}
virtual MInt setMinFlushSize(MInt minFlushSize)
Sets the minimum buffer length that has to be reached before the buffer is flushed.
Definition: infoout.cpp:187

◆ setMpiWriteBuffer()

MInt InfoOut_mpiFileBuffer::setMpiWriteBuffer ( MInt  newBufferSize)
private
Author
Michael Schlottke
Date
June 2012

This method calls MPI_Wait to make sure that all write statements have completed before the buffer is deleted. Then m_mpiWriteBuffer is deleted and afterwards recreated with the new buffer size.

\params[in] newBufferSize The new size of the write buffer

Returns
Previous buffer size

Definition at line 765 of file infoout.cpp.

765 {
766 // Make sure that the write buffer is empty
767 MPI_Wait(&m_mpiRequest, MPI_STATUS_IGNORE, AT_);
768
769 // Delete old write buffer
770 delete[] m_mpiWriteBuffer;
771
772 // Create new write buffer
773 m_mpiWriteBuffer = new MChar[newBufferSize];
774
775 // Save old buffer size to temporary variable and new buffer size to member variable
776 MInt oldBufferSize = m_mpiWriteBufferSize;
777 m_mpiWriteBufferSize = newBufferSize;
778
779 // Return the previous buffer size
780 return oldBufferSize;
781}

◆ sync()

MInt InfoOut_mpiFileBuffer::sync ( )
protectedvirtual
Author
Michael Schlottke
Date
June 2012

Sync is called automatically when an "endl" is sent to the stream. At first the buffer content is wrapped in the prefix and suffix messages, then the entire string is written to the MPI file using nonblocking communication by calling flushBuffer(). Finally the internal buffers are reset.

Returns
Zero by default.

Definition at line 677 of file infoout.cpp.

677 {
678 // Only write to MPI if the MPI file was already opened, and only if we're supposed to on this domain
679 if(m_isOpen && !(m_rootOnly && m_domainId != 0)) {
680 // Escape XML entities in buffer
681 str(encodeXml(str()));
682
683 // Create formatted string and write to temporary buffer
684 if(str().length() > (unsigned)m_maxMessageLength) {
685 // If buffer content + prefix/suffix message is too long for m_mpiWriteBuffer, use substr and ensure a newline at
686 // the end. In substr the '-1' is for the newline character.
687 m_tmpBuffer << m_prefixMessage << str().substr(0, m_maxMessageLength - 1) << "\n" << m_suffixMessage;
688 } else {
689 // Otherwise just copy the whole string
691 }
692
693 // Only write to MPI file if current buffer length exceeds the minimum size for flushing
694 if(m_tmpBuffer.str().length() >= (unsigned)m_minFlushSize) {
695 flushBuffer();
696 }
697 }
698
699 // Reset internal buffer
700 str("");
701
702 // Default return value for sync()
703 return 0;
704}
virtual MString encodeXml(const std::string &str)
Parses the string input and returns the string with XML entities escaped.
Definition: infoout.cpp:95

Member Data Documentation

◆ m_filename

MString InfoOut_mpiFileBuffer::m_filename
private

Definition at line 121 of file infoout.h.

◆ m_isOpen

MBool InfoOut_mpiFileBuffer::m_isOpen
private

Definition at line 120 of file infoout.h.

◆ m_maxMessageLength

MInt InfoOut_mpiFileBuffer::m_maxMessageLength
private

Definition at line 117 of file infoout.h.

◆ m_maxStringLength

const MInt InfoOut_mpiFileBuffer::m_maxStringLength = 8192
staticprivate

Definition at line 116 of file infoout.h.

◆ m_mpiComm

MPI_Comm InfoOut_mpiFileBuffer::m_mpiComm
private

Definition at line 122 of file infoout.h.

◆ m_mpiFileHandle

MPI_File InfoOut_mpiFileBuffer::m_mpiFileHandle
private

Definition at line 123 of file infoout.h.

◆ m_mpiRequest

MPI_Request InfoOut_mpiFileBuffer::m_mpiRequest
private

Definition at line 124 of file infoout.h.

◆ m_mpiWriteBuffer

MChar* InfoOut_mpiFileBuffer::m_mpiWriteBuffer
private

Definition at line 119 of file infoout.h.

◆ m_mpiWriteBufferSize

MInt InfoOut_mpiFileBuffer::m_mpiWriteBufferSize
private

Definition at line 118 of file infoout.h.


The documentation for this class was generated from the following files: