16 #include <deal.II/base/exceptions.h> 17 #include <deal.II/base/mpi.h> 18 #include <deal.II/base/signaling_nan.h> 19 #include <deal.II/base/thread_management.h> 20 #include <deal.II/base/timer.h> 21 #include <deal.II/base/utilities.h> 30 #include <type_traits> 32 #ifdef DEAL_II_HAVE_SYS_RESOURCE_H 33 # include <sys/resource.h> 42 DEAL_II_NAMESPACE_OPEN
46 namespace TimerImplementation
55 struct is_duration : std::false_type
61 template <
typename Rep,
typename Period>
62 struct is_duration<
std::chrono::duration<Rep, Period>> : std::true_type
72 from_seconds(
const double time)
74 static_assert(is_duration<T>::value,
75 "The template type should be a duration type.");
76 return T(std::lround(T::period::den * (time / T::period::num)));
83 template <
typename Rep,
typename Period>
85 to_seconds(
const std::chrono::duration<Rep, Period> duration)
87 return Period::num * double(duration.count()) / Period::den;
96 data.
sum = numbers::signaling_nan<double>();
97 data.
min = numbers::signaling_nan<double>();
98 data.
max = numbers::signaling_nan<double>();
99 data.
avg = numbers::signaling_nan<double>();
112 double system_cpu_duration = 0.0;
114 FILETIME cpuTime, sysTime, createTime, exitTime;
115 const auto succeeded = GetProcessTimes(
116 GetCurrentProcess(), &createTime, &exitTime, &sysTime, &cpuTime);
119 system_cpu_duration =
120 (double)(((
unsigned long long)cpuTime.dwHighDateTime << 32) |
121 cpuTime.dwLowDateTime) /
125 #elif defined(DEAL_II_HAVE_SYS_RESOURCE_H) 127 getrusage(RUSAGE_SELF, &usage);
128 system_cpu_duration = usage.ru_utime.tv_sec + 1.e-6 * usage.ru_utime.tv_usec;
130 DEAL_II_WARNING(
"Unsupported platform. Porting not finished.")
133 internal::TimerImplementation::from_seconds<duration>(system_cpu_duration));
138 template <
typename clock_type_>
147 template <
typename clock_type_>
151 current_lap_start_time = clock_type::now();
152 accumulated_time = duration_type::zero();
153 last_lap_time = duration_type::zero();
159 :
Timer(MPI_COMM_SELF, false)
166 , mpi_communicator(mpi_communicator)
167 , sync_lap_times(sync_lap_times_)
179 #ifdef DEAL_II_WITH_MPI 211 internal::TimerImplementation::from_seconds<decltype(
214 internal::TimerImplementation::from_seconds<decltype(
217 internal::TimerImplementation::to_seconds(
229 return internal::TimerImplementation::to_seconds(
cpu_times.accumulated_time);
239 const double running_time = internal::TimerImplementation::to_seconds(
257 return internal::TimerImplementation::to_seconds(
cpu_times.last_lap_time);
281 wall_clock_type::duration current_elapsed_wall_time;
283 current_elapsed_wall_time = wall_clock_type::now() -
289 return internal::TimerImplementation::to_seconds(current_elapsed_wall_time);
319 : output_frequency(output_frequency)
320 , output_type(output_type)
321 , out_stream(stream, true)
322 , output_is_enabled(true)
323 , mpi_communicator(MPI_COMM_SELF)
331 : output_frequency(output_frequency)
332 , output_type(output_type)
334 , output_is_enabled(true)
335 , mpi_communicator(MPI_COMM_SELF)
341 std::ostream & stream,
344 : output_frequency(output_frequency)
345 , output_type(output_type)
346 , out_stream(stream, true)
347 , output_is_enabled(true)
348 , mpi_communicator(mpi_communicator)
357 : output_frequency(output_frequency)
358 , output_type(output_type)
360 , output_is_enabled(true)
361 , mpi_communicator(mpi_communicator)
368 auto do_exit = [
this]() {
385 #ifdef DEAL_II_WITH_MPI 388 std::cerr <<
"---------------------------------------------------------" 390 <<
"TimerOutput objects finalize timed values printed to the" 392 <<
"screen by communicating over MPI in their destructors." 394 <<
"Since an exception is currently uncaught, this" << std::endl
395 <<
"synchronization (and subsequent output) will be skipped to" 397 <<
"avoid a possible deadlock." << std::endl
398 <<
"---------------------------------------------------------" 415 std::lock_guard<std::mutex> lock(
mutex);
417 Assert(section_name.empty() ==
false,
ExcMessage(
"Section string is empty."));
422 ExcMessage(std::string(
"Cannot enter the already active section <") +
423 section_name +
">."));
440 sections[section_name].total_cpu_time = 0;
441 sections[section_name].total_wall_time = 0;
445 sections[section_name].timer.reset();
446 sections[section_name].timer.start();
458 ExcMessage(
"Cannot exit any section because none has been entered!"));
460 std::lock_guard<std::mutex> lock(
mutex);
462 if (!section_name.empty())
465 ExcMessage(
"Cannot delete a section that was never created."));
469 ExcMessage(
"Cannot delete a section that has not been entered."));
474 const std::string actual_section_name =
477 sections[actual_section_name].timer.stop();
478 sections[actual_section_name].total_wall_time +=
479 sections[actual_section_name].timer.last_wall_time();
485 const double cpu_time =
sections[actual_section_name].timer.last_cpu_time();
486 sections[actual_section_name].total_cpu_time += cpu_time;
493 std::string output_time;
494 std::ostringstream cpu;
495 cpu << cpu_time <<
"s";
496 std::ostringstream wall;
497 wall <<
sections[actual_section_name].timer.last_wall_time() <<
"s";
499 output_time =
", CPU time: " + cpu.str();
501 output_time =
", wall time: " + wall.str() +
".";
504 ", CPU/wall time: " + cpu.str() +
" / " + wall.str() +
".";
506 out_stream << actual_section_name << output_time << std::endl;
513 actual_section_name));
518 std::map<std::string, double>
521 std::map<std::string, double> output;
522 for (
const auto §ion :
sections)
526 case TimerOutput::OutputData::total_cpu_time:
527 output[section.first] = section.second.total_cpu_time;
529 case TimerOutput::OutputData::total_wall_time:
530 output[section.first] = section.second.total_wall_time;
532 case TimerOutput::OutputData::n_calls:
533 output[section.first] = section.second.n_calls;
554 unsigned int max_width = 0;
557 std::max(max_width, static_cast<unsigned int>(i.first.length()));
560 max_width = std::max(max_width + 1, static_cast<unsigned int>(32));
561 const std::string extra_dash = std::string(max_width - 32,
'-');
562 const std::string extra_space = std::string(max_width - 32,
' ');
575 double check_time = 0.;
577 check_time += i.second.total_cpu_time;
585 <<
"+---------------------------------------------" 586 << extra_dash <<
"+------------" 587 <<
"+------------+\n" 588 <<
"| Total CPU time elapsed since start " 589 << extra_space <<
"|";
590 out_stream << std::setw(10) << std::setprecision(3) << std::right;
593 << extra_space <<
"| " 600 <<
" | % of total |\n";
601 out_stream <<
"+---------------------------------" << extra_dash
602 <<
"+-----------+------------" 606 std::string name_out = i.first;
609 unsigned int pos_non_space = name_out.find_first_not_of(
' ');
610 name_out.erase(0, pos_non_space);
611 name_out.resize(max_width,
' ');
619 out_stream << i.second.total_cpu_time <<
"s |";
626 const double fraction =
628 if (fraction > 0.001)
642 <<
"+---------------------------------" << extra_dash
644 <<
"------------+------------+\n" 650 <<
"Note: The sum of counted times is " << time_gap
651 <<
" seconds larger than the total time.\n" 652 <<
"(Timer function may have introduced too much overhead, or different\n" 653 <<
"section timers may have run at the same time.)" << std::endl;
663 <<
"+---------------------------------------------" 664 << extra_dash <<
"+------------" 665 <<
"+------------+\n" 666 <<
"| Total wallclock time elapsed since start " 667 << extra_space <<
"|";
668 out_stream << std::setw(10) << std::setprecision(3) << std::right;
671 << extra_space <<
"| " 678 out_stream <<
"+---------------------------------" << extra_dash
679 <<
"+-----------+------------" 683 std::string name_out = i.first;
686 unsigned int pos_non_space = name_out.find_first_not_of(
' ');
687 name_out.erase(0, pos_non_space);
688 name_out.resize(max_width,
' ');
696 out_stream << i.second.total_wall_time <<
"s |";
704 const double fraction =
706 if (fraction > 0.001)
720 <<
"+---------------------------------" << extra_dash
722 <<
"------------+------------+\n" 735 double check_time = 0.;
738 check_time += i.second.total_cpu_time;
745 out_stream <<
"\n\n+---------------------------------------------" 747 <<
"------------+------------+" 748 <<
"------------+------------+" 750 <<
"| Total CPU/wall time elapsed since start " 751 << extra_space <<
"|" << std::setw(10) << std::setprecision(3)
755 << extra_space <<
"|" 758 <<
"\n| Section " << extra_space
760 <<
" CPU time | % of total |" 761 <<
" wall time | % of total |" 762 <<
"\n+---------------------------------" << extra_dash
764 <<
"------------+------------+" 765 <<
"------------+------------+" << std::endl;
769 std::string name_out = i.first;
772 unsigned int pos_non_space = name_out.find_first_not_of(
' ');
773 name_out.erase(0, pos_non_space);
774 name_out.resize(max_width,
' ');
784 out_stream << i.second.total_cpu_time <<
"s |";
791 const double fraction =
793 if (fraction > 0.001)
811 out_stream << i.second.total_wall_time <<
"s |";
819 const double fraction =
821 if (fraction > 0.001)
837 out_stream <<
"+---------------------------------" << extra_dash
839 <<
"------------+------------+" 840 <<
"------------+------------+" << std::endl
846 <<
"Note: The sum of counted times is " << time_gap
847 <<
" seconds larger than the total time.\n" 848 <<
"(Timer function may have introduced too much overhead, or different\n" 849 <<
"section timers may have run at the same time.)" << std::endl;
877 std::lock_guard<std::mutex> lock(
mutex);
894 DEAL_II_NAMESPACE_CLOSE
void print_summary() const
static const unsigned int invalid_unsigned_int
double last_wall_time() const
double get_lap_time() const
MPI_Comm mpi_communicator
MPI_Comm mpi_communicator
static time_point now() noexcept
Utilities::MPI::MinMaxAvg last_lap_wall_time_data
static ::ExceptionBase & ExcMessage(std::string arg1)
T sum(const T &t, const MPI_Comm &mpi_communicator)
#define Assert(cond, exc)
double operator()() const
duration_type accumulated_time
typename clock_type::duration duration_type
ClockMeasurements< wall_clock_type > wall_times
duration_type last_lap_time
std::list< std::string > active_sections
void leave_subsection(const std::string §ion_name="")
std::map< std::string, double > get_summary_data(const OutputData kind) const
#define AssertThrowMPI(error_code)
double last_cpu_time() const
TimerOutput(std::ostream &stream, const OutputFrequency output_frequency, const OutputType output_type)
std::map< std::string, Section > sections
ConditionalOStream out_stream
std::ostream & get_stream() const
std::chrono::time_point< CPUClock, duration > time_point
static ::ExceptionBase & ExcNotImplemented()
void enter_subsection(const std::string §ion_name)
MinMaxAvg min_max_avg(const double my_value, const MPI_Comm &mpi_communicator)
OutputFrequency output_frequency
time_point_type current_lap_start_time
Utilities::MPI::MinMaxAvg accumulated_wall_time_data
ClockMeasurements< cpu_clock_type > cpu_times