check_include_files(unistd.h HAVE_UNISTD_H)
check_include_files(pwd.h HAVE_PWD_H)
check_include_files(dirent.h HAVE_DIRENT_H)
+check_include_files(time.h HAVE_TIME_H)
check_include_files(sys/time.h HAVE_SYS_TIME_H)
check_include_files(io.h HAVE_IO_H)
check_include_files(sched.h HAVE_SCHED_H)
include(CheckLibraryExists)
check_library_exists(m sqrt "" HAVE_LIBM)
+check_library_exists(rt clock_gettime "" HAVE_LIBRT)
include(CheckTypeSize)
endif(GMX_LOAD_PLUGINS)
set(VMD_QUIETLY TRUE CACHE INTERNAL "")
+# Link real-time library for POSIX timers
+if(HAVE_TIME_H AND HAVE_UNISTD_H AND HAVE_LIBRT)
+ list(APPEND GMX_EXTRA_LIBRARIES rt)
+endif()
+
# Math and thread libraries must often come after all others when linking...
if(HAVE_LIBM)
list(APPEND GMX_EXTRA_LIBRARIES m)
}
}
-void print_perf(FILE *out, double nodetime, double realtime,
+void print_perf(FILE *out, double time_per_thread, double time_per_node,
gmx_large_int_t nsteps, real delta_t,
double nbfs, double mflop)
{
fprintf(out, "\n");
- if (realtime > 0)
+ if (time_per_node > 0)
{
fprintf(out, "%12s %12s %12s %10s\n", "", "Core t (s)", "Wall t (s)", "(%)");
fprintf(out, "%12s %12.3f %12.3f %10.1f\n", "Time:",
- nodetime, realtime, 100.0*nodetime/realtime);
- /* only print day-hour-sec format if realtime is more than 30 min */
- if (realtime > 30*60)
+ time_per_thread, time_per_node, 100.0*time_per_thread/time_per_node);
+ /* only print day-hour-sec format if time_per_node is more than 30 min */
+ if (time_per_node > 30*60)
{
fprintf(out, "%12s %12s", "", "");
- pr_difftime(out, realtime);
+ pr_difftime(out, time_per_node);
}
if (delta_t > 0)
{
- mflop = mflop/realtime;
+ mflop = mflop/time_per_node;
runtime = nsteps*delta_t;
if (getenv("GMX_DETAILED_PERF_STATS") == NULL)
fprintf(out, "%12s %12s %12s\n",
"", "(ns/day)", "(hour/ns)");
fprintf(out, "%12s %12.3f %12.3f\n", "Performance:",
- runtime*24*3.6/realtime, 1000*realtime/(3600*runtime));
+ runtime*24*3.6/time_per_node, 1000*time_per_node/(3600*runtime));
}
else
{
"", "(Mnbf/s)", (mflop > 1000) ? "(GFlops)" : "(MFlops)",
"(ns/day)", "(hour/ns)");
fprintf(out, "%12s %12.3f %12.3f %12.3f %12.3f\n", "Performance:",
- nbfs/realtime, (mflop > 1000) ? (mflop/1000) : mflop,
- runtime*24*3.6/realtime, 1000*realtime/(3600*runtime));
+ nbfs/time_per_node, (mflop > 1000) ? (mflop/1000) : mflop,
+ runtime*24*3.6/time_per_node, 1000*time_per_node/(3600*runtime));
}
}
else
fprintf(out, "%12s %14s\n",
"", "(steps/hour)");
fprintf(out, "%12s %14.1f\n", "Performance:",
- nsteps*3600.0/realtime);
+ nsteps*3600.0/time_per_node);
}
else
{
"", "(Mnbf/s)", (mflop > 1000) ? "(GFlops)" : "(MFlops)",
"(steps/hour)");
fprintf(out, "%12s %12.3f %12.3f %14.1f\n", "Performance:",
- nbfs/realtime, (mflop > 1000) ? (mflop/1000) : mflop,
- nsteps*3600.0/realtime);
+ nbfs/time_per_node, (mflop > 1000) ? (mflop/1000) : mflop,
+ nsteps*3600.0/time_per_node);
}
}
}
/*! /brief Manages measuring wall clock times for simulations */
typedef struct {
- double real; //!< Seconds since the epoch recorded at the start of the simulation
- // TODO rename real
-#ifdef GMX_CRAY_XT3
- double proc; //!< Seconds since the start start of the simulation
-#else
- clock_t proc; //!< Seconds since the start start of the simulation
-#endif
- double realtime; //!< Total seconds elapsed over the simulation
- // TODO rename realtime
- double proctime; //!< Total seconds elapsed over the simulation
- // TODO eliminate use of proc and proctime - also eliminates
- // dependency on clock() and dclock()
- double time_per_step; //!< Local variable TODO kill this
- double last; //!< Local variable TODO kill this
- gmx_large_int_t nsteps_done; //!< Used by integrators to report the amount of work they did
+ double start_time_stamp; //!< Seconds since the epoch recorded at the start of the simulation
+ double start_time_stamp_per_thread; //!< Seconds since the epoch recorded at the start of the simulation for this thread
+ double elapsed_run_time; //!< Total seconds elapsed over the simulation
+ double elapsed_run_time_per_thread; //!< Total seconds elapsed over the simulation running this thread
+ gmx_large_int_t nsteps_done; //!< Used by integrators to report the amount of work they did
} gmx_runtime_t;
void runtime_end(gmx_runtime_t *runtime);
-void runtime_upd_proc(gmx_runtime_t *runtime);
-/* The processor time should be updated every once in a while,
- * since on 32-bit manchines it loops after 72 minutes.
- */
+double runtime_get_elapsed_time(gmx_runtime_t *runtime);
void print_date_and_time(FILE *log, int pid, const char *title,
const gmx_runtime_t *runtime);
#include <config.h>
#endif
-#ifdef GMX_CRAY_XT3
-#include <catamount/dclock.h>
-#endif
-
-
#include <stdio.h>
-#include <time.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
#include <math.h>
#include "typedefs.h"
#include "string2.h"
#include <config.h>
#endif
-#ifdef GMX_CRAY_XT3
-#include <catamount/dclock.h>
-#endif
-
-
#include <stdio.h>
#include <time.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include "pbc.h"
#include "chargegroup.h"
#include "vec.h"
-#include <time.h>
#include "nrnb.h"
#include "mshift.h"
#include "mdrun.h"
double
gmx_gettime()
{
-#ifdef HAVE_GETTIMEOFDAY
+#if _POSIX_TIMERS > 0
+ /* Mac and Windows do not support this */
+ struct timespec t;
+ double seconds;
+
+ clock_gettime(CLOCK_REALTIME, &t);
+ seconds = (double) t.tv_sec + 1e-9*(double)t.tv_nsec;
+ return seconds;
+#elif defined HAVE_GETTIMEOFDAY
struct timeval t;
double seconds;
- // TODO later: gettimeofday() is deprecated by POSIX. We could use
- // clock_gettime in POSIX (which also offers nanosecond resolution
- // if the hardware supports it), but that requires linking with
- // -lrt. Maybe a better option will come along before we have to
- // really change from gettimeofday().
gettimeofday(&t, NULL);
-
seconds = (double) t.tv_sec + 1e-6*(double)t.tv_usec;
return seconds;
#endif
}
-// TODO Remove this. gmx_gettime returns double, so this is now useless
-#define difftime(end, start) ((double)(end)-(double)(start))
+double
+gmx_gettime_per_thread()
+{
+#if _POSIX_THREAD_CPUTIME > 0
+ struct timespec t;
+ double seconds;
+
+ clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t);
+ seconds = (double) t.tv_sec + 1e-9*(double)t.tv_nsec;
+ return seconds;
+#else
+ return gmx_gettime();
+#endif
+}
void print_time(FILE *out, gmx_runtime_t *runtime, gmx_large_int_t step,
t_inputrec *ir, t_commrec gmx_unused *cr)
{
time_t finish;
char timebuf[STRLEN];
- double dt;
+ double dt, time_per_step;
char buf[48];
#ifndef GMX_THREAD_MPI
fprintf(out, "step %s", gmx_step_str(step, buf));
if ((step >= ir->nstlist))
{
- runtime->last = gmx_gettime();
- dt = difftime(runtime->last, runtime->real);
- runtime->time_per_step = dt/(step - ir->init_step + 1);
+ double seconds_since_epoch = gmx_gettime();
+ dt = seconds_since_epoch - runtime->start_time_stamp;
+ time_per_step = dt/(step - ir->init_step + 1);
- dt = (ir->nsteps + ir->init_step - step)*runtime->time_per_step;
+ dt = (ir->nsteps + ir->init_step - step) * time_per_step;
if (ir->nsteps >= 0)
{
if (dt >= 300)
{
- finish = (time_t) (runtime->last + dt);
+ finish = (time_t) (seconds_since_epoch + dt);
gmx_ctime_r(&finish, timebuf, STRLEN);
sprintf(buf, "%s", timebuf);
buf[strlen(buf)-1] = '\0';
else
{
fprintf(out, " performance: %.1f ns/day ",
- ir->delta_t/1000*24*60*60/runtime->time_per_step);
+ ir->delta_t/1000*24*60*60/time_per_step);
}
}
#ifndef GMX_THREAD_MPI
fflush(out);
}
-// TODO eliminate this
-#ifdef NO_CLOCK
-#define clock() -1
-#endif
-
-static double set_proctime(gmx_runtime_t *runtime)
-{
- double diff;
-#ifdef GMX_CRAY_XT3
- double prev;
-
- prev = runtime->proc;
- runtime->proc = dclock();
-
- diff = runtime->proc - prev;
-#else
- clock_t prev;
-
- prev = runtime->proc;
- runtime->proc = clock();
-
- diff = (double)(runtime->proc - prev)/(double)CLOCKS_PER_SEC;
-#endif
- if (diff < 0)
- {
- /* The counter has probably looped, ignore this data */
- diff = 0;
- }
-
- return diff;
-}
-
void runtime_start(gmx_runtime_t *runtime)
{
- runtime->real = gmx_gettime();
- runtime->proc = 0;
- set_proctime(runtime);
- runtime->realtime = 0;
- runtime->proctime = 0;
- runtime->last = 0;
- runtime->time_per_step = 0;
+ runtime->start_time_stamp = gmx_gettime();
+ runtime->start_time_stamp_per_thread = gmx_gettime_per_thread();
+ runtime->elapsed_run_time = 0;
}
void runtime_end(gmx_runtime_t *runtime)
{
- double now;
+ double now, now_per_thread;
- now = gmx_gettime();
+ now = gmx_gettime();
+ now_per_thread = gmx_gettime_per_thread();
- runtime->proctime += set_proctime(runtime);
- runtime->realtime = now - runtime->real;
- runtime->real = now;
+ runtime->elapsed_run_time = now - runtime->start_time_stamp;
+ runtime->elapsed_run_time_per_thread = now_per_thread - runtime->start_time_stamp_per_thread;
}
-void runtime_upd_proc(gmx_runtime_t *runtime)
+double runtime_get_elapsed_time(gmx_runtime_t *runtime)
{
- runtime->proctime += set_proctime(runtime);
+ return gmx_gettime() - runtime->start_time_stamp;
}
void print_date_and_time(FILE *fplog, int nodeid, const char *title,
{
if (runtime != NULL)
{
- tmptime = (time_t) runtime->real;
+ tmptime = (time_t) runtime->start_time_stamp;
gmx_ctime_r(&tmptime, timebuf, STRLEN);
}
else
int nnbl, kernel_type, enr_nbnxn_kernel_ljc, enr_nbnxn_kernel_lj;
char *env;
nonbonded_verlet_group_t *nbvg;
- gmx_bool bCUDA;
+ gmx_bool bCUDA;
if (!(flags & GMX_FORCE_NONBONDED))
{
t_nrnb *nrnb_tot = NULL;
real delta_t;
double nbfs, mflop;
-
+ double elapsed_run_time_over_all_ranks = 0;
+ double elapsed_run_time_per_thread_over_all_ranks = 0;
wallcycle_sum(cr, wcycle);
if (cr->nnodes > 1)
nrnb_tot = nrnb;
}
-#if defined(GMX_MPI) && !defined(GMX_THREAD_MPI)
+#ifdef GMX_MPI
if (cr->nnodes > 1)
{
- /* reduce nodetime over all MPI processes in the current simulation */
- double sum;
- MPI_Allreduce(&runtime->proctime, &sum, 1, MPI_DOUBLE, MPI_SUM,
+ /* reduce elapsed_run_time over all MPI ranks in the current simulation */
+ MPI_Allreduce(&runtime->elapsed_run_time,
+ &elapsed_run_time_over_all_ranks,
+ 1, MPI_DOUBLE, MPI_SUM,
+ cr->mpi_comm_mysim);
+ elapsed_run_time_over_all_ranks /= cr->nnodes;
+ /* reduce elapsed_run_time_per_thread over all MPI ranks in the current simulation */
+ MPI_Allreduce(&runtime->elapsed_run_time_per_thread,
+ &elapsed_run_time_per_thread_over_all_ranks,
+ 1, MPI_DOUBLE, MPI_SUM,
cr->mpi_comm_mysim);
- runtime->proctime = sum;
}
+ else
#endif
+ {
+ elapsed_run_time_over_all_ranks = runtime->elapsed_run_time;
+ elapsed_run_time_per_thread_over_all_ranks = runtime->elapsed_run_time_per_thread;
+ }
if (SIMMASTER(cr))
{
if (SIMMASTER(cr))
{
- wallcycle_print(fplog, cr->nnodes, cr->npmenodes, runtime->realtime,
+ wallcycle_print(fplog, cr->nnodes, cr->npmenodes, runtime->elapsed_run_time,
wcycle, gputimes);
if (EI_DYNAMICS(inputrec->eI))
if (fplog)
{
- print_perf(fplog, runtime->proctime, runtime->realtime,
+ print_perf(fplog, elapsed_run_time_per_thread_over_all_ranks,
+ elapsed_run_time_over_all_ranks,
runtime->nsteps_done, delta_t, nbfs, mflop);
}
if (bWriteStat)
{
- print_perf(stderr, runtime->proctime, runtime->realtime,
+ print_perf(stderr, elapsed_run_time_per_thread_over_all_ranks,
+ elapsed_run_time_over_all_ranks,
runtime->nsteps_done, delta_t, nbfs, mflop);
}
}
{
gmx_mdoutf_t *outf;
gmx_large_int_t step, step_rel;
- double run_time;
+ double elapsed_run_time;
double t, t0, lam0[efptNR];
gmx_bool bGStatEveryStep, bGStat, bCalcVir, bCalcEner;
gmx_bool bNS, bNStList, bSimAnn, bStopCM, bRerunMD, bNotLastFrame = FALSE,
copy_mat(state->fvir_prev, force_vir);
}
- /* Determine the wallclock run time up till now */
- run_time = gmx_gettime() - (double)runtime->real;
+ elapsed_run_time = runtime_get_elapsed_time(runtime);
/* Check whether everything is still allright */
if (((int)gmx_get_stop_condition() > handled_stop_condition)
handled_stop_condition = (int)gmx_get_stop_condition();
}
else if (MASTER(cr) && (bNS || ir->nstlist <= 0) &&
- (max_hours > 0 && run_time > max_hours*60.0*60.0*0.99) &&
+ (max_hours > 0 && elapsed_run_time > max_hours*60.0*60.0*0.99) &&
gs.sig[eglsSTOPCOND] == 0 && gs.set[eglsSTOPCOND] == 0)
{
/* Signal to terminate the run */
}
if (bResetCountersHalfMaxH && MASTER(cr) &&
- run_time > max_hours*60.0*60.0*0.495)
+ elapsed_run_time > max_hours*60.0*60.0*0.495)
{
gs.sig[eglsRESETCOUNTERS] = 1;
}
if (MASTER(cr) && ((bGStat || !PAR(cr)) &&
cpt_period >= 0 &&
(cpt_period == 0 ||
- run_time >= nchkpt*cpt_period*60.0)) &&
+ elapsed_run_time >= nchkpt*cpt_period*60.0)) &&
gs.set[eglsCHKPT] == 0)
{
gs.sig[eglsCHKPT] = 1;
}
/* ######### END PREPARING EDR OUTPUT ########### */
- /* Time for performance */
- if (((step % stepout) == 0) || bLastStep)
- {
- runtime_upd_proc(runtime);
- }
-
/* Output stuff */
if (MASTER(cr))
{
gmx_pme_send_resetcounters(cr, step);
}
/* Correct max_hours for the elapsed time */
- max_hours -= run_time/(60.0*60.0);
+ max_hours -= elapsed_run_time/(60.0*60.0);
bResetCountersHalfMaxH = FALSE;
gs.set[eglsRESETCOUNTERS] = 0;
}
gmx_pmeonly(*pmedata, cr, nrnb, wcycle, &runtime, ewaldcoeff, inputrec);
}
- // TODO remove this, nobody reads runtime.real or runtime.proc after
- // this point - runtime_end() has already been called!
- if (EI_DYNAMICS(inputrec->eI) || EI_TPI(inputrec->eI))
- {
- /* Some timing stats */
- if (SIMMASTER(cr))
- {
- if (runtime.proc == 0)
- {
- runtime.proc = runtime.real;
- }
- }
- else
- {
- runtime.real = 0;
- }
- }
-
wallcycle_stop(wcycle, ewcRUN);
/* Finish up, write some stuff