#include "gromacs/domdec/domdec_network.h"
#include "gromacs/domdec/domdec_struct.h"
#include "gromacs/fft/calcgrid.h"
-#include "gromacs/gmxlib/md_logging.h"
#include "gromacs/gmxlib/network.h"
#include "gromacs/math/functions.h"
#include "gromacs/math/vec.h"
#include "gromacs/utility/cstringutil.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/gmxassert.h"
+#include "gromacs/utility/logger.h"
#include "gromacs/utility/smalloc.h"
#include "pme-internal.h"
void pme_loadbal_init(pme_load_balancing_t **pme_lb_p,
t_commrec *cr,
- FILE *fp_log,
+ const gmx::MDLogger &mdlog,
const t_inputrec *ir,
matrix box,
const interaction_const_t *ic,
- struct gmx_pme_t *pmedata,
+ gmx_pme_t *pmedata,
gmx_bool bUseGPU,
gmx_bool *bPrinting)
{
if (!wallcycle_have_counter())
{
- md_print_warn(cr, fp_log, "NOTE: Cycle counters unsupported or not enabled in kernel. Cannot use PME-PP balancing.\n");
+ GMX_LOG(mdlog.warning).asParagraph().appendText("NOTE: Cycle counters unsupported or not enabled in kernel. Cannot use PME-PP balancing.");
}
/* Tune with GPUs and/or separate PME ranks.
dd_dlb_lock(cr->dd);
if (dd_dlb_is_locked(cr->dd))
{
- md_print_warn(cr, fp_log, "NOTE: DLB will not turn on during the first phase of PME tuning\n");
+ GMX_LOG(mdlog.warning).asParagraph().appendText("NOTE: DLB will not turn on during the first phase of PME tuning");
}
}
t_commrec *cr,
FILE *fp_err,
FILE *fp_log,
+ const gmx::MDLogger &mdlog,
const t_inputrec *ir,
t_state *state,
double cycles,
/* This should not happen, as we set limits on the DLB bounds.
* But we implement a complete failsafe solution anyhow.
*/
- md_print_warn(cr, fp_log, "The fastest PP/PME load balancing setting (cutoff %.3f nm) is no longer available due to DD DLB or box size limitations\n");
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "The fastest PP/PME load balancing setting (cutoff %.3f nm) is no longer available due to DD DLB or box size limitations", pme_lb->fastest);
pme_lb->fastest = pme_lb->lower_limit;
pme_lb->start = pme_lb->lower_limit;
}
t_commrec *cr,
FILE *fp_err,
FILE *fp_log,
+ const gmx::MDLogger &mdlog,
const t_inputrec *ir,
t_forcerec *fr,
t_state *state,
{
/* Unlock the DLB=auto, DLB is allowed to activate */
dd_dlb_unlock(cr->dd);
- md_print_warn(cr, fp_log, "NOTE: DLB can now turn on, when beneficial\n");
+ GMX_LOG(mdlog.warning).asParagraph().appendText("NOTE: DLB can now turn on, when beneficial");
/* We don't deactivate the tuning yet, since we will balance again
* after DLB gets turned on, if it does within PMETune_period.
* but the first data collected is skipped anyhow.
*/
pme_load_balance(pme_lb, cr,
- fp_err, fp_log,
+ fp_err, fp_log, mdlog,
ir, state, pme_lb->cycles_c - cycles_prev,
fr->ic, fr->nbv, &fr->pmedata,
step);
{
/* Make sure DLB is allowed when we deactivate PME tuning */
dd_dlb_unlock(cr->dd);
- md_print_warn(cr, fp_log, "NOTE: DLB can now turn on, when beneficial\n");
+ GMX_LOG(mdlog.warning).asParagraph().appendText("NOTE: DLB can now turn on, when beneficial");
}
*bPrinting = pme_lb->bBalance;
/*! \brief Print all load-balancing settings */
static void print_pme_loadbal_settings(pme_load_balancing_t *pme_lb,
- t_commrec *cr,
FILE *fplog,
+ const gmx::MDLogger &mdlog,
gmx_bool bNonBondedOnGPU)
{
double pp_ratio, grid_ratio;
if (pp_ratio > 1.5 && !bNonBondedOnGPU)
{
- md_print_warn(cr, fplog,
- "NOTE: PME load balancing increased the non-bonded workload by more than 50%%.\n"
- " For better performance, use (more) PME ranks (mdrun -npme),\n"
- " or if you are beyond the scaling limit, use fewer total ranks (or nodes).\n");
+ GMX_LOG(mdlog.warning).asParagraph().appendText(
+ "NOTE: PME load balancing increased the non-bonded workload by more than 50%.\n"
+ " For better performance, use (more) PME ranks (mdrun -npme),\n"
+ " or if you are beyond the scaling limit, use fewer total ranks (or nodes).");
}
else
{
}
void pme_loadbal_done(pme_load_balancing_t *pme_lb,
- t_commrec *cr,
FILE *fplog,
+ const gmx::MDLogger &mdlog,
gmx_bool bNonBondedOnGPU)
{
if (fplog != NULL && (pme_lb->cur > 0 || pme_lb->elimited != epmelblimNO))
{
- print_pme_loadbal_settings(pme_lb, cr, fplog, bNonBondedOnGPU);
+ print_pme_loadbal_settings(pme_lb, fplog, mdlog, bNonBondedOnGPU);
}
/* TODO: Here we should free all pointers in pme_lb,
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct t_commrec;
struct t_inputrec;
+namespace gmx
+{
+class MDLogger;
+}
+
/*! \brief Object to manage PME load balancing */
struct pme_load_balancing_t;
* usage.
*/
void pme_loadbal_init(pme_load_balancing_t **pme_lb_p,
- struct t_commrec *cr,
- FILE *fp_log,
+ t_commrec *cr,
+ const gmx::MDLogger &mdlog,
const t_inputrec *ir,
matrix box,
const interaction_const_t *ic,
- struct gmx_pme_t *pmedata,
+ gmx_pme_t *pmedata,
gmx_bool bUseGPU,
gmx_bool *bPrinting);
struct t_commrec *cr,
FILE *fp_err,
FILE *fp_log,
+ const gmx::MDLogger &mdlog,
const t_inputrec *ir,
t_forcerec *fr,
t_state *state,
/*! \brief Finish the PME load balancing and print the settings when fplog!=NULL */
void pme_loadbal_done(pme_load_balancing_t *pme_lb,
- struct t_commrec *cr,
FILE *fplog,
+ const gmx::MDLogger &mdlog,
gmx_bool bNonBondedOnGPU);
#endif
+++ /dev/null
-/*
- * This file is part of the GROMACS molecular simulation package.
- *
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2014,2015, by the GROMACS development team, led by
- * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
- * and including many others, as listed in the AUTHORS file in the
- * top-level source directory and at http://www.gromacs.org.
- *
- * GROMACS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * GROMACS is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GROMACS; if not, see
- * http://www.gnu.org/licenses, or write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * If you want to redistribute modifications to GROMACS, please
- * consider that scientific software is very special. Version
- * control is crucial - bugs must be traceable. We will be happy to
- * consider code for inclusion in the official distribution, but
- * derived work must not be called official GROMACS. Details are found
- * in the README & COPYING files - if they are missing, get the
- * official version at http://www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org.
- */
-#include "gmxpre.h"
-
-#include "md_logging.h"
-
-#include <cstdarg>
-#include <cstdio>
-
-#include "gromacs/mdtypes/commrec.h"
-
-
-void md_print_info(const t_commrec *cr, FILE *fplog,
- const char *fmt, ...)
-{
- va_list ap;
-
- if (cr == NULL || SIMMASTER(cr))
- {
- va_start(ap, fmt);
-
- vfprintf(stderr, fmt, ap);
-
- va_end(ap);
- }
- if (fplog != NULL)
- {
- va_start(ap, fmt);
-
- vfprintf(fplog, fmt, ap);
-
- va_end(ap);
- }
-}
-
-void md_print_warn(const t_commrec *cr, FILE *fplog,
- const char *fmt, ...)
-{
- va_list ap;
-
- if (cr == NULL || SIMMASTER(cr))
- {
- va_start(ap, fmt);
-
- fprintf(stderr, "\n");
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
-
- va_end(ap);
- }
- if (fplog != NULL)
- {
- va_start(ap, fmt);
-
- fprintf(fplog, "\n");
- vfprintf(fplog, fmt, ap);
- fprintf(fplog, "\n");
-
- va_end(ap);
- }
-}
+++ /dev/null
-/*
- * This file is part of the GROMACS molecular simulation package.
- *
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2014,2015, by the GROMACS development team, led by
- * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
- * and including many others, as listed in the AUTHORS file in the
- * top-level source directory and at http://www.gromacs.org.
- *
- * GROMACS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * GROMACS is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GROMACS; if not, see
- * http://www.gnu.org/licenses, or write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * If you want to redistribute modifications to GROMACS, please
- * consider that scientific software is very special. Version
- * control is crucial - bugs must be traceable. We will be happy to
- * consider code for inclusion in the official distribution, but
- * derived work must not be called official GROMACS. Details are found
- * in the README & COPYING files - if they are missing, get the
- * official version at http://www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org.
- */
-#ifndef GMX_GMXLIB_MD_LOGGING_H
-#define GMX_GMXLIB_MD_LOGGING_H
-
-#include <cstdio>
-
-struct t_commrec;
-
-void md_print_info(const t_commrec *cr, FILE *fplog,
- const char *fmt, ...);
-/* Print an general information message to stderr on the master node
- * and to fplog if fplog!=NULL.
- * fmt is a standard printf formatting string which should end in \n,
- * the arguments after that contain the values to be printed, as in printf.
- */
-
-void md_print_warn(const t_commrec *cr, FILE *fplog,
- const char *fmt, ...);
-/* As md_print_info above, but for important notices or warnings.
- * The only difference with md_print_info is that a newline is printed
- * before and after the message such that it stands out.
- */
-
-#endif
#include "gromacs/hardware/gpu_hw_info.h"
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/cstringutil.h"
+#include "gromacs/utility/logger.h"
#include "gromacs/utility/smalloc.h"
#if HAVE_NVML
return 0;
}
-#if HAVE_NVML
-/* TODO: We should actually be using md_print_warn in md_logging.c,
- * but we can't include mpi.h in CUDA code.
- */
-static void md_print_info(FILE *fplog,
- const char *fmt, ...)
-{
- va_list ap;
-
- if (fplog != NULL)
- {
- /* We should only print to stderr on the master node,
- * in most cases fplog is only set on the master node, so this works.
- */
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
-
- va_start(ap, fmt);
- vfprintf(fplog, fmt, ap);
- va_end(ap);
- }
-}
-#endif /*HAVE_NVML*/
-
-/* TODO: We should actually be using md_print_warn in md_logging.c,
- * but we can't include mpi.h in CUDA code.
- * This is replicated from nbnxn_cuda_data_mgmt.cu.
- */
-static void md_print_warn(FILE *fplog,
- const char *fmt, ...)
-{
- va_list ap;
-
- if (fplog != NULL)
- {
- /* We should only print to stderr on the master node,
- * in most cases fplog is only set on the master node, so this works.
- */
- va_start(ap, fmt);
- fprintf(stderr, "\n");
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
- va_end(ap);
-
- va_start(ap, fmt);
- fprintf(fplog, "\n");
- vfprintf(fplog, fmt, ap);
- fprintf(fplog, "\n");
- va_end(ap);
- }
-}
-
#if HAVE_NVML_APPLICATION_CLOCKS
/*! \brief Determines and adds the NVML device ID to the passed \cuda_dev.
*
* allow this. For future GPU architectures a more sophisticated scheme might be
* required.
*
- * \param[out] fplog log file to write to
+ * \param mdlog log file to write to
* \param[in] gpuid index of the GPU to set application clocks for
* \param[in] gpu_info GPU info of all detected devices in the system.
* \returns true if no error occurs during application clocks handling.
*/
-static gmx_bool init_gpu_application_clocks(FILE gmx_unused *fplog, int gmx_unused gpuid, const gmx_gpu_info_t gmx_unused *gpu_info)
+static gmx_bool init_gpu_application_clocks(
+ const gmx::MDLogger &mdlog, int gmx_unused gpuid,
+ const gmx_gpu_info_t gmx_unused *gpu_info)
{
const cudaDeviceProp *prop = &gpu_info->gpu_dev[gpuid].prop;
int cuda_version_number = prop->major * 10 + prop->minor;
int cuda_runtime = 0;
cudaDriverGetVersion(&cuda_driver);
cudaRuntimeGetVersion(&cuda_runtime);
- md_print_warn( fplog, "NOTE: GROMACS was configured without NVML support hence it can not exploit\n"
- " application clocks of the detected %s GPU to improve performance.\n"
- " Recompile with the NVML library (compatible with the driver used) or set application clocks manually.\n",
- prop->name);
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "NOTE: GROMACS was configured without NVML support hence it can not exploit\n"
+ " application clocks of the detected %s GPU to improve performance.\n"
+ " Recompile with the NVML library (compatible with the driver used) or set application clocks manually.",
+ prop->name);
return true;
#else
if (!bCompiledWithApplicationClockSupport)
int cuda_runtime = 0;
cudaDriverGetVersion(&cuda_driver);
cudaRuntimeGetVersion(&cuda_runtime);
- md_print_warn( fplog, "NOTE: GROMACS was compiled with an old NVML library which does not support\n"
- " managing application clocks of the detected %s GPU to improve performance.\n"
- " If your GPU supports application clocks, upgrade NVML (and driver) and recompile or set the clocks manually.\n",
- prop->name );
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "NOTE: GROMACS was compiled with an old NVML library which does not support\n"
+ " managing application clocks of the detected %s GPU to improve performance.\n"
+ " If your GPU supports application clocks, upgrade NVML (and driver) and recompile or set the clocks manually.",
+ prop->name );
return true;
}
e.g. if max application clocks should not be used for certain GPUs. */
if (nvml_stat == NVML_SUCCESS && app_sm_clock < max_sm_clock && gpu_info->gpu_dev[gpuid].nvml_is_restricted == NVML_FEATURE_DISABLED)
{
- md_print_info( fplog, "Changing GPU application clocks for %s to (%d,%d)\n", gpu_info->gpu_dev[gpuid].prop.name, max_mem_clock, max_sm_clock);
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "Changing GPU application clocks for %s to (%d,%d)",
+ gpu_info->gpu_dev[gpuid].prop.name, max_mem_clock, max_sm_clock);
nvml_stat = nvmlDeviceSetApplicationsClocks ( gpu_info->gpu_dev[gpuid].nvml_device_id, max_mem_clock, max_sm_clock );
HANDLE_NVML_RET_ERR( nvml_stat, "nvmlDeviceGetApplicationsClock failed" );
gpu_info->gpu_dev[gpuid].nvml_ap_clocks_changed = true;
}
else if (nvml_stat == NVML_SUCCESS && app_sm_clock < max_sm_clock)
{
- md_print_warn( fplog, "Can not change application clocks for %s to optimal values due to insufficient permissions. Current values are (%d,%d), max values are (%d,%d).\nUse sudo nvidia-smi -acp UNRESTRICTED or contact your admin to change application clocks.\n", gpu_info->gpu_dev[gpuid].prop.name, app_mem_clock, app_sm_clock, max_mem_clock, max_sm_clock);
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "Can not change application clocks for %s to optimal values due to insufficient permissions. Current values are (%d,%d), max values are (%d,%d).\nUse sudo nvidia-smi -acp UNRESTRICTED or contact your admin to change application clocks.",
+ gpu_info->gpu_dev[gpuid].prop.name, app_mem_clock, app_sm_clock, max_mem_clock, max_sm_clock);
}
else if (nvml_stat == NVML_SUCCESS && app_sm_clock == max_sm_clock)
{
//TODO: This should probably be integrated into the GPU Properties table.
- md_print_info( fplog, "Application clocks (GPU clocks) for %s are (%d,%d)\n", gpu_info->gpu_dev[gpuid].prop.name, app_mem_clock, app_sm_clock);
+ GMX_LOG(mdlog.warning).appendTextFormatted(
+ "Application clocks (GPU clocks) for %s are (%d,%d)",
+ gpu_info->gpu_dev[gpuid].prop.name, app_mem_clock, app_sm_clock);
}
else
{
- md_print_warn( fplog, "Can not change GPU application clocks to optimal values due to NVML error (%d): %s.\n", nvml_stat, nvmlErrorString(nvml_stat));
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "Can not change GPU application clocks to optimal values due to NVML error (%d): %s.",
+ nvml_stat, nvmlErrorString(nvml_stat));
}
return (nvml_stat == NVML_SUCCESS);
#endif /* HAVE_NVML */
#endif /* HAVE_NVML_APPLICATION_CLOCKS */
}
-gmx_bool init_gpu(FILE gmx_unused *fplog, int mygpu, char *result_str,
+gmx_bool init_gpu(const gmx::MDLogger &mdlog, int mygpu, char *result_str,
const struct gmx_gpu_info_t *gpu_info,
const struct gmx_gpu_opt_t *gpu_opt)
{
//Ignoring return value as NVML errors should be treated not critical.
if (stat == cudaSuccess)
{
- init_gpu_application_clocks(fplog, gpuid, gpu_info);
+ init_gpu_application_clocks(mdlog, gpuid, gpu_info);
}
return (stat == cudaSuccess);
}
struct gmx_gpu_info_t;
struct gmx_gpu_opt_t;
+namespace gmx
+{
+class MDLogger;
+}
+
/*! \brief Detect all GPUs in the system.
*
* Will detect every GPU supported by the device driver in use. Also
* The varible \p mygpu is the index of the GPU to initialize in the
* gpu_info.gpu_dev array.
*
- * \param[out] fplog log file to write to
+ * \param mdlog log file to write to
* \param[in] mygpu index of the GPU to initialize
* \param[out] result_str the message related to the error that occurred
* during the initialization (if there was any).
* \returns true if no error occurs during initialization.
*/
GPU_FUNC_QUALIFIER
-gmx_bool init_gpu(FILE *GPU_FUNC_ARGUMENT(fplog),
+gmx_bool init_gpu(const gmx::MDLogger &GPU_FUNC_ARGUMENT(mdlog),
int GPU_FUNC_ARGUMENT(mygpu),
char *GPU_FUNC_ARGUMENT(result_str),
const struct gmx_gpu_info_t *GPU_FUNC_ARGUMENT(gpu_info),
}
//! This function is documented in the header file
-gmx_bool init_gpu(FILE gmx_unused *fplog,
+gmx_bool init_gpu(const gmx::MDLogger & /*mdlog*/,
int mygpu,
char *result_str,
const gmx_gpu_info_t gmx_unused *gpu_info,
#include "thread_mpi/threads.h"
-#include "gromacs/gmxlib/md_logging.h"
#include "gromacs/gmxlib/network.h"
#include "gromacs/gpu_utils/gpu_utils.h"
#include "gromacs/hardware/cpuinfo.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/gmxomp.h"
+#include "gromacs/utility/logger.h"
#include "gromacs/utility/programcontext.h"
#include "gromacs/utility/smalloc.h"
#include "gromacs/utility/stringutil.h"
}
}
-static void print_gpu_detection_stats(FILE *fplog,
- const gmx_gpu_info_t *gpu_info,
- const t_commrec *cr)
+static void print_gpu_detection_stats(const gmx::MDLogger &mdlog,
+ const gmx_gpu_info_t *gpu_info)
{
char onhost[HOSTNAMELEN+10], stmp[STRLEN];
int ngpu;
if (ngpu > 0)
{
sprint_gpus(stmp, gpu_info);
- md_print_warn(cr, fplog, "%d GPU%s detected%s:\n%s\n",
- ngpu, (ngpu > 1) ? "s" : "", onhost, stmp);
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "%d GPU%s detected%s:\n%s",
+ ngpu, (ngpu > 1) ? "s" : "", onhost, stmp);
}
else
{
- md_print_warn(cr, fplog, "No GPUs detected%s\n", onhost);
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted("No GPUs detected%s", onhost);
}
}
/* Give a suitable fatal error or warning if the build configuration
and runtime CPU do not match. */
static void
-check_use_of_rdtscp_on_this_cpu(FILE *fplog,
- const t_commrec *cr,
+check_use_of_rdtscp_on_this_cpu(const gmx::MDLogger &mdlog,
const gmx::CpuInfo &cpuInfo)
{
#ifdef HAVE_RDTSCP
{
if (binaryUsesRdtscp)
{
- md_print_warn(cr, fplog, "The %s executable was compiled to use the rdtscp CPU instruction. "
- "We cannot detect the features of your current CPU, but will proceed anyway. "
- "If you get a crash, rebuild GROMACS with the GMX_USE_RDTSCP=OFF CMake option.",
- programName);
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "The %s executable was compiled to use the rdtscp CPU instruction. "
+ "We cannot detect the features of your current CPU, but will proceed anyway. "
+ "If you get a crash, rebuild GROMACS with the GMX_USE_RDTSCP=OFF CMake option.",
+ programName);
}
}
else
if (cpuHasRdtscp && !binaryUsesRdtscp)
{
- md_print_warn(cr, fplog, "The current CPU can measure timings more accurately than the code in\n"
- "%s was configured to use. This might affect your simulation\n"
- "speed as accurate timings are needed for load-balancing.\n"
- "Please consider rebuilding %s with the GMX_USE_RDTSCP=ON CMake option.\n",
- programName, programName);
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "The current CPU can measure timings more accurately than the code in\n"
+ "%s was configured to use. This might affect your simulation\n"
+ "speed as accurate timings are needed for load-balancing.\n"
+ "Please consider rebuilding %s with the GMX_USE_RDTSCP=ON CMake option.",
+ programName, programName);
}
}
}
-void gmx_check_hw_runconf_consistency(FILE *fplog,
+void gmx_check_hw_runconf_consistency(const gmx::MDLogger &mdlog,
const gmx_hw_info_t *hwinfo,
const t_commrec *cr,
const gmx_hw_opt_t *hw_opt,
if (hwinfo->gpu_info.n_dev_compatible > 0)
{
- std::string gpuUseageReport;
+ std::string gpuUsageReport;
try
{
- gpuUseageReport = makeGpuUsageReport(&hwinfo->gpu_info,
- &hw_opt->gpu_opt,
- cr->nrank_pp_intranode,
- bMPI && cr->nnodes > 1);
+ gpuUsageReport = makeGpuUsageReport(&hwinfo->gpu_info,
+ &hw_opt->gpu_opt,
+ cr->nrank_pp_intranode,
+ bMPI && cr->nnodes > 1);
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
/* NOTE: this print is only for and on one physical node */
- md_print_info(cr, fplog, "%s\n", gpuUseageReport.c_str());
+ GMX_LOG(mdlog.warning).appendText(gpuUsageReport);
}
/* Need to ensure that we have enough GPUs:
{
/* There are more GPUs than tMPI threads; we have
limited the number GPUs used. */
- md_print_warn(cr, fplog,
- "NOTE: %d GPU%s were detected, but only %d PP thread-MPI thread%s can be started.\n"
- " %s can use one GPU per PP tread-MPI thread, so only %d GPU%s will be used.\n",
- ngpu_comp, gpu_comp_plural,
- npppn, th_or_proc_plural,
- programName, npppn,
- npppn > 1 ? "s" : "");
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "NOTE: %d GPU%s were detected, but only %d PP thread-MPI thread%s can be started.\n"
+ " %s can use one GPU per PP tread-MPI thread, so only %d GPU%s will be used.",
+ ngpu_comp, gpu_comp_plural,
+ npppn, th_or_proc_plural,
+ programName, npppn,
+ npppn > 1 ? "s" : "");
}
}
/* TODO Should we have a gpu_opt->n_dev_supported field? */
if (ngpu_comp > npppn && gmx_multiple_gpu_per_node_supported())
{
- md_print_warn(cr, fplog,
- "NOTE: potentially sub-optimal launch configuration, %s started with less\n"
- " PP %s%s%s than GPU%s available.\n"
- " Each PP %s can use only one GPU, %d GPU%s%s will be used.\n",
- programName, th_or_proc,
- th_or_proc_plural, pernode, gpu_comp_plural,
- th_or_proc, npppn, gpu_use_plural, pernode);
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "NOTE: potentially sub-optimal launch configuration, %s started with less\n"
+ " PP %s%s%s than GPU%s available.\n"
+ " Each PP %s can use only one GPU, %d GPU%s%s will be used.",
+ programName, th_or_proc,
+ th_or_proc_plural, pernode, gpu_comp_plural,
+ th_or_proc, npppn, gpu_use_plural, pernode);
}
if (ngpu_use != npppn)
if (same_count > 0)
{
- md_print_info(cr, fplog,
- "NOTE: You assigned %s to multiple %s%s.\n",
- same_count > 1 ? "GPUs" : "a GPU", th_or_proc, btMPI ? "s" : "es");
+ GMX_LOG(mdlog.warning).appendTextFormatted(
+ "NOTE: You assigned %s to multiple %s%s.",
+ same_count > 1 ? "GPUs" : "a GPU", th_or_proc, btMPI ? "s" : "es");
}
}
}
* _SC_NPROCESSORS_ONLN to report 1 at the beginning of the run. For this
* reason we now warn if this mismatches with the detected core count.
*/
-static void check_nthreads_hw_avail(const t_commrec gmx_unused *cr,
- FILE gmx_unused *fplog, int nthreads)
+static void check_nthreads_hw_avail(const gmx::MDLogger gmx_unused &mdlog, int nthreads)
{
// Now check if we have the argument to use before executing the call
#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
if (nthreads != sysconf(_SC_NPROCESSORS_ONLN))
{
- md_print_warn(cr, fplog,
- "%d CPUs configured, but only %d of them are online.\n"
- "This can happen on embedded platforms (e.g. ARM) where the OS shuts some cores\n"
- "off to save power, and will turn them back on later when the load increases.\n"
- "However, this will likely mean GROMACS cannot pin threads to those cores. You\n"
- "will likely see much better performance by forcing all cores to be online, and\n"
- "making sure they run at their full clock frequency.", nthreads, sysconf(_SC_NPROCESSORS_ONLN));
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "%d CPUs configured, but only %d of them are online.\n"
+ "This can happen on embedded platforms (e.g. ARM) where the OS shuts some cores\n"
+ "off to save power, and will turn them back on later when the load increases.\n"
+ "However, this will likely mean GROMACS cannot pin threads to those cores. You\n"
+ "will likely see much better performance by forcing all cores to be online, and\n"
+ "making sure they run at their full clock frequency.",
+ nthreads, sysconf(_SC_NPROCESSORS_ONLN));
}
#endif
#if GMX_OPENMP
if (nthreads != gmx_omp_get_num_procs())
{
- md_print_warn(cr, fplog,
- "Number of logical cores detected (%d) does not match the number reported by OpenMP (%d).\n"
- "Consider setting the launch configuration manually!",
- nthreads, gmx_omp_get_num_procs());
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "Number of logical cores detected (%d) does not match the number reported by OpenMP (%d).\n"
+ "Consider setting the launch configuration manually!",
+ nthreads, gmx_omp_get_num_procs());
}
#endif
}
-static void gmx_detect_gpus(FILE *fplog, const t_commrec *cr)
+static void gmx_detect_gpus(const gmx::MDLogger &mdlog, const t_commrec *cr)
{
#if GMX_LIB_MPI
int rank_world;
MPI_Comm_split(MPI_COMM_WORLD, gmx_physicalnode_id_hash(),
rank_world, &physicalnode_comm);
MPI_Comm_rank(physicalnode_comm, &rank_local);
+ GMX_UNUSED_VALUE(cr);
#else
/* Here there should be only one process, check this */
GMX_RELEASE_ASSERT(cr->nnodes == 1 && cr->sim_nodeid == 0, "Only a single (master) process should execute here");
{
sprintf(sbuf, ".");
}
- md_print_warn(cr, fplog,
- "NOTE: Error occurred during GPU detection%s"
- " Can not use GPU acceleration, will fall back to CPU kernels.\n",
- sbuf);
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "NOTE: Error occurred during GPU detection%s"
+ " Can not use GPU acceleration, will fall back to CPU kernels.",
+ sbuf);
}
}
#endif
}
-gmx_hw_info_t *gmx_detect_hardware(FILE *fplog, const t_commrec *cr,
+gmx_hw_info_t *gmx_detect_hardware(const gmx::MDLogger &mdlog, const t_commrec *cr,
gmx_bool bDetectGPUs)
{
int ret;
// TODO: Get rid of this altogether.
hwinfo_g->nthreads_hw_avail = hwinfo_g->hardwareTopology->machine().logicalProcessorCount;
- check_nthreads_hw_avail(cr, fplog, hwinfo_g->nthreads_hw_avail);
+ check_nthreads_hw_avail(mdlog, hwinfo_g->nthreads_hw_avail);
/* detect GPUs */
hwinfo_g->gpu_info.n_dev = 0;
getenv("GMX_DISABLE_GPU_DETECTION") == NULL);
if (hwinfo_g->gpu_info.bDetectGPUs)
{
- gmx_detect_gpus(fplog, cr);
+ gmx_detect_gpus(mdlog, cr);
}
}
/* increase the reference counter */
}
void gmx_print_detected_hardware(FILE *fplog, const t_commrec *cr,
+ const gmx::MDLogger &mdlog,
const gmx_hw_info_t *hwinfo)
{
const gmx::CpuInfo &cpuInfo = *hwinfo_g->cpuInfo;
}
/* For RDTSCP we only check on our local node and skip the MPI reduction */
- check_use_of_rdtscp_on_this_cpu(fplog, cr, cpuInfo);
+ check_use_of_rdtscp_on_this_cpu(mdlog, cpuInfo);
}
//! \brief Return if any GPU ID (e.g in a user-supplied string) is repeated
}
}
-void gmx_select_gpu_ids(FILE *fplog, const t_commrec *cr,
+void gmx_select_gpu_ids(const gmx::MDLogger &mdlog, const t_commrec *cr,
const gmx_gpu_info_t *gpu_info,
gmx_bool bForceUseGPU,
gmx_gpu_opt_t *gpu_opt)
if (!res)
{
- print_gpu_detection_stats(fplog, gpu_info, cr);
+ print_gpu_detection_stats(mdlog, gpu_info);
sprintf(sbuf, "Some of the requested GPUs do not exist, behave strangely, or are not compatible:\n");
for (i = 0; i < gpu_opt->n_dev_use; i++)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct gmx_hw_opt_t;
struct t_commrec;
+namespace gmx
+{
+class MDLogger;
+}
+
/*! \brief Return whether mdrun can use more than one GPU per node
*
* The OpenCL implementation cannot use more than one GPU per node,
/* Construct the global hwinfo structure and return a pointer to
it. Caller is responsible for freeing this pointer. */
-gmx_hw_info_t *gmx_detect_hardware(FILE *fplog, const t_commrec *cr,
- gmx_bool bDetectGPUs);
+gmx_hw_info_t *gmx_detect_hardware(const gmx::MDLogger &mdlog,
+ const t_commrec *cr, gmx_bool bDetectGPUs);
/* Print information about the detected hardware to fplog (if != NULL)
* and to stderr the master rank.
*/
void gmx_print_detected_hardware(FILE *fplog, const t_commrec *cr,
+ const gmx::MDLogger &mdlog,
const gmx_hw_info_t *hwinfo);
void gmx_hardware_info_free(gmx_hw_info_t *hwinfo);
void gmx_parse_gpu_ids(gmx_gpu_opt_t *gpu_opt);
-void gmx_select_gpu_ids(FILE *fplog, const t_commrec *cr,
+void gmx_select_gpu_ids(const gmx::MDLogger &mdlog, const t_commrec *cr,
const gmx_gpu_info_t *gpu_info,
gmx_bool bForceUseGPU,
gmx_gpu_opt_t *gpu_opt);
/* Check the consistency of hw_opt with hwinfo.
This function should be called once on each MPI rank. */
-void gmx_check_hw_runconf_consistency(FILE *fplog,
+void gmx_check_hw_runconf_consistency(const gmx::MDLogger &mdlog,
const gmx_hw_info_t *hwinfo,
const t_commrec *cr,
const gmx_hw_opt_t *hw_opt,
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct t_nrnb;
struct t_pbc;
+namespace gmx
+{
+class MDLogger;
+}
+
void calc_vir(int nxf, rvec x[], rvec f[], tensor vir,
gmx_bool bScrewPBC, matrix box);
/* Calculate virial for nxf atoms, and add it to vir */
*/
-gmx_bool nbnxn_gpu_acceleration_supported(FILE *fplog,
- const t_commrec *cr,
- const t_inputrec *ir,
- gmx_bool bRerunMD);
+gmx_bool nbnxn_gpu_acceleration_supported(const gmx::MDLogger &mdlog,
+ const t_inputrec *ir,
+ gmx_bool bRerunMD);
/* Return if GPU acceleration is supported with the given settings.
*
* If the return value is FALSE and fplog/cr != NULL, prints a fallback
* message to fplog/stderr.
*/
-gmx_bool nbnxn_simd_supported(FILE *fplog,
- const t_commrec *cr,
- const t_inputrec *ir);
+gmx_bool nbnxn_simd_supported(const gmx::MDLogger &mdlog,
+ const t_inputrec *ir);
/* Return if CPU SIMD support exists for the given inputrec
* If the return value is FALSE and fplog/cr != NULL, prints a fallback
* message to fplog/stderr.
#include "gromacs/domdec/domdec_struct.h"
#include "gromacs/ewald/ewald.h"
#include "gromacs/fileio/filetypes.h"
-#include "gromacs/gmxlib/md_logging.h"
#include "gromacs/gmxlib/network.h"
#include "gromacs/gmxlib/nonbonded/nonbonded.h"
#include "gromacs/gpu_utils/gpu_utils.h"
#include "gromacs/utility/cstringutil.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/gmxassert.h"
+#include "gromacs/utility/logger.h"
#include "gromacs/utility/pleasecite.h"
#include "gromacs/utility/smalloc.h"
#include "gromacs/utility/stringutil.h"
}
-gmx_bool nbnxn_gpu_acceleration_supported(FILE *fplog,
- const t_commrec *cr,
- const t_inputrec *ir,
- gmx_bool bRerunMD)
+gmx_bool nbnxn_gpu_acceleration_supported(const gmx::MDLogger &mdlog,
+ const t_inputrec *ir,
+ gmx_bool bRerunMD)
{
if (bRerunMD && ir->opts.ngener > 1)
{
* (which runs much faster than a multiple-energy-groups
* implementation would), and issue a note in the .log
* file. Users can re-run if they want the information. */
- md_print_warn(cr, fplog, "Rerun with energy groups is not implemented for GPUs, falling back to the CPU\n");
+ GMX_LOG(mdlog.warning).asParagraph().appendText("Rerun with energy groups is not implemented for GPUs, falling back to the CPU");
return FALSE;
}
return TRUE;
}
-gmx_bool nbnxn_simd_supported(FILE *fplog,
- const t_commrec *cr,
- const t_inputrec *ir)
+gmx_bool nbnxn_simd_supported(const gmx::MDLogger &mdlog,
+ const t_inputrec *ir)
{
if (ir->vdwtype == evdwPME && ir->ljpme_combination_rule == eljpmeLB)
{
/* LJ PME with LB combination rule does 7 mesh operations.
* This so slow that we don't compile SIMD non-bonded kernels
* for that. */
- md_print_warn(cr, fplog, "LJ-PME with Lorentz-Berthelot is not supported with SIMD kernels, falling back to plain C kernels\n");
+ GMX_LOG(mdlog.warning).asParagraph().appendText("LJ-PME with Lorentz-Berthelot is not supported with SIMD kernels, falling back to plain C kernels");
return FALSE;
}
};
static void pick_nbnxn_kernel(FILE *fp,
- const t_commrec *cr,
+ const gmx::MDLogger &mdlog,
gmx_bool use_simd_kernels,
gmx_bool bUseGPU,
gmx_bool bEmulateGPU,
if (bDoNonbonded)
{
- md_print_warn(cr, fp, "Emulating a GPU run on the CPU (slow)");
+ GMX_LOG(mdlog.warning).asParagraph().appendText("Emulating a GPU run on the CPU (slow)");
}
}
else if (bUseGPU)
if (*kernel_type == nbnxnkNotSet)
{
if (use_simd_kernels &&
- nbnxn_simd_supported(fp, cr, ir))
+ nbnxn_simd_supported(mdlog, ir))
{
pick_nbnxn_kernel_cpu(ir, kernel_type, ewald_excl);
}
if (nbnxnk4x4_PlainC == *kernel_type ||
nbnxnk8x8x8_PlainC == *kernel_type)
{
- md_print_warn(cr, fp,
- "WARNING: Using the slow %s kernels. This should\n"
- "not happen during routine usage on supported platforms.\n\n",
- lookup_nbnxn_kernel_name(*kernel_type));
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "WARNING: Using the slow %s kernels. This should\n"
+ "not happen during routine usage on supported platforms.",
+ lookup_nbnxn_kernel_name(*kernel_type));
}
}
}
-static void pick_nbnxn_resources(FILE *fp,
+static void pick_nbnxn_resources(const gmx::MDLogger &mdlog,
const t_commrec *cr,
const gmx_hw_info_t *hwinfo,
gmx_bool bDoNonbonded,
{
/* Each PP node will use the intra-node id-th device from the
* list of detected/selected GPUs. */
- if (!init_gpu(fp, cr->rank_pp_intranode, gpu_err_str,
+ if (!init_gpu(mdlog, cr->rank_pp_intranode, gpu_err_str,
&hwinfo->gpu_info, gpu_opt))
{
/* At this point the init should never fail as we made sure that
}
static void init_nb_verlet(FILE *fp,
+ const gmx::MDLogger &mdlog,
nonbonded_verlet_t **nb_verlet,
gmx_bool bFEP_NonBonded,
const t_inputrec *ir,
snew(nbv, 1);
- pick_nbnxn_resources(fp, cr, fr->hwinfo,
+ pick_nbnxn_resources(mdlog, cr, fr->hwinfo,
fr->bNonbonded,
&nbv->bUseGPU,
&bEmulateGPU,
if (i == 0) /* local */
{
- pick_nbnxn_kernel(fp, cr, fr->use_simd_kernels,
+ pick_nbnxn_kernel(fp, mdlog, fr->use_simd_kernels,
nbv->bUseGPU, bEmulateGPU, ir,
&nbv->grp[i].kernel_type,
&nbv->grp[i].ewald_excl,
if (nbpu_opt != NULL && strcmp(nbpu_opt, "gpu_cpu") == 0)
{
/* Use GPU for local, select a CPU kernel for non-local */
- pick_nbnxn_kernel(fp, cr, fr->use_simd_kernels,
+ pick_nbnxn_kernel(fp, mdlog, fr->use_simd_kernels,
FALSE, FALSE, ir,
&nbv->grp[i].kernel_type,
&nbv->grp[i].ewald_excl,
return nbv != NULL && nbv->bUseGPU;
}
-void init_forcerec(FILE *fp,
- t_forcerec *fr,
- t_fcdata *fcd,
- const t_inputrec *ir,
- const gmx_mtop_t *mtop,
- const t_commrec *cr,
- matrix box,
- const char *tabfn,
- const char *tabpfn,
- const char *tabbfn,
- const char *nbpu_opt,
- gmx_bool bNoSolvOpt,
- real print_force)
+void init_forcerec(FILE *fp,
+ const gmx::MDLogger &mdlog,
+ t_forcerec *fr,
+ t_fcdata *fcd,
+ const t_inputrec *ir,
+ const gmx_mtop_t *mtop,
+ const t_commrec *cr,
+ matrix box,
+ const char *tabfn,
+ const char *tabpfn,
+ const char *tabbfn,
+ const char *nbpu_opt,
+ gmx_bool bNoSolvOpt,
+ real print_force)
{
int i, m, negp_pp, negptable, egi, egj;
real rtab;
* In mdrun, hwinfo has already been set before calling init_forcerec.
* Here we ignore GPUs, as tools will not use them anyhow.
*/
- fr->hwinfo = gmx_detect_hardware(fp, cr, FALSE);
+ fr->hwinfo = gmx_detect_hardware(mdlog, cr, FALSE);
}
/* By default we turn SIMD kernels on, but it might be turned off further down... */
{
/* turn off non-bonded calculations */
fr->bNonbonded = FALSE;
- md_print_warn(cr, fp,
- "Found environment variable GMX_NO_NONBONDED.\n"
- "Disabling nonbonded calculations.\n");
+ GMX_LOG(mdlog.warning).asParagraph().appendText(
+ "Found environment variable GMX_NO_NONBONDED.\n"
+ "Disabling nonbonded calculations.");
}
bGenericKernelOnly = FALSE;
fr->bMolPBC = FALSE;
if (fp)
{
- md_print_warn(cr, fp, "GMX_USE_GRAPH is set, using the graph for bonded interactions\n");
+ GMX_LOG(mdlog.warning).asParagraph().appendText("GMX_USE_GRAPH is set, using the graph for bonded interactions");
}
if (mtop->bIntermolecularInteractions)
{
- md_print_warn(cr, fp, "WARNING: Molecules linked by intermolecular interactions have to reside in the same periodic image, otherwise artifacts will occur!\n");
+ GMX_LOG(mdlog.warning).asParagraph().appendText("WARNING: Molecules linked by intermolecular interactions have to reside in the same periodic image, otherwise artifacts will occur!");
}
}
GMX_RELEASE_ASSERT(ir->rcoulomb == ir->rvdw, "With Verlet lists and no PME rcoulomb and rvdw should be identical");
}
- init_nb_verlet(fp, &fr->nbv, bFEP_NonBonded, ir, fr, cr, nbpu_opt);
+ init_nb_verlet(fp, mdlog, &fr->nbv, bFEP_NonBonded, ir, fr, cr, nbpu_opt);
}
if (ir->eDispCorr != edispcNO)
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct t_commrec;
struct t_fcdata;
+namespace gmx
+{
+class MDLogger;
+}
+
/*! \brief Create a new forcerec structure */
t_forcerec *mk_forcerec(void);
*
* The Force rec struct must be created with mk_forcerec.
* \param[in] fplog File for printing
+ * \param[in] mdlog File for printing
* \param[out] fr The forcerec
* \param[in] fcd Force constant data
* \param[in] ir Inputrec structure
* \param[in] print_force Print forces for atoms with force >= print_force
*/
void init_forcerec(FILE *fplog,
+ const gmx::MDLogger &mdlog,
t_forcerec *fr,
t_fcdata *fcd,
const t_inputrec *ir,
#include <cstdlib>
#include <cstring>
-#include "gromacs/gmxlib/md_logging.h"
#include "gromacs/gmxlib/network.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/utility/cstringutil.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/gmxomp.h"
+#include "gromacs/utility/logger.h"
#include "gromacs/utility/programcontext.h"
/** Structure with the number of threads for each OpenMP multi-threaded
* The "group" scheme supports OpenMP only in PME and in thise case all but
* the PME nthread values default to 1.
*/
-static void pick_module_nthreads(FILE *fplog, int m,
- gmx_bool bSimMaster,
+static void pick_module_nthreads(const gmx::MDLogger &mdlog, int m,
gmx_bool bFullOmpSupport,
gmx_bool bSepPME)
{
char *env;
int nth;
- char sbuf[STRLEN];
const bool bOMP = GMX_OPENMP;
/* only babble if we are really overriding with a different value */
if ((bSepPME && m == emntPME && nth != modth.gnth_pme) || (nth != modth.gnth))
{
- sprintf(sbuf, "%s=%d set, overriding the default number of %s threads",
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "%s=%d set, overriding the default number of %s threads",
modth_env_var[m], nth, mod_name[m]);
- if (bSimMaster)
- {
- fprintf(stderr, "\n%s\n", sbuf);
- }
- if (fplog)
- {
- fprintf(fplog, "%s\n", sbuf);
- }
}
}
else
/*! \brief Helper function for parsing various input about the number
of OpenMP threads to use in various modules and deciding what to
do about it. */
-static void manage_number_of_openmp_threads(FILE *fplog,
- const t_commrec *cr,
- bool bOMP,
- int nthreads_hw_avail,
- int omp_nthreads_req,
- int omp_nthreads_pme_req,
- gmx_bool gmx_unused bThisNodePMEOnly,
- gmx_bool bFullOmpSupport,
- int nppn,
- gmx_bool bSepPME)
+static void manage_number_of_openmp_threads(const gmx::MDLogger &mdlog,
+ const t_commrec *cr,
+ bool bOMP,
+ int nthreads_hw_avail,
+ int omp_nthreads_req,
+ int omp_nthreads_pme_req,
+ gmx_bool gmx_unused bThisNodePMEOnly,
+ gmx_bool bFullOmpSupport,
+ int nppn,
+ gmx_bool bSepPME)
{
int nth;
char *env;
{
return;
}
+#else
+ GMX_UNUSED_VALUE(cr);
#endif
if (modth.initialized)
/* now set the per-module values */
modth.nth[emntDefault] = modth.gnth;
- pick_module_nthreads(fplog, emntDomdec, SIMMASTER(cr), bFullOmpSupport, bSepPME);
- pick_module_nthreads(fplog, emntPairsearch, SIMMASTER(cr), bFullOmpSupport, bSepPME);
- pick_module_nthreads(fplog, emntNonbonded, SIMMASTER(cr), bFullOmpSupport, bSepPME);
- pick_module_nthreads(fplog, emntBonded, SIMMASTER(cr), bFullOmpSupport, bSepPME);
- pick_module_nthreads(fplog, emntPME, SIMMASTER(cr), bFullOmpSupport, bSepPME);
- pick_module_nthreads(fplog, emntUpdate, SIMMASTER(cr), bFullOmpSupport, bSepPME);
- pick_module_nthreads(fplog, emntVSITE, SIMMASTER(cr), bFullOmpSupport, bSepPME);
- pick_module_nthreads(fplog, emntLINCS, SIMMASTER(cr), bFullOmpSupport, bSepPME);
- pick_module_nthreads(fplog, emntSETTLE, SIMMASTER(cr), bFullOmpSupport, bSepPME);
+ pick_module_nthreads(mdlog, emntDomdec, bFullOmpSupport, bSepPME);
+ pick_module_nthreads(mdlog, emntPairsearch, bFullOmpSupport, bSepPME);
+ pick_module_nthreads(mdlog, emntNonbonded, bFullOmpSupport, bSepPME);
+ pick_module_nthreads(mdlog, emntBonded, bFullOmpSupport, bSepPME);
+ pick_module_nthreads(mdlog, emntPME, bFullOmpSupport, bSepPME);
+ pick_module_nthreads(mdlog, emntUpdate, bFullOmpSupport, bSepPME);
+ pick_module_nthreads(mdlog, emntVSITE, bFullOmpSupport, bSepPME);
+ pick_module_nthreads(mdlog, emntLINCS, bFullOmpSupport, bSepPME);
+ pick_module_nthreads(mdlog, emntSETTLE, bFullOmpSupport, bSepPME);
/* set the number of threads globally */
if (bOMP)
/*! \brief Report on the OpenMP settings that will be used */
static void
-reportOpenmpSettings(FILE *fplog,
- const t_commrec *cr,
- gmx_bool bOMP,
- gmx_bool bFullOmpSupport,
- gmx_bool bSepPME)
+reportOpenmpSettings(const gmx::MDLogger &mdlog,
+ const t_commrec *cr,
+ gmx_bool bOMP,
+ gmx_bool bFullOmpSupport,
+ gmx_bool bSepPME)
{
#if GMX_THREAD_MPI
const char *mpi_str = "per tMPI thread";
{
if (nth_max == nth_min)
{
- md_print_info(cr, fplog, "Using %d OpenMP thread%s %s\n",
- nth_min, nth_min > 1 ? "s" : "",
- cr->nnodes > 1 ? mpi_str : "");
+ GMX_LOG(mdlog.warning).appendTextFormatted(
+ "Using %d OpenMP thread%s %s",
+ nth_min, nth_min > 1 ? "s" : "",
+ cr->nnodes > 1 ? mpi_str : "");
}
else
{
- md_print_info(cr, fplog, "Using %d - %d OpenMP threads %s\n",
- nth_min, nth_max, mpi_str);
+ GMX_LOG(mdlog.warning).appendTextFormatted(
+ "Using %d - %d OpenMP threads %s",
+ nth_min, nth_max, mpi_str);
}
}
if (bSepPME && (nth_pme_min != nth_min || nth_pme_max != nth_max))
{
if (nth_pme_max == nth_pme_min)
{
- md_print_info(cr, fplog, "Using %d OpenMP thread%s %s for PME\n",
- nth_pme_min, nth_pme_min > 1 ? "s" : "",
- cr->nnodes > 1 ? mpi_str : "");
+ GMX_LOG(mdlog.warning).appendTextFormatted(
+ "Using %d OpenMP thread%s %s for PME",
+ nth_pme_min, nth_pme_min > 1 ? "s" : "",
+ cr->nnodes > 1 ? mpi_str : "");
}
else
{
- md_print_info(cr, fplog, "Using %d - %d OpenMP threads %s for PME\n",
- nth_pme_min, nth_pme_max, mpi_str);
+ GMX_LOG(mdlog.warning).appendTextFormatted(
+ "Using %d - %d OpenMP threads %s for PME",
+ nth_pme_min, nth_pme_max, mpi_str);
}
}
- md_print_info(cr, fplog, "\n");
+ GMX_LOG(mdlog.warning);
}
/*! \brief Detect and warn about oversubscription of cores.
*
* \todo Enable this for separate PME nodes as well! */
static void
-issueOversubscriptionWarning(FILE *fplog,
- const t_commrec *cr,
- int nthreads_hw_avail,
- int nppn,
- gmx_bool bSepPME)
+issueOversubscriptionWarning(const gmx::MDLogger &mdlog,
+ const t_commrec *cr,
+ int nthreads_hw_avail,
+ int nppn,
+ gmx_bool bSepPME)
{
char sbuf[STRLEN], sbuf1[STRLEN], sbuf2[STRLEN];
#endif
}
#endif
- md_print_warn(cr, fplog,
- "WARNING: %sversubscribing the available %d logical CPU cores%s with %d %s.\n"
- " This will cause considerable performance loss!",
- sbuf2, nthreads_hw_avail, sbuf1, nppn*modth.gnth, sbuf);
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "WARNING: %sversubscribing the available %d logical CPU cores%s with %d %s.\n"
+ " This will cause considerable performance loss!",
+ sbuf2, nthreads_hw_avail, sbuf1, nppn*modth.gnth, sbuf);
}
}
-void gmx_omp_nthreads_init(FILE *fplog, t_commrec *cr,
+void gmx_omp_nthreads_init(const gmx::MDLogger &mdlog, t_commrec *cr,
int nthreads_hw_avail,
int omp_nthreads_req,
int omp_nthreads_pme_req,
bSepPME = ( (cr->duty & DUTY_PP) && !(cr->duty & DUTY_PME)) ||
(!(cr->duty & DUTY_PP) && (cr->duty & DUTY_PME));
- manage_number_of_openmp_threads(fplog, cr, bOMP,
+ manage_number_of_openmp_threads(mdlog, cr, bOMP,
nthreads_hw_avail,
omp_nthreads_req, omp_nthreads_pme_req,
bThisNodePMEOnly, bFullOmpSupport,
}
#endif
- reportOpenmpSettings(fplog, cr, bOMP, bFullOmpSupport, bSepPME);
- issueOversubscriptionWarning(fplog, cr, nthreads_hw_avail, nppn, bSepPME);
+ reportOpenmpSettings(mdlog, cr, bOMP, bFullOmpSupport, bSepPME);
+ issueOversubscriptionWarning(mdlog, cr, nthreads_hw_avail, nppn, bSepPME);
}
int gmx_omp_nthreads_get(int mod)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct t_commrec;
+namespace gmx
+{
+class MDLogger;
+}
+
/** Enum values corresponding to multithreaded algorithmic modules. */
typedef enum module_nth
{
* It is compatible with tMPI, thread-safety is ensured (for the features
* available with tMPI).
* This function should caled only once during the initialization of mdrun. */
-void gmx_omp_nthreads_init(FILE *fplog, t_commrec *cr,
+void gmx_omp_nthreads_init(const gmx::MDLogger &fplog, t_commrec *cr,
int nthreads_hw_avail,
int omp_nthreads_req,
int omp_nthreads_pme_req,
namespace gmx
{
+
+class MDLogger;
+
/*! \brief Integrator algorithm implementation.
*
* \param[in] fplog Log file for output
* \param[in] cr Communication record
+ * \param[in] mdlog Log writer for important output
* \param[in] nfile Number of files
* \param[in] fnm Filename structure array
* \param[in] oenv Output information
* \param[in] Flags Flags to control mdrun
* \param[in] walltime_accounting More timing information
*/
-typedef double integrator_t (FILE *fplog, t_commrec *cr,
+typedef double integrator_t (FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
int nfile, const t_filenm fnm[],
const gmx_output_env_t *oenv, gmx_bool bVerbose,
int nstglobalcomm,
#include <algorithm>
#include "gromacs/domdec/domdec.h"
-#include "gromacs/gmxlib/md_logging.h"
#include "gromacs/gmxlib/network.h"
#include "gromacs/gmxlib/nrnb.h"
#include "gromacs/math/vec.h"
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/cstringutil.h"
#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/logger.h"
#include "gromacs/utility/smalloc.h"
#include "gromacs/utility/snprintf.h"
}
}
-void check_nst_param(FILE *fplog, t_commrec *cr,
- const char *desc_nst, int nst,
- const char *desc_p, int *p)
+/* check whether an 'nst'-style parameter p is a multiple of nst, and
+ set it to be one if not, with a warning. */
+static void check_nst_param(const gmx::MDLogger &mdlog,
+ const char *desc_nst, int nst,
+ const char *desc_p, int *p)
{
if (*p > 0 && *p % nst != 0)
{
/* Round up to the next multiple of nst */
*p = ((*p)/nst + 1)*nst;
- md_print_warn(cr, fplog,
- "NOTE: %s changes %s to %d\n", desc_nst, desc_p, *p);
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "NOTE: %s changes %s to %d", desc_nst, desc_p, *p);
}
}
return nst;
}
-int check_nstglobalcomm(FILE *fplog, t_commrec *cr,
- int nstglobalcomm, t_inputrec *ir)
+int check_nstglobalcomm(const gmx::MDLogger &mdlog, int nstglobalcomm, t_inputrec *ir)
{
if (!EI_DYNAMICS(ir->eI))
{
nstglobalcomm > ir->nstlist && nstglobalcomm % ir->nstlist != 0)
{
nstglobalcomm = (nstglobalcomm / ir->nstlist)*ir->nstlist;
- md_print_warn(cr, fplog, "WARNING: nstglobalcomm is larger than nstlist, but not a multiple, setting it to %d\n", nstglobalcomm);
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "WARNING: nstglobalcomm is larger than nstlist, but not a multiple, setting it to %d",
+ nstglobalcomm);
}
if (ir->nstcalcenergy > 0)
{
- check_nst_param(fplog, cr, "-gcom", nstglobalcomm,
+ check_nst_param(mdlog, "-gcom", nstglobalcomm,
"nstcalcenergy", &ir->nstcalcenergy);
}
if (ir->etc != etcNO && ir->nsttcouple > 0)
{
- check_nst_param(fplog, cr, "-gcom", nstglobalcomm,
+ check_nst_param(mdlog, "-gcom", nstglobalcomm,
"nsttcouple", &ir->nsttcouple);
}
if (ir->epc != epcNO && ir->nstpcouple > 0)
{
- check_nst_param(fplog, cr, "-gcom", nstglobalcomm,
+ check_nst_param(mdlog, "-gcom", nstglobalcomm,
"nstpcouple", &ir->nstpcouple);
}
- check_nst_param(fplog, cr, "-gcom", nstglobalcomm,
+ check_nst_param(mdlog, "-gcom", nstglobalcomm,
"nstenergy", &ir->nstenergy);
- check_nst_param(fplog, cr, "-gcom", nstglobalcomm,
+ check_nst_param(mdlog, "-gcom", nstglobalcomm,
"nstlog", &ir->nstlog);
}
if (ir->comm_mode != ecmNO && ir->nstcomm < nstglobalcomm)
{
- md_print_warn(cr, fplog, "WARNING: Changing nstcomm from %d to %d\n",
- ir->nstcomm, nstglobalcomm);
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "WARNING: Changing nstcomm from %d to %d",
+ ir->nstcomm, nstglobalcomm);
ir->nstcomm = nstglobalcomm;
}
struct t_state;
struct t_trxframe;
+namespace gmx
+{
+class MDLogger;
+}
+
/* Define a number of flags to better control the information
* passed to compute_globals in md.c and global_stat.
*/
/* return the number of steps between global communcations */
-int check_nstglobalcomm(FILE *fplog, t_commrec *cr,
- int nstglobalcomm, t_inputrec *ir);
-
-/* check whether an 'nst'-style parameter p is a multiple of nst, and
- set it to be one if not, with a warning. */
-void check_nst_param(FILE *fplog, t_commrec *cr,
- const char *desc_nst, int nst,
- const char *desc_p, int *p);
+int check_nstglobalcomm(const gmx::MDLogger &mdlog, int nstglobalcomm, t_inputrec *ir);
/* check which of the multisim simulations has the shortest number of
steps and return that number of nsteps */
#include "gromacs/ewald/pme.h"
#include "gromacs/fileio/confio.h"
#include "gromacs/fileio/mtxio.h"
-#include "gromacs/gmxlib/md_logging.h"
#include "gromacs/gmxlib/network.h"
#include "gromacs/gmxlib/nrnb.h"
#include "gromacs/imd/imd.h"
#include "gromacs/utility/cstringutil.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/logger.h"
#include "gromacs/utility/smalloc.h"
//! Utility structure for manipulating states during EM
{
/*! \brief Do conjugate gradients minimization
- \copydoc integrator_t (FILE *fplog, t_commrec *cr,
- int nfile, const t_filenm fnm[],
- const gmx_output_env_t *oenv, gmx_bool bVerbose,
- int nstglobalcomm,
- gmx_vsite_t *vsite, gmx_constr_t constr,
- int stepout,
- t_inputrec *inputrec,
- gmx_mtop_t *top_global, t_fcdata *fcd,
- t_state *state_global,
- t_mdatoms *mdatoms,
- t_nrnb *nrnb, gmx_wallcycle_t wcycle,
- gmx_edsam_t ed,
- t_forcerec *fr,
- int repl_ex_nst, int repl_ex_nex, int repl_ex_seed,
- real cpt_period, real max_hours,
- int imdport,
- unsigned long Flags,
- gmx_walltime_accounting_t walltime_accounting)
+ \copydoc integrator_t(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
+ int nfile, const t_filenm fnm[],
+ const gmx_output_env_t *oenv, gmx_bool bVerbose,
+ int nstglobalcomm,
+ gmx_vsite_t *vsite, gmx_constr_t constr,
+ int stepout,
+ t_inputrec *inputrec,
+ gmx_mtop_t *top_global, t_fcdata *fcd,
+ t_state *state_global,
+ t_mdatoms *mdatoms,
+ t_nrnb *nrnb, gmx_wallcycle_t wcycle,
+ gmx_edsam_t ed,
+ t_forcerec *fr,
+ int repl_ex_nst, int repl_ex_nex, int repl_ex_seed,
+ real cpt_period, real max_hours,
+ int imdport,
+ unsigned long Flags,
+ gmx_walltime_accounting_t walltime_accounting)
*/
-double do_cg(FILE *fplog, t_commrec *cr,
+double do_cg(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
int nfile, const t_filenm fnm[],
const gmx_output_env_t gmx_unused *oenv, gmx_bool bVerbose,
int gmx_unused nstglobalcomm,
/*! \brief Do L-BFGS conjugate gradients minimization
- \copydoc integrator_t (FILE *fplog, t_commrec *cr,
- int nfile, const t_filenm fnm[],
- const gmx_output_env_t *oenv, gmx_bool bVerbose,
- int nstglobalcomm,
- gmx_vsite_t *vsite, gmx_constr_t constr,
- int stepout,
- t_inputrec *inputrec,
- gmx_mtop_t *top_global, t_fcdata *fcd,
- t_state *state_global,
- t_mdatoms *mdatoms,
- t_nrnb *nrnb, gmx_wallcycle_t wcycle,
- gmx_edsam_t ed,
- t_forcerec *fr,
- int repl_ex_nst, int repl_ex_nex, int repl_ex_seed,
- real cpt_period, real max_hours,
- int imdport,
- unsigned long Flags,
- gmx_walltime_accounting_t walltime_accounting)
+ \copydoc integrator_t(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
+ int nfile, const t_filenm fnm[],
+ const gmx_output_env_t *oenv, gmx_bool bVerbose,
+ int nstglobalcomm,
+ gmx_vsite_t *vsite, gmx_constr_t constr,
+ int stepout,
+ t_inputrec *inputrec,
+ gmx_mtop_t *top_global, t_fcdata *fcd,
+ t_state *state_global,
+ t_mdatoms *mdatoms,
+ t_nrnb *nrnb, gmx_wallcycle_t wcycle,
+ gmx_edsam_t ed,
+ t_forcerec *fr,
+ int repl_ex_nst, int repl_ex_nex, int repl_ex_seed,
+ real cpt_period, real max_hours,
+ int imdport,
+ unsigned long Flags,
+ gmx_walltime_accounting_t walltime_accounting)
*/
-double do_lbfgs(FILE *fplog, t_commrec *cr,
+double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
int nfile, const t_filenm fnm[],
const gmx_output_env_t gmx_unused *oenv, gmx_bool bVerbose,
int gmx_unused nstglobalcomm,
} /* That's all folks */
/*! \brief Do steepest descents minimization
- \copydoc integrator_t (FILE *fplog, t_commrec *cr,
- int nfile, const t_filenm fnm[],
- const gmx_output_env_t *oenv, gmx_bool bVerbose,
- int nstglobalcomm,
- gmx_vsite_t *vsite, gmx_constr_t constr,
- int stepout,
- t_inputrec *inputrec,
- gmx_mtop_t *top_global, t_fcdata *fcd,
- t_state *state_global,
- t_mdatoms *mdatoms,
- t_nrnb *nrnb, gmx_wallcycle_t wcycle,
- gmx_edsam_t ed,
- t_forcerec *fr,
- int repl_ex_nst, int repl_ex_nex, int repl_ex_seed,
- real cpt_period, real max_hours,
- int imdport,
- unsigned long Flags,
- gmx_walltime_accounting_t walltime_accounting)
+ \copydoc integrator_t(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
+ int nfile, const t_filenm fnm[],
+ const gmx_output_env_t *oenv, gmx_bool bVerbose,
+ int nstglobalcomm,
+ gmx_vsite_t *vsite, gmx_constr_t constr,
+ int stepout,
+ t_inputrec *inputrec,
+ gmx_mtop_t *top_global, t_fcdata *fcd,
+ t_state *state_global,
+ t_mdatoms *mdatoms,
+ t_nrnb *nrnb, gmx_wallcycle_t wcycle,
+ gmx_edsam_t ed,
+ t_forcerec *fr,
+ int repl_ex_nst, int repl_ex_nex, int repl_ex_seed,
+ real cpt_period, real max_hours,
+ int imdport,
+ unsigned long Flags,
+ gmx_walltime_accounting_t walltime_accounting)
*/
-double do_steep(FILE *fplog, t_commrec *cr,
+double do_steep(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
int nfile, const t_filenm fnm[],
const gmx_output_env_t gmx_unused *oenv, gmx_bool bVerbose,
int gmx_unused nstglobalcomm,
} /* That's all folks */
/*! \brief Do normal modes analysis
- \copydoc integrator_t (FILE *fplog, t_commrec *cr,
- int nfile, const t_filenm fnm[],
- const gmx_output_env_t *oenv, gmx_bool bVerbose,
- int nstglobalcomm,
- gmx_vsite_t *vsite, gmx_constr_t constr,
- int stepout,
- t_inputrec *inputrec,
- gmx_mtop_t *top_global, t_fcdata *fcd,
- t_state *state_global,
- t_mdatoms *mdatoms,
- t_nrnb *nrnb, gmx_wallcycle_t wcycle,
- gmx_edsam_t ed,
- t_forcerec *fr,
- int repl_ex_nst, int repl_ex_nex, int repl_ex_seed,
- real cpt_period, real max_hours,
- int imdport,
- unsigned long Flags,
- gmx_walltime_accounting_t walltime_accounting)
+ \copydoc integrator_t(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
+ int nfile, const t_filenm fnm[],
+ const gmx_output_env_t *oenv, gmx_bool bVerbose,
+ int nstglobalcomm,
+ gmx_vsite_t *vsite, gmx_constr_t constr,
+ int stepout,
+ t_inputrec *inputrec,
+ gmx_mtop_t *top_global, t_fcdata *fcd,
+ t_state *state_global,
+ t_mdatoms *mdatoms,
+ t_nrnb *nrnb, gmx_wallcycle_t wcycle,
+ gmx_edsam_t ed,
+ t_forcerec *fr,
+ int repl_ex_nst, int repl_ex_nex, int repl_ex_seed,
+ real cpt_period, real max_hours,
+ int imdport,
+ unsigned long Flags,
+ gmx_walltime_accounting_t walltime_accounting)
*/
-double do_nm(FILE *fplog, t_commrec *cr,
+double do_nm(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
int nfile, const t_filenm fnm[],
const gmx_output_env_t gmx_unused *oenv, gmx_bool bVerbose,
int gmx_unused nstglobalcomm,
*/
if (EEL_FULL(fr->eeltype) || fr->rlist == 0.0)
{
- md_print_info(cr, fplog, "Non-cutoff electrostatics used, forcing full Hessian format.\n");
+ GMX_LOG(mdlog.warning).appendText("Non-cutoff electrostatics used, forcing full Hessian format.");
bSparse = FALSE;
}
else if (atom_index.size() < 1000)
{
- md_print_info(cr, fplog, "Small system size (N=%d), using full Hessian format.\n", atom_index.size());
+ GMX_LOG(mdlog.warning).appendTextFormatted("Small system size (N=%d), using full Hessian format.",
+ atom_index.size());
bSparse = FALSE;
}
else
{
- md_print_info(cr, fplog, "Using compressed symmetric sparse Hessian format.\n");
+ GMX_LOG(mdlog.warning).appendText("Using compressed symmetric sparse Hessian format.");
bSparse = TRUE;
}
/* if forces are not small, warn user */
get_state_f_norm_max(cr, &(inputrec->opts), mdatoms, state_work);
- md_print_info(cr, fplog, "Maximum force:%12.5e\n", state_work->fmax);
+ GMX_LOG(mdlog.warning).appendTextFormatted("Maximum force:%12.5e", state_work->fmax);
if (state_work->fmax > 1.0e-3)
{
- md_print_info(cr, fplog,
- "The force is probably not small enough to "
- "ensure that you are at a minimum.\n"
- "Be aware that negative eigenvalues may occur\n"
- "when the resulting matrix is diagonalized.\n\n");
+ GMX_LOG(mdlog.warning).appendText(
+ "The force is probably not small enough to "
+ "ensure that you are at a minimum.\n"
+ "Be aware that negative eigenvalues may occur\n"
+ "when the resulting matrix is diagonalized.");
}
/***********************************************************
}
// TODO This can be cleaned up a lot, and move back to runner.cpp
-void finish_run(FILE *fplog, t_commrec *cr,
+void finish_run(FILE *fplog, const gmx::MDLogger &mdlog, t_commrec *cr,
t_inputrec *inputrec,
t_nrnb nrnb[], gmx_wallcycle_t wcycle,
gmx_walltime_accounting_t walltime_accounting,
{
struct gmx_wallclock_gpu_t* gputimes = use_GPU(nbv) ? nbnxn_gpu_get_timings(nbv->gpu_nbv) : NULL;
- wallcycle_print(fplog, cr->nnodes, cr->npmenodes, nthreads_pp, nthreads_pme,
+ wallcycle_print(fplog, mdlog, cr->nnodes, cr->npmenodes, nthreads_pp, nthreads_pme,
elapsed_time_over_all_ranks,
wcycle, cycle_sum, gputimes);
struct t_mdatoms;
struct t_nrnb;
+namespace gmx
+{
+class MDLogger;
+}
+
typedef struct gmx_global_stat *gmx_global_stat_t;
void do_pbc_first(FILE *log, matrix box, t_forcerec *fr,
gmx_walltime_accounting_t walltime_accounting,
const char *name);
-void finish_run(FILE *log, t_commrec *cr,
+void finish_run(FILE *log, const gmx::MDLogger &mdlog, t_commrec *cr,
t_inputrec *inputrec,
t_nrnb nrnb[], gmx_wallcycle_t wcycle,
gmx_walltime_accounting_t walltime_accounting,
{
/*! \brief Do test particle insertion.
- \copydoc integrator_t (FILE *fplog, t_commrec *cr,
+ \copydoc integrator_t (FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
int nfile, const t_filenm fnm[],
const gmx_output_env_t *oenv, gmx_bool bVerbose,
int nstglobalcomm,
unsigned long Flags,
gmx_walltime_accounting_t walltime_accounting)
*/
-double do_tpi(FILE *fplog, t_commrec *cr,
+double do_tpi(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
int nfile, const t_filenm fnm[],
const gmx_output_env_t *oenv, gmx_bool bVerbose,
int gmx_unused nstglobalcomm,
#include "gromacs/hardware/hw_info.h"
#include "gromacs/mdrunutility/threadaffinity.h"
+#include "gromacs/utility/logger.h"
struct t_commrec;
{
setLogicalProcessorCount(1);
}
- gmx_set_thread_affinity(nullptr, cr_, hwOpt_, *hwTop_,
+ MDLogger mdlog;
+ gmx_set_thread_affinity(nullptr, mdlog, cr_, hwOpt_, *hwTop_,
nthread_local, &affinityAccess_);
}
#include "thread_mpi/threads.h"
-#include "gromacs/gmxlib/md_logging.h"
#include "gromacs/hardware/hardwaretopology.h"
#include "gromacs/hardware/hw_info.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/gmxomp.h"
+#include "gromacs/utility/logger.h"
#include "gromacs/utility/programcontext.h"
#include "gromacs/utility/scoped_cptr.h"
#include "gromacs/utility/smalloc.h"
}
static bool
-get_thread_affinity_layout(FILE *fplog,
+get_thread_affinity_layout(FILE *fplog, const gmx::MDLogger &mdlog,
const t_commrec *cr,
const gmx::HardwareTopology &hwTop,
int threads,
if (invalidWithinSimulation(cr, invalidValue))
{
/* We don't know anything about the hardware, don't pin */
- md_print_warn(cr, fplog,
- "NOTE: No information on available cores, thread pinning disabled.\n");
+ GMX_LOG(mdlog.warning).asParagraph().appendText(
+ "NOTE: No information on available cores, thread pinning disabled.");
alreadyWarned = true;
}
bool validLayout = !invalidValue;
bool warn = (invalidValue && threads > 1 && threads < hwThreads);
if (invalidWithinSimulation(cr, warn) && !alreadyWarned)
{
- md_print_warn(cr, fplog,
- "NOTE: The number of threads is not equal to the number of (logical) cores\n"
- " and the -pin option is set to auto: will not pin thread to cores.\n"
- " This can lead to significant performance degradation.\n"
- " Consider using -pin on (and -pinoffset in case you run multiple jobs).\n");
+ GMX_LOG(mdlog.warning).asParagraph().appendText(
+ "NOTE: The number of threads is not equal to the number of (logical) cores\n"
+ " and the -pin option is set to auto: will not pin thread to cores.\n"
+ " This can lead to significant performance degradation.\n"
+ " Consider using -pin on (and -pinoffset in case you run multiple jobs).");
alreadyWarned = true;
}
validLayout = validLayout && !invalidValue;
invalidValue = (threads > hwThreads);
if (invalidWithinSimulation(cr, invalidValue) && !alreadyWarned)
{
- md_print_warn(cr, fplog,
- "NOTE: Oversubscribing a CPU, will not pin threads.\n");
+ GMX_LOG(mdlog.warning).asParagraph().appendText(
+ "NOTE: Oversubscribing the CPU, will not pin threads");
alreadyWarned = true;
}
validLayout = validLayout && !invalidValue;
invalidValue = (pin_offset + threads > hwThreads);
if (invalidWithinSimulation(cr, invalidValue) && !alreadyWarned)
{
- md_print_warn(cr, fplog,
- "WARNING: Requested offset too large for available cores, thread pinning disabled.\n");
+ GMX_LOG(mdlog.warning).asParagraph().appendText(
+ "WARNING: Requested offset too large for available cores, thread pinning disabled.");
alreadyWarned = true;
}
if (invalidWithinSimulation(cr, invalidValue) && !alreadyWarned)
{
/* We are oversubscribing, don't pin */
- md_print_warn(cr, fplog,
- "WARNING: Requested stride too large for available cores, thread pinning disabled.\n");
+ GMX_LOG(mdlog.warning).asParagraph().appendText(
+ "WARNING: Requested stride too large for available cores, thread pinning disabled.");
}
validLayout = validLayout && !invalidValue;
*/
void
gmx_set_thread_affinity(FILE *fplog,
+ const gmx::MDLogger &mdlog,
const t_commrec *cr,
const gmx_hw_opt_t *hw_opt,
const gmx::HardwareTopology &hwTop,
no point in warning the user in that case. In any other case
the user might be able to do something about it. */
#if !defined(__APPLE__) && !defined(__bg__)
- md_print_warn(cr, fplog,
- "NOTE: Cannot set thread affinities on the current platform.\n");
+ GMX_LOG(mdlog.warning).asParagraph().appendText(
+ "NOTE: Cannot set thread affinities on the current platform.");
#endif /* __APPLE__ */
return;
}
int core_pinning_stride = hw_opt->core_pinning_stride;
if (offset != 0)
{
- md_print_info(cr, fplog, "Applying core pinning offset %d\n", offset);
+ GMX_LOG(mdlog.warning).appendTextFormatted("Applying core pinning offset %d", offset);
}
bool automatic = (hw_opt->thread_affinity == threadaffAUTO);
bool validLayout
- = get_thread_affinity_layout(fplog, cr, hwTop, nthread_node, automatic,
+ = get_thread_affinity_layout(fplog, mdlog, cr, hwTop, nthread_node, automatic,
offset, &core_pinning_stride, &localityOrder);
gmx::scoped_guard_sfree localityOrderGuard(localityOrder);
}
if (invalidWithinSimulation(cr, !allAffinitiesSet))
{
- md_print_warn(cr, fplog,
- "NOTE: Thread affinity setting failed. This can cause performance degradation.\n"
- " If you think your settings are correct, ask on the gmx-users list.\n");
+ GMX_LOG(mdlog.warning).asParagraph().appendText(
+ "NOTE: Thread affinity setting failed. This can cause performance degradation.\n"
+ " If you think your settings are correct, ask on the gmx-users list.");
}
}
* Note that this will only work on Linux as we use a GNU feature.
*/
void
-gmx_check_thread_affinity_set(FILE *fplog,
- const t_commrec *cr,
- gmx_hw_opt_t *hw_opt,
- int gmx_unused nthreads_hw_avail,
- gmx_bool bAfterOpenmpInit)
+gmx_check_thread_affinity_set(const gmx::MDLogger &mdlog,
+ const t_commrec *cr,
+ gmx_hw_opt_t *hw_opt,
+ int gmx_unused nthreads_hw_avail,
+ gmx_bool bAfterOpenmpInit)
{
GMX_RELEASE_ASSERT(hw_opt, "hw_opt must be a non-NULL pointer");
if (!gmx_omp_check_thread_affinity(&message))
{
/* TODO: with -pin auto we should only warn when using all cores */
- md_print_warn(cr, fplog, "%s", message);
+ GMX_LOG(mdlog.warning).asParagraph().appendText(message);
sfree(message);
hw_opt->thread_affinity = threadaffOFF;
}
{
if (!bAfterOpenmpInit)
{
- md_print_warn(cr, fplog,
- "Non-default thread affinity set, disabling internal thread affinity");
+ GMX_LOG(mdlog.warning).asParagraph().appendText(
+ "Non-default thread affinity set, disabling internal thread affinity");
}
else
{
- md_print_warn(cr, fplog,
- "Non-default thread affinity set probably by the OpenMP library,\n"
- "disabling internal thread affinity");
+ GMX_LOG(mdlog.warning).asParagraph().appendText(
+ "Non-default thread affinity set probably by the OpenMP library,\n"
+ "disabling internal thread affinity");
}
hw_opt->thread_affinity = threadaffOFF;
}
/* Only warn once, at the last check (bAfterOpenmpInit==TRUE) */
if (bAfterOpenmpInit)
{
- md_print_warn(cr, fplog,
- "Overriding thread affinity set outside %s\n",
- gmx::getProgramContext().displayName());
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "Overriding thread affinity set outside %s",
+ gmx::getProgramContext().displayName());
}
}
{
class HardwareTopology;
+class MDLogger;
class IThreadAffinityAccess
{
*/
void
gmx_set_thread_affinity(FILE *fplog,
+ const gmx::MDLogger &mdlog,
const t_commrec *cr,
const gmx_hw_opt_t *hw_opt,
const gmx::HardwareTopology &hwTop,
* variables for setting the affinity are set.
*/
void
-gmx_check_thread_affinity_set(FILE *fplog, const t_commrec *cr,
+gmx_check_thread_affinity_set(const gmx::MDLogger &mdlog, const t_commrec *cr,
gmx_hw_opt_t *hw_opt, int ncpus,
gmx_bool bAfterOpenmpInit);
#include <array>
-#include "gromacs/gmxlib/md_logging.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/timing/cyclecounter.h"
#include "gromacs/timing/gpu_timing.h"
#include "gromacs/utility/cstringutil.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/gmxmpi.h"
+#include "gromacs/utility/logger.h"
#include "gromacs/utility/smalloc.h"
#include "gromacs/utility/snprintf.h"
}
-void wallcycle_print(FILE *fplog, int nnodes, int npme,
+void wallcycle_print(FILE *fplog, const gmx::MDLogger &mdlog, int nnodes, int npme,
int nth_pp, int nth_pme, double realtime,
gmx_wallcycle_t wc, const WallcycleCounts &cyc_sum,
struct gmx_wallclock_gpu_t *gpu_t)
timing data might still be sensible for some non-Jenkins
run, than is lost from diagnosing Jenkins FP exceptions on
runs about whose execution time we don't care. */
- md_print_warn(NULL, fplog, "WARNING: A total of %f CPU cycles was recorded, so mdrun cannot print a time accounting\n", tot);
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "WARNING: A total of %f CPU cycles was recorded, so mdrun cannot print a time accounting",
+ tot);
return;
}
if (wc->haveInvalidCount)
{
- md_print_warn(NULL, fplog, "%s\n",
- "NOTE: Detected invalid cycle counts, probably because threads moved between CPU cores that do not have synchronized cycle counters. Will not print the cycle accounting.");
+ GMX_LOG(mdlog.warning).asParagraph().appendText("NOTE: Detected invalid cycle counts, probably because threads moved between CPU cores that do not have synchronized cycle counters. Will not print the cycle accounting.");
return;
}
/* The user could have used -notunepme,
* but we currently can't check that here.
*/
- md_print_warn(NULL, fplog,
- "\nNOTE: The GPU has >25%% less load than the CPU. This imbalance causes\n"
- " performance loss. Maybe the domain decomposition limits the PME tuning.\n"
- " In that case, try setting the DD grid manually (-dd) or lowering -dds.");
+ GMX_LOG(mdlog.warning).asParagraph().appendText(
+ "NOTE: The GPU has >25% less load than the CPU. This imbalance causes\n"
+ " performance loss. Maybe the domain decomposition limits the PME tuning.\n"
+ " In that case, try setting the DD grid manually (-dd) or lowering -dds.");
}
else
{
/* We should not end up here, unless the box is
* too small for increasing the cut-off for PME tuning.
*/
- md_print_warn(NULL, fplog,
- "\nNOTE: The GPU has >25%% less load than the CPU. This imbalance causes\n"
- " performance loss.");
+ GMX_LOG(mdlog.warning).asParagraph().appendText(
+ "NOTE: The GPU has >25% less load than the CPU. This imbalance causes\n"
+ " performance loss.");
}
}
if (gpu_cpu_ratio > 1.2)
{
- md_print_warn(NULL, fplog,
- "\nNOTE: The GPU has >20%% more load than the CPU. This imbalance causes\n"
- " performance loss, consider using a shorter cut-off and a finer PME grid.");
+ GMX_LOG(mdlog.warning).asParagraph().appendText(
+ "NOTE: The GPU has >20% more load than the CPU. This imbalance causes\n"
+ " performance loss, consider using a shorter cut-off and a finer PME grid.");
}
}
}
if (wc->wc_barrier)
{
- md_print_warn(NULL, fplog,
- "MPI_Barrier was called before each cycle start/stop\n"
- "call, so timings are not those of real runs.\n");
+ GMX_LOG(mdlog.warning).asParagraph().appendText(
+ "MPI_Barrier was called before each cycle start/stop\n"
+ "call, so timings are not those of real runs.");
}
if (wc->wcc[ewcNB_XF_BUF_OPS].n > 0 &&
/* Only the sim master calls this function, so always print to stderr */
if (wc->wcc[ewcDOMDEC].n == 0)
{
- md_print_warn(NULL, fplog,
- "NOTE: %d %% of the run time was spent in pair search,\n"
- " you might want to increase nstlist (this has no effect on accuracy)\n",
- (int)(100*cyc_sum[ewcNS]/tot+0.5));
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "NOTE: %d %% of the run time was spent in pair search,\n"
+ " you might want to increase nstlist (this has no effect on accuracy)\n",
+ (int)(100*cyc_sum[ewcNS]/tot+0.5));
}
else
{
- md_print_warn(NULL, fplog,
- "NOTE: %d %% of the run time was spent in domain decomposition,\n"
- " %d %% of the run time was spent in pair search,\n"
- " you might want to increase nstlist (this has no effect on accuracy)\n",
- (int)(100*cyc_sum[ewcDOMDEC]/tot+0.5),
- (int)(100*cyc_sum[ewcNS]/tot+0.5));
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "NOTE: %d %% of the run time was spent in domain decomposition,\n"
+ " %d %% of the run time was spent in pair search,\n"
+ " you might want to increase nstlist (this has no effect on accuracy)\n",
+ (int)(100*cyc_sum[ewcDOMDEC]/tot+0.5),
+ (int)(100*cyc_sum[ewcNS]/tot+0.5));
}
}
if (cyc_sum[ewcMoveE] > tot*0.05)
{
- /* Only the sim master calls this function, so always print to stderr */
- md_print_warn(NULL, fplog,
- "NOTE: %d %% of the run time was spent communicating energies,\n"
- " you might want to use the -gcom option of mdrun\n",
- (int)(100*cyc_sum[ewcMoveE]/tot+0.5));
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "NOTE: %d %% of the run time was spent communicating energies,\n"
+ " you might want to use the -gcom option of mdrun\n",
+ (int)(100*cyc_sum[ewcMoveE]/tot+0.5));
}
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2008, The GROMACS development team.
- * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/basedefinitions.h"
+struct t_commrec;
+
+namespace gmx
+{
+class MDLogger;
+}
+
typedef struct gmx_wallcycle *gmx_wallcycle_t;
typedef struct gmx_wallclock_gpu_t gmx_wallclock_gpu_t;
-struct t_commrec;
typedef std::array<double, ewcNR+ewcsNR> WallcycleCounts;
/* Convenience typedef */
/* Return a vector of the sum of cycle counts over the nodes in
cr->mpi_comm_mysim. */
-void wallcycle_print(FILE *fplog, int nnodes, int npme,
+void wallcycle_print(FILE *fplog, const gmx::MDLogger &mdlog, int nnodes, int npme,
int nth_pp, int nth_pme, double realtime,
gmx_wallcycle_t wc, const WallcycleCounts &cyc_sum,
struct gmx_wallclock_gpu_t *gpu_t);
entry_.text.append(text);
return *this;
}
+ //! Appends given text to the log entry.
+ LogEntryWriter &appendText(const std::string &text)
+ {
+ entry_.text.append(text);
+ return *this;
+ }
//! Appends given text to the log entry, with printf-style formatting.
LogEntryWriter &appendTextFormatted(const char *fmt, ...);
//! Writes the log entry with empty lines before and after.
//! Initializes a helper for writing to the given target.
explicit LogWriteHelper(ILogTarget *target) : target_(target) {}
+ // Should be explicit, once that works in CUDA.
/*! \brief
* Returns whether anything needs to be written.
*
* Note that the return value is unintuitively `false` when the target
* is active, to allow implementing ::GMX_LOG like it is now.
*/
- explicit operator bool() const { return target_ == NULL; }
+ operator bool() const { return target_ == NULL; }
/*! \brief
* Writes the entry from the given writer to the log target.
//! Initializes a helper for writing to the given target.
explicit LogLevelHelper(ILogTarget *target) : target_(target) {}
+ // Both of the below should be explicit, once that works in CUDA.
//! Returns whether the output for this log level goes anywhere.
- explicit operator bool() const { return target_ != NULL; }
+ operator bool() const { return target_ != NULL; }
//! Creates a helper for ::GMX_LOG.
- explicit operator LogWriteHelper() const { return LogWriteHelper(target_); }
+ operator LogWriteHelper() const { return LogWriteHelper(target_); }
private:
ILogTarget *target_;
{
public:
//! Supported logging levels.
- enum class LogLevel
+ enum LogLevel
{
Warning,
Info
};
//! Number of logging levels.
- static const int LogLevelCount = static_cast<int>(LogLevel::Info) + 1;
+ static const int LogLevelCount = static_cast<int>(Info) + 1;
MDLogger();
//! Creates a logger with the given targets.
#include "gromacs/ewald/pme.h"
#include "gromacs/ewald/pme-load-balancing.h"
#include "gromacs/fileio/trxio.h"
-#include "gromacs/gmxlib/md_logging.h"
#include "gromacs/gmxlib/network.h"
#include "gromacs/gmxlib/nrnb.h"
#include "gromacs/gpu_utils/gpu_utils.h"
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/cstringutil.h"
#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/logger.h"
#include "gromacs/utility/real.h"
#include "gromacs/utility/smalloc.h"
}
}
-static void reset_all_counters(FILE *fplog, t_commrec *cr,
+static void reset_all_counters(FILE *fplog, const gmx::MDLogger &mdlog, t_commrec *cr,
gmx_int64_t step,
gmx_int64_t *step_rel, t_inputrec *ir,
gmx_wallcycle_t wcycle, t_nrnb *nrnb,
char sbuf[STEPSTRSIZE];
/* Reset all the counters related to performance over the run */
- md_print_warn(cr, fplog, "step %s: resetting all time and cycle counters\n",
- gmx_step_str(step, sbuf));
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "step %s: resetting all time and cycle counters",
+ gmx_step_str(step, sbuf));
if (use_GPU(nbv))
{
}
/*! \libinternal
- \copydoc integrator_t (FILE *fplog, t_commrec *cr,
+ \copydoc integrator_t (FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
int nfile, const t_filenm fnm[],
const gmx_output_env_t *oenv, gmx_bool bVerbose,
int nstglobalcomm,
unsigned long Flags,
gmx_walltime_accounting_t walltime_accounting)
*/
-double gmx::do_md(FILE *fplog, t_commrec *cr, int nfile, const t_filenm fnm[],
+double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
+ int nfile, const t_filenm fnm[],
const gmx_output_env_t *oenv, gmx_bool bVerbose,
int nstglobalcomm,
gmx_vsite_t *vsite, gmx_constr_t constr,
nstglobalcomm = 1;
}
- nstglobalcomm = check_nstglobalcomm(fplog, cr, nstglobalcomm, ir);
+ nstglobalcomm = check_nstglobalcomm(mdlog, nstglobalcomm, ir);
bGStatEveryStep = (nstglobalcomm == 1);
if (bRerunMD)
!(Flags & MD_REPRODUCIBLE));
if (bPMETune)
{
- pme_loadbal_init(&pme_loadbal, cr, fplog, ir, state->box,
+ pme_loadbal_init(&pme_loadbal, cr, mdlog, ir, state->box,
fr->ic, fr->pmedata, use_GPU(fr->nbv),
&bPMETunePrinting);
}
/* PME grid + cut-off optimization with GPUs or PME nodes */
pme_loadbal_do(pme_loadbal, cr,
(bVerbose && MASTER(cr)) ? stderr : NULL,
- fplog,
+ fplog, mdlog,
ir, fr, state,
wcycle,
step, step_rel,
"resetting counters later in the run, e.g. with gmx "
"mdrun -resetstep.", step);
}
- reset_all_counters(fplog, cr, step, &step_rel, ir, wcycle, nrnb, walltime_accounting,
+ reset_all_counters(fplog, mdlog, cr, step, &step_rel, ir, wcycle, nrnb, walltime_accounting,
use_GPU(fr->nbv) ? fr->nbv : NULL);
wcycle_set_reset_counters(wcycle, -1);
if (!(cr->duty & DUTY_PME))
if (bPMETune)
{
- pme_loadbal_done(pme_loadbal, cr, fplog, use_GPU(fr->nbv));
+ pme_loadbal_done(pme_loadbal, fplog, mdlog, use_GPU(fr->nbv));
}
done_shellfc(fplog, shellfc, step_rel);
#include <algorithm>
-#include "gromacs/gmxlib/md_logging.h"
#include "gromacs/hardware/cpuinfo.h"
#include "gromacs/hardware/detecthardware.h"
#include "gromacs/hardware/gpu_hw_info.h"
#include "gromacs/topology/topology.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/gmxassert.h"
+#include "gromacs/utility/logger.h"
/* DISCLAIMER: All the atom count and thread numbers below are heuristic.
}
-static int getMaxGpuUsable(FILE *fplog, const t_commrec *cr, const gmx_hw_info_t *hwinfo,
+static int getMaxGpuUsable(const gmx::MDLogger &mdlog, const gmx_hw_info_t *hwinfo,
int cutoff_scheme, gmx_bool bUseGpu)
{
/* This code relies on the fact that GPU are not detected when GPU
{
if (hwinfo->gpu_info.n_dev_compatible > 1)
{
- md_print_warn(cr, fplog, "More than one compatible GPU is available, but GROMACS can only use one of them. Using a single thread-MPI rank.\n");
+ GMX_LOG(mdlog.warning).asParagraph().appendText("More than one compatible GPU is available, but GROMACS can only use one of them. Using a single thread-MPI rank.");
}
return 1;
}
gmx_hw_opt_t *hw_opt,
const t_inputrec *inputrec,
const gmx_mtop_t *mtop,
- const t_commrec *cr,
- FILE *fplog,
+ const gmx::MDLogger &mdlog,
gmx_bool bUseGpu)
{
int nthreads_hw, nthreads_tot_max, nrank, ngpu;
if (inputrec->eI == eiLBFGS ||
inputrec->coulombtype == eelEWALD)
{
- md_print_warn(cr, fplog, "The integration or electrostatics algorithm doesn't support parallel runs. Using a single thread-MPI rank.\n");
+ GMX_LOG(mdlog.warning).asParagraph().appendText("The integration or electrostatics algorithm doesn't support parallel runs. Using a single thread-MPI rank.");
if (hw_opt->nthreads_tmpi > 1)
{
gmx_fatal(FARGS, "You asked for more than 1 thread-MPI rank, but an algorithm doesn't support that");
nthreads_tot_max = nthreads_hw;
}
- ngpu = getMaxGpuUsable(fplog, cr, hwinfo, inputrec->cutoff_scheme, bUseGpu);
+ ngpu = getMaxGpuUsable(mdlog, hwinfo, inputrec->cutoff_scheme, bUseGpu);
if (inputrec->cutoff_scheme == ecutsGROUP)
{
const gmx_hw_opt_t *hw_opt,
gmx_bool bNtOmpOptionSet,
t_commrec *cr,
- FILE *fplog)
+ const gmx::MDLogger &mdlog)
{
#if GMX_OPENMP && GMX_MPI
int nth_omp_min, nth_omp_max, ngpu;
if (bNtOmpOptionSet)
{
- md_print_warn(cr, fplog, "NOTE: %s\n", buf);
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted("NOTE: %s", buf);
}
else
{
*/
if (bNtOmpOptionSet || (bEnvSet && nth_omp_min != nth_omp_max))
{
- md_print_warn(cr, fplog, "NOTE: %s\n", buf);
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted("NOTE: %s", buf);
}
else
{
#if !GMX_OPENMP && !GMX_MPI
if (hwinfo->hardwareTopology->numberOfCores() > 1)
{
- md_print_warn(cr, fplog, "NOTE: GROMACS was compiled without OpenMP and (thread-)MPI support, can only use a single CPU core\n");
+ GMX_LOG(*mdlog).asParagraph().appendText("NOTE: GROMACS was compiled without OpenMP and (thread-)MPI support, can only use a single CPU core");
}
#else
GMX_UNUSED_VALUE(hwinfo);
GMX_UNUSED_VALUE(cr);
- GMX_UNUSED_VALUE(fplog);
+ GMX_UNUSED_VALUE(mdlog);
#endif
#endif /* GMX_OPENMP && GMX_MPI */
struct t_commrec;
struct t_inputrec;
+namespace gmx
+{
+class MDLogger;
+}
+
/* Return the number of threads to use for thread-MPI based on how many
* were requested, which algorithms we're using,
* and how many particles there are.
gmx_hw_opt_t *hw_opt,
const t_inputrec *inputrec,
const gmx_mtop_t *mtop,
- const t_commrec *cr,
- FILE *fplog,
+ const gmx::MDLogger &mdlog,
gmx_bool bUseGpu);
/* Check if the number of OpenMP threads is within reasonable range
void check_resource_division_efficiency(const gmx_hw_info_t *hwinfo,
const gmx_hw_opt_t *hw_opt,
gmx_bool bNtOmpOptionSet,
- struct t_commrec *cr,
- FILE *fplog);
+ t_commrec *cr,
+ const gmx::MDLogger &mdlog);
/* Checks we can do when we don't (yet) know the cut-off scheme */
void check_and_update_hw_opt_1(gmx_hw_opt_t *hw_opt,
#include "gromacs/fileio/checkpoint.h"
#include "gromacs/fileio/oenv.h"
#include "gromacs/fileio/tpxio.h"
-#include "gromacs/gmxlib/md_logging.h"
#include "gromacs/gmxlib/network.h"
#include "gromacs/gpu_utils/gpu_utils.h"
#include "gromacs/hardware/cpuinfo.h"
#include "gromacs/utility/cstringutil.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/filestream.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/gmxmpi.h"
+#include "gromacs/utility/logger.h"
+#include "gromacs/utility/loggerbuilder.h"
#include "gromacs/utility/pleasecite.h"
#include "gromacs/utility/smalloc.h"
*
* with value passed on the command line (if any)
*/
-static void override_nsteps_cmdline(FILE *fplog,
- gmx_int64_t nsteps_cmdline,
- t_inputrec *ir,
- const t_commrec *cr)
+static void override_nsteps_cmdline(const gmx::MDLogger &mdlog,
+ gmx_int64_t nsteps_cmdline,
+ t_inputrec *ir)
{
assert(ir);
- assert(cr);
/* override with anything else than the default -2 */
if (nsteps_cmdline > -2)
gmx_step_str(nsteps_cmdline, sbuf_steps));
}
- md_print_warn(cr, fplog, "%s\n", sbuf_msg);
+ GMX_LOG(mdlog.warning).asParagraph().appendText(sbuf_msg);
}
else if (nsteps_cmdline < -2)
{
}
}
+//! Initializes the logger for mdrun.
+static gmx::LoggerOwner buildLogger(FILE *fplog, const t_commrec *cr)
+{
+ gmx::LoggerBuilder builder;
+ if (fplog != NULL)
+ {
+ builder.addTargetFile(gmx::MDLogger::LogLevel::Info, fplog);
+ }
+ if (cr == nullptr || SIMMASTER(cr))
+ {
+ builder.addTargetStream(gmx::MDLogger::LogLevel::Warning,
+ &gmx::TextOutputFile::standardError());
+ }
+ return builder.build();
+}
+
int mdrunner(gmx_hw_opt_t *hw_opt,
FILE *fplog, t_commrec *cr, int nfile,
const t_filenm fnm[], const gmx_output_env_t *oenv, gmx_bool bVerbose,
bForceUseGPU = (strncmp(nbpu_opt, "gpu", 3) == 0);
bTryUseGPU = (strncmp(nbpu_opt, "auto", 4) == 0) || bForceUseGPU;
+ // Here we assume that SIMMASTER(cr) does not change even after the
+ // threads are started.
+ gmx::LoggerOwner logOwner(buildLogger(fplog, cr));
+ gmx::MDLogger mdlog(logOwner.logger());
+
/* Detect hardware, gather information. This is an operation that is
* global for this process (MPI rank). */
- hwinfo = gmx_detect_hardware(fplog, cr, bTryUseGPU);
+ hwinfo = gmx_detect_hardware(mdlog, cr, bTryUseGPU);
- gmx_print_detected_hardware(fplog, cr, hwinfo);
+ gmx_print_detected_hardware(fplog, cr, mdlog, hwinfo);
if (fplog != NULL)
{
* update the message text and the content of nbnxn_acceleration_supported.
*/
if (bUseGPU &&
- !nbnxn_gpu_acceleration_supported(fplog, cr, inputrec, bRerunMD))
+ !nbnxn_gpu_acceleration_supported(mdlog, inputrec, bRerunMD))
{
/* Fallback message printed by nbnxn_acceleration_supported */
if (bForceUseGPU)
if (hwinfo->gpu_info.n_dev_compatible > 0)
{
- md_print_warn(cr, fplog,
- "NOTE: GPU(s) found, but the current simulation can not use GPUs\n"
- " To use a GPU, set the mdp option: cutoff-scheme = Verlet\n");
+ GMX_LOG(mdlog.warning).asParagraph().appendText(
+ "NOTE: GPU(s) found, but the current simulation can not use GPUs\n"
+ " To use a GPU, set the mdp option: cutoff-scheme = Verlet");
}
if (bForceUseGPU)
check_and_update_hw_opt_1(hw_opt, cr, npme);
/* Early check for externally set process affinity. */
- gmx_check_thread_affinity_set(fplog, cr,
+ gmx_check_thread_affinity_set(mdlog, cr,
hw_opt, hwinfo->nthreads_hw_avail, FALSE);
#if GMX_THREAD_MPI
hw_opt->nthreads_tmpi = get_nthreads_mpi(hwinfo,
hw_opt,
inputrec, mtop,
- cr, fplog, bUseGPU);
+ mdlog, bUseGPU);
if (hw_opt->nthreads_tmpi > 1)
{
}
}
- if (MASTER(cr) && (Flags & MD_APPENDFILES))
+ if (SIMMASTER(cr) && (Flags & MD_APPENDFILES))
{
gmx_log_open(ftp2fn(efLOG, nfile, fnm), cr,
Flags, &fplog);
+ logOwner = buildLogger(fplog, nullptr);
+ mdlog = logOwner.logger();
}
/* override nsteps with value from cmdline */
- override_nsteps_cmdline(fplog, nsteps_cmdline, inputrec, cr);
+ override_nsteps_cmdline(mdlog, nsteps_cmdline, inputrec);
if (SIMMASTER(cr))
{
#if GMX_MPI
if (MULTISIM(cr))
{
- md_print_info(cr, fplog,
- "This is simulation %d out of %d running as a composite GROMACS\n"
- "multi-simulation job. Setup for this simulation:\n\n",
- cr->ms->sim, cr->ms->nsim);
+ GMX_LOG(mdlog.warning).asParagraph().appendTextFormatted(
+ "This is simulation %d out of %d running as a composite GROMACS\n"
+ "multi-simulation job. Setup for this simulation:\n",
+ cr->ms->sim, cr->ms->nsim);
}
- md_print_info(cr, fplog, "Using %d MPI %s\n",
- cr->nnodes,
+ GMX_LOG(mdlog.warning).appendTextFormatted(
+ "Using %d MPI %s\n",
+ cr->nnodes,
#if GMX_THREAD_MPI
- cr->nnodes == 1 ? "thread" : "threads"
+ cr->nnodes == 1 ? "thread" : "threads"
#else
- cr->nnodes == 1 ? "process" : "processes"
+ cr->nnodes == 1 ? "process" : "processes"
#endif
- );
+ );
fflush(stderr);
#endif
/* Check and update hw_opt for the number of MPI ranks */
check_and_update_hw_opt_3(hw_opt);
- gmx_omp_nthreads_init(fplog, cr,
+ gmx_omp_nthreads_init(mdlog, cr,
hwinfo->nthreads_hw_avail,
hw_opt->nthreads_omp,
hw_opt->nthreads_omp_pme,
if (bUseGPU)
{
/* Select GPU id's to use */
- gmx_select_gpu_ids(fplog, cr, &hwinfo->gpu_info, bForceUseGPU,
+ gmx_select_gpu_ids(mdlog, cr, &hwinfo->gpu_info, bForceUseGPU,
&hw_opt->gpu_opt);
}
else
/* check consistency across ranks of things like SIMD
* support and number of GPUs selected */
- gmx_check_hw_runconf_consistency(fplog, hwinfo, cr, hw_opt, bUseGPU);
+ gmx_check_hw_runconf_consistency(mdlog, hwinfo, cr, hw_opt, bUseGPU);
/* Now that we know the setup is consistent, check for efficiency */
check_resource_division_efficiency(hwinfo, hw_opt, Flags & MD_NTOMPSET,
- cr, fplog);
+ cr, mdlog);
if (DOMAINDECOMP(cr))
{
fr = mk_forcerec();
fr->hwinfo = hwinfo;
fr->gpu_opt = &hw_opt->gpu_opt;
- init_forcerec(fplog, fr, fcd, inputrec, mtop, cr, box,
+ init_forcerec(fplog, mdlog, fr, fcd, inputrec, mtop, cr, box,
opt2fn("-table", nfile, fnm),
opt2fn("-tablep", nfile, fnm),
opt2fn("-tableb", nfile, fnm),
* - which indicates that probably the OpenMP library has changed it
* since we first checked).
*/
- gmx_check_thread_affinity_set(fplog, cr,
+ gmx_check_thread_affinity_set(mdlog, cr,
hw_opt, hwinfo->nthreads_hw_avail, TRUE);
int nthread_local;
}
/* Set the CPU affinity */
- gmx_set_thread_affinity(fplog, cr, hw_opt, *hwinfo->hardwareTopology,
+ gmx_set_thread_affinity(fplog, mdlog, cr, hw_opt, *hwinfo->hardwareTopology,
nthread_local, nullptr);
}
}
/* Now do whatever the user wants us to do (how flexible...) */
- my_integrator(inputrec->eI) (fplog, cr, nfile, fnm,
+ my_integrator(inputrec->eI) (fplog, cr, mdlog, nfile, fnm,
oenv, bVerbose,
nstglobalcomm,
vsite, constr,
/* Finish up, write some stuff
* if rerunMD, don't write last frame again
*/
- finish_run(fplog, cr,
+ finish_run(fplog, mdlog, cr,
inputrec, nrnb, wcycle, walltime_accounting,
fr ? fr->nbv : NULL,
EI_DYNAMICS(inputrec->eI) && !MULTISIM(cr));