/*========================================================================= Program: Visualization Toolkit Module: vtkParallelTimer.h Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // /** * @class vtkParallelTimer * * * Provides distributed log functionality. When the file is * written each process data is collected by rank 0 who * writes the data to a single file in rank order. * * The log works as an event stack. EventStart pushes the * event identifier and its start time onto the stack. EventEnd * pops the most recent event time and identifier computes the * elapsed time and adds an entry to the log recording the * event, it's start and end times, and its elapsed time. * EndEventSynch includes a barrier before the measurement. * * The log class implements the singleton pattern so that it * may be shared across class boundaries. If the log instance * doesn't exist then one is created. It will be automatically * destroyed at exit by the signleton destructor. It can be * destroyed explicitly by calling DeleteGlobalInstance. */ #ifndef vtkParallelTimer_h #define vtkParallelTimer_h #define vtkParallelTimerDEBUG -1 #include "vtkObject.h" #include "vtkRenderingParallelLICModule.h" // for export #include // for sstream #include // for string #include // for vector #if vtkParallelTimerDEBUG > 0 #include // for cerr #endif class vtkParallelTimerBuffer; class VTKRENDERINGPARALLELLIC_EXPORT vtkParallelTimer : public vtkObject { public: static vtkParallelTimer* New(); vtkTypeMacro(vtkParallelTimer, vtkObject); void PrintSelf(ostream& os, vtkIndent indent) override; ///@{ /** * Type used to direct an output stream into the log's header. The header * is a buffer used only by the root rank. */ class LogHeaderType { public: template LogHeaderType& operator<<(const T& s); }; ///@} ///@{ /** * Type used to direct an output stream into the log's body. The body is a * buffer that all ranks write to. */ class LogBodyType { public: template LogBodyType& operator<<(const T& s); }; ///@} ///@{ /** * Set the rank who writes. */ vtkSetMacro(WriterRank, int); vtkGetMacro(WriterRank, int); ///@} ///@{ /** * Set the filename that is used during write when the object * is used as a singleton. If nothing is set the default is * ROOT_RANKS_PID.log */ vtkSetFilePathMacro(FileName); vtkGetFilePathMacro(FileName); ///@} void SetFileName(VTK_FILEPATH const std::string& fileName) { this->SetFileName(fileName.c_str()); } ///@{ /** * The log works as an event stack. EventStart pushes the * event identifier and its start time onto the stack. EventEnd * pops the most recent event time and identifier computes the * elapsed time and adds an entry to the log recording the * event, it's start and end times, and its elapsed time. * EndEventSynch includes a barrier before the measurement. */ void StartEvent(const char* event); void StartEvent(int rank, const char* event); void EndEvent(const char* event); void EndEvent(int rank, const char* event); void EndEventSynch(const char* event); void EndEventSynch(int rank, const char* event); ///@} /** * Insert text into the log header on the writer rank. */ template vtkParallelTimer& operator<<(const T& s); /** * stream output to the log's header(root rank only). */ vtkParallelTimer::LogHeaderType GetHeader() { return vtkParallelTimer::LogHeaderType(); } /** * stream output to log body(all ranks). */ vtkParallelTimer::LogBodyType GetBody() { return vtkParallelTimer::LogBodyType(); } /** * Clear the log. */ void Clear(); /** * When an object is finished writing data to the log * object it must call Update to send the data to the writer * rank. * This ensures that all data is transferred to the root before * MPI_Finalize is called while allowing the write to occur * after Mpi_finalize. Note: This is a collective call. */ void Update(); /** * Write the log contents to a file. */ int Write(); /** * The log class implements the singleton pattern so that it * may be shared across class boundaries. If the log instance * doesn't exist then one is created. It will be automatically * destroyed at exit by the signleton destructor. It can be * destroyed explicitly by calling DeleteGlobalInstance. */ static vtkParallelTimer* GetGlobalInstance(); /** * Explicitly delete the singleton. */ static void DeleteGlobalInstance(); ///@{ /** * If enabled and used as a singleton the log will write * it's contents to disk during program termination. */ vtkSetMacro(WriteOnClose, int); vtkGetMacro(WriteOnClose, int); ///@} ///@{ /** * Set/Get the global log level. Applications can set this to the * desired level so that all pipeline objects will log data. */ vtkSetMacro(GlobalLevel, int); vtkGetMacro(GlobalLevel, int); ///@} protected: vtkParallelTimer(); virtual ~vtkParallelTimer(); private: vtkParallelTimer(const vtkParallelTimer&) = delete; void operator=(const vtkParallelTimer&) = delete; /** * A class responsible for delete'ing the global instance of the log. */ class VTKRENDERINGPARALLELLIC_EXPORT vtkParallelTimerDestructor { public: vtkParallelTimerDestructor() : Log(0) { } ~vtkParallelTimerDestructor(); void SetLog(vtkParallelTimer* log) { this->Log = log; } private: vtkParallelTimer* Log; }; private: int GlobalLevel; int Initialized; int WorldRank; int WriterRank; char* FileName; int WriteOnClose; std::vector StartTime; #if vtkParallelTimerDEBUG < 0 std::vector EventId; #endif vtkParallelTimerBuffer* Log; static vtkParallelTimer* GlobalInstance; static vtkParallelTimerDestructor GlobalInstanceDestructor; std::ostringstream HeaderBuffer; friend class LogHeaderType; friend class LogBodyType; }; //----------------------------------------------------------------------------- template vtkParallelTimer& vtkParallelTimer::operator<<(const T& s) { if (this->WorldRank == this->WriterRank) { this->HeaderBuffer << s; #if vtkParallelTimerDEBUG > 0 std::cerr << s; #endif } return *this; } //----------------------------------------------------------------------------- template vtkParallelTimer::LogHeaderType& vtkParallelTimer::LogHeaderType::operator<<(const T& s) { vtkParallelTimer* log = vtkParallelTimer::GetGlobalInstance(); if (log->WorldRank == log->WriterRank) { log->HeaderBuffer << s; #if vtkParallelTimerDEBUG > 0 std::cerr << s; #endif } return *this; } //----------------------------------------------------------------------------- template vtkParallelTimer::LogBodyType& vtkParallelTimer::LogBodyType::operator<<(const T& s) { vtkParallelTimer* log = vtkParallelTimer::GetGlobalInstance(); *(log->Log) << s; #if vtkParallelTimerDEBUG > 0 std::cerr << s; #endif return *this; } #endif