Files
mfem/general/tic_toc.cpp
T
2020-03-09 15:36:41 -07:00

461 lines
11 KiB
C++

// Copyright (c) 2010-2020, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.
#include "tic_toc.hpp"
#if (MFEM_TIMER_TYPE == 0)
#include <ctime>
#elif (MFEM_TIMER_TYPE == 1)
#include <sys/times.h>
#include <climits>
#include <unistd.h>
#elif (MFEM_TIMER_TYPE == 2)
#include <time.h>
#if (!defined(CLOCK_MONOTONIC) || !defined(CLOCK_PROCESS_CPUTIME_ID))
#error "CLOCK_MONOTONIC and CLOCK_PROCESS_CPUTIME_ID not defined in <time.h>"
#endif
#elif (MFEM_TIMER_TYPE == 3)
#define NOMINMAX
#include <windows.h>
#undef NOMINMAX
#elif (MFEM_TIMER_TYPE == 4)
#include <ctime>
#include <mach/mach_time.h>
#elif (MFEM_TIMER_TYPE == 5)
#include <sys/time.h> // gettimeofday
#elif (MFEM_TIMER_TYPE == 6)
#include <mpi.h> // MPI_Wtime()
#else
#error "Unknown MFEM_TIMER_TYPE"
#endif
namespace mfem
{
namespace internal
{
class StopWatch
{
private:
#if (MFEM_TIMER_TYPE == 0)
std::clock_t user_time, start_utime;
#elif (MFEM_TIMER_TYPE == 1)
clock_t real_time, user_time, syst_time;
clock_t start_rtime, start_utime, start_stime;
long my_CLK_TCK;
inline void Current(clock_t *, clock_t *, clock_t *);
#elif (MFEM_TIMER_TYPE == 2)
struct timespec real_time, user_time;
struct timespec start_rtime, start_utime;
inline void GetRealTime(struct timespec &tp);
inline void GetUserTime(struct timespec &tp);
#elif (MFEM_TIMER_TYPE == 3)
LARGE_INTEGER frequency, real_time, start_rtime;
#elif (MFEM_TIMER_TYPE == 4)
std::clock_t user_time, start_utime;
mach_timebase_info_data_t ratio;
uint64_t real_time, start_rtime;
#elif (MFEM_TIMER_TYPE == 5)
struct timeval real_time, start_rtime;
#elif (MFEM_TIMER_TYPE == 6)
double real_time, start_rtime;
#endif
short Running;
public:
StopWatch();
inline void Clear();
inline void Start();
inline void Stop();
inline double Resolution();
inline double RealTime();
inline double UserTime();
inline double SystTime();
};
StopWatch::StopWatch()
{
#if (MFEM_TIMER_TYPE == 0)
user_time = 0;
#elif (MFEM_TIMER_TYPE == 1)
my_CLK_TCK = sysconf(_SC_CLK_TCK);
real_time = user_time = syst_time = 0;
#elif (MFEM_TIMER_TYPE == 2)
real_time.tv_sec = user_time.tv_sec = 0;
real_time.tv_nsec = user_time.tv_nsec = 0;
#elif (MFEM_TIMER_TYPE == 3)
QueryPerformanceFrequency(&frequency);
real_time.QuadPart = 0;
#elif (MFEM_TIMER_TYPE == 4)
user_time = 0;
real_time = 0;
mach_timebase_info(&ratio);
#elif (MFEM_TIMER_TYPE == 5)
real_time.tv_sec = 0;
real_time.tv_usec = 0;
#elif (MFEM_TIMER_TYPE == 6)
real_time = 0.0;
#endif
Running = 0;
}
#if (MFEM_TIMER_TYPE == 1)
inline void StopWatch::Current(clock_t *r, clock_t *u, clock_t *s)
{
struct tms my_tms;
*r = times(&my_tms);
*u = my_tms.tms_utime;
*s = my_tms.tms_stime;
}
#elif (MFEM_TIMER_TYPE == 2)
inline void StopWatch::GetRealTime(struct timespec &tp)
{
clock_gettime(CLOCK_MONOTONIC, &tp);
}
inline void StopWatch::GetUserTime(struct timespec &tp)
{
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp);
}
#endif
inline void StopWatch::Clear()
{
#if (MFEM_TIMER_TYPE == 0)
user_time = 0;
if (Running)
{
start_utime = std::clock();
}
#elif (MFEM_TIMER_TYPE == 1)
real_time = user_time = syst_time = 0;
if (Running)
{
Current(&start_rtime, &start_utime, &start_stime);
}
#elif (MFEM_TIMER_TYPE == 2)
real_time.tv_sec = user_time.tv_sec = 0;
real_time.tv_nsec = user_time.tv_nsec = 0;
if (Running)
{
GetRealTime(start_rtime);
GetUserTime(start_utime);
}
#elif (MFEM_TIMER_TYPE == 3)
real_time.QuadPart = 0;
if (Running)
{
QueryPerformanceCounter(&start_rtime);
}
#elif (MFEM_TIMER_TYPE == 4)
user_time = 0;
real_time = 0;
if (Running)
{
start_utime = std::clock();
start_rtime = mach_absolute_time();
}
#elif (MFEM_TIMER_TYPE == 5)
real_time.tv_sec = 0;
real_time.tv_usec = 0;
if (Running)
{
gettimeofday(&start_rtime, NULL);
}
#elif (MFEM_TIMER_TYPE == 6)
real_time = 0.0;
if (Running)
{
start_rtime = MPI_Wtime();
}
#endif
}
inline void StopWatch::Start()
{
if (Running) { return; }
#if (MFEM_TIMER_TYPE == 0)
start_utime = std::clock();
#elif (MFEM_TIMER_TYPE == 1)
Current(&start_rtime, &start_utime, &start_stime);
#elif (MFEM_TIMER_TYPE == 2)
GetRealTime(start_rtime);
GetUserTime(start_utime);
#elif (MFEM_TIMER_TYPE == 3)
QueryPerformanceCounter(&start_rtime);
#elif (MFEM_TIMER_TYPE == 4)
start_utime = std::clock();
start_rtime = mach_absolute_time();
#elif (MFEM_TIMER_TYPE == 5)
gettimeofday(&start_rtime, NULL);
#elif (MFEM_TIMER_TYPE == 6)
start_rtime = MPI_Wtime();
#endif
Running = 1;
}
inline void StopWatch::Stop()
{
if (!Running) { return; }
#if (MFEM_TIMER_TYPE == 0)
user_time += ( std::clock() - start_utime );
#elif (MFEM_TIMER_TYPE == 1)
clock_t curr_rtime, curr_utime, curr_stime;
Current(&curr_rtime, &curr_utime, &curr_stime);
real_time += ( curr_rtime - start_rtime );
user_time += ( curr_utime - start_utime );
syst_time += ( curr_stime - start_stime );
#elif (MFEM_TIMER_TYPE == 2)
struct timespec curr_rtime, curr_utime;
GetRealTime(curr_rtime);
GetUserTime(curr_utime);
real_time.tv_sec += ( curr_rtime.tv_sec - start_rtime.tv_sec );
real_time.tv_nsec += ( curr_rtime.tv_nsec - start_rtime.tv_nsec );
user_time.tv_sec += ( curr_utime.tv_sec - start_utime.tv_sec );
user_time.tv_nsec += ( curr_utime.tv_nsec - start_utime.tv_nsec );
#elif (MFEM_TIMER_TYPE == 3)
LARGE_INTEGER curr_rtime;
QueryPerformanceCounter(&curr_rtime);
real_time.QuadPart += (curr_rtime.QuadPart - start_rtime.QuadPart);
#elif (MFEM_TIMER_TYPE == 4)
user_time += ( std::clock() - start_utime );
real_time += (mach_absolute_time() - start_rtime);
#elif (MFEM_TIMER_TYPE == 5)
struct timeval curr_rtime;
gettimeofday(&curr_rtime, NULL);
real_time.tv_sec += ( curr_rtime.tv_sec - start_rtime.tv_sec );
real_time.tv_usec += ( curr_rtime.tv_usec - start_rtime.tv_usec );
#elif (MFEM_TIMER_TYPE == 6)
real_time += (MPI_Wtime() - start_rtime);
#endif
Running = 0;
}
inline double StopWatch::Resolution()
{
#if (MFEM_TIMER_TYPE == 0)
return 1.0 / CLOCKS_PER_SEC; // potential resolution
#elif (MFEM_TIMER_TYPE == 1)
return 1.0 / my_CLK_TCK;
#elif (MFEM_TIMER_TYPE == 2)
// return the resolution of the "real time" clock, CLOCK_MONOTONIC, which may
// be different from the resolution of the "user time" clock,
// CLOCK_PROCESS_CPUTIME_ID.
struct timespec res;
clock_getres(CLOCK_MONOTONIC, &res);
return res.tv_sec + 1e-9*res.tv_nsec;
#elif (MFEM_TIMER_TYPE == 3)
return 1.0 / frequency.QuadPart;
#elif (MFEM_TIMER_TYPE == 4)
return 1.0 / CLOCKS_PER_SEC; // potential resolution
// return 1e-9; // not real resolution
#elif (MFEM_TIMER_TYPE == 5)
return 1e-6; // not real resolution
#elif (MFEM_TIMER_TYPE == 6)
return MPI_Wtick();
#endif
}
inline double StopWatch::RealTime()
{
#if (MFEM_TIMER_TYPE == 0)
return UserTime();
#elif (MFEM_TIMER_TYPE == 1)
clock_t curr_rtime, curr_utime, curr_stime;
clock_t rtime = real_time;
if (Running)
{
Current(&curr_rtime, &curr_utime, &curr_stime);
rtime += (curr_rtime - start_rtime);
}
return (double)(rtime) / my_CLK_TCK;
#elif (MFEM_TIMER_TYPE == 2)
if (Running)
{
struct timespec curr_rtime;
GetRealTime(curr_rtime);
return ((real_time.tv_sec + (curr_rtime.tv_sec - start_rtime.tv_sec)) +
1e-9*(real_time.tv_nsec +
(curr_rtime.tv_nsec - start_rtime.tv_nsec)));
}
else
{
return real_time.tv_sec + 1e-9*real_time.tv_nsec;
}
#elif (MFEM_TIMER_TYPE == 3)
LARGE_INTEGER curr_rtime, rtime = real_time;
if (Running)
{
QueryPerformanceCounter(&curr_rtime);
rtime.QuadPart += (curr_rtime.QuadPart - start_rtime.QuadPart);
}
return (double)(rtime.QuadPart) / frequency.QuadPart;
#elif (MFEM_TIMER_TYPE == 4)
uint64_t rtime = real_time;
if (Running)
{
rtime += (mach_absolute_time() - start_rtime);
}
return 1e-9*rtime*ratio.numer/ratio.denom;
#elif (MFEM_TIMER_TYPE == 5)
if (Running)
{
struct timeval curr_rtime;
gettimeofday(&curr_rtime, NULL);
real_time.tv_sec += ( curr_rtime.tv_sec - start_rtime.tv_sec );
real_time.tv_usec += ( curr_rtime.tv_usec - start_rtime.tv_usec );
return ((real_time.tv_sec + (curr_rtime.tv_sec - start_rtime.tv_sec)) +
1e-6*(real_time.tv_usec +
(curr_rtime.tv_usec - start_rtime.tv_usec)));
}
else
{
return real_time.tv_sec + 1e-6*real_time.tv_usec;
}
#elif (MFEM_TIMER_TYPE == 6)
double rtime = real_time;
if (Running)
{
rtime += (MPI_Wtime() - start_rtime);
}
return rtime;
#endif
}
inline double StopWatch::UserTime()
{
#if (MFEM_TIMER_TYPE == 0)
std::clock_t utime = user_time;
if (Running)
{
utime += (std::clock() - start_utime);
}
return (double)(utime) / CLOCKS_PER_SEC;
#elif (MFEM_TIMER_TYPE == 1)
clock_t curr_rtime, curr_utime, curr_stime;
clock_t utime = user_time;
if (Running)
{
Current(&curr_rtime, &curr_utime, &curr_stime);
utime += (curr_utime - start_utime);
}
return (double)(utime) / my_CLK_TCK;
#elif (MFEM_TIMER_TYPE == 2)
if (Running)
{
struct timespec curr_utime;
GetUserTime(curr_utime);
return ((user_time.tv_sec + (curr_utime.tv_sec - start_utime.tv_sec)) +
1e-9*(user_time.tv_nsec +
(curr_utime.tv_nsec - start_utime.tv_nsec)));
}
else
{
return user_time.tv_sec + 1e-9*user_time.tv_nsec;
}
#elif (MFEM_TIMER_TYPE == 3)
return RealTime();
#elif (MFEM_TIMER_TYPE == 4)
std::clock_t utime = user_time;
if (Running)
{
utime += (std::clock() - start_utime);
}
return (double)(utime) / CLOCKS_PER_SEC;
#elif (MFEM_TIMER_TYPE == 5)
return RealTime();
#elif (MFEM_TIMER_TYPE == 6)
return RealTime();
#endif
}
inline double StopWatch::SystTime()
{
#if (MFEM_TIMER_TYPE == 1)
clock_t curr_rtime, curr_utime, curr_stime;
clock_t stime = syst_time;
if (Running)
{
Current(&curr_rtime, &curr_utime, &curr_stime);
stime += (curr_stime - start_stime);
}
return (double)(stime) / my_CLK_TCK;
#else
return 0.0;
#endif
}
} // namespace internal
StopWatch::StopWatch()
{
M = new internal::StopWatch;
}
void StopWatch::Clear()
{
M->Clear();
}
void StopWatch::Start()
{
M->Start();
}
void StopWatch::Stop()
{
M->Stop();
}
double StopWatch::Resolution()
{
return M->Resolution();
}
double StopWatch::RealTime()
{
return M->RealTime();
}
double StopWatch::UserTime()
{
return M->UserTime();
}
double StopWatch::SystTime()
{
return M->SystTime();
}
StopWatch::~StopWatch()
{
delete M;
}
StopWatch tic_toc;
void tic()
{
tic_toc.Clear();
tic_toc.Start();
}
double toc()
{
return tic_toc.UserTime();
}
}