static void print_gpu_detection_stats(FILE *fplog, const gmx_gpu_info_t *gpu_info, const t_commrec *cr) { char onhost[266], stmp[STRLEN]; int ngpu; if (!gpu_info->bDetectGPUs) { /* We skipped the detection, so don't print detection stats */ return; } ngpu = gpu_info->ncuda_dev; #if defined GMX_MPI && !defined GMX_THREAD_MPI /* We only print the detection on one, of possibly multiple, nodes */ strncpy(onhost, " on host ", 10); gmx_gethostname(onhost+9, 256); #else /* We detect all relevant GPUs */ strncpy(onhost, "", 1); #endif 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); } else { md_print_warn(cr, fplog, "No GPUs detected%s\n", onhost); } }
void gmx_log_open(const char *lognm, const t_commrec *cr, gmx_bool bAppendFiles, FILE** fplog) { int pid; char host[256]; char timebuf[STRLEN]; FILE *fp = *fplog; debug_gmx(); if (!bAppendFiles) { fp = gmx_fio_fopen(lognm, bAppendFiles ? "a+" : "w+" ); } gmx_fatal_set_log_file(fp); /* Get some machine parameters */ gmx_gethostname(host, 256); pid = gmx_getpid(); gmx_format_current_time(timebuf, STRLEN); if (bAppendFiles) { fprintf(fp, "\n" "\n" "-----------------------------------------------------------\n" "Restarting from checkpoint, appending to previous log file.\n" "\n" ); } fprintf(fp, "Log file opened on %s" "Host: %s pid: %d rank ID: %d number of ranks: %d\n", timebuf, host, pid, cr->nodeid, cr->nnodes); try { gmx::BinaryInformationSettings settings; settings.extendedInfo(true); settings.copyright(!bAppendFiles); gmx::printBinaryInformation(fp, gmx::getProgramContext(), settings); } GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR; fprintf(fp, "\n"); fflush(fp); debug_gmx(); *fplog = fp; }
void gmx_log_open(const char *lognm, const t_commrec *cr, gmx_bool bMasterOnly, gmx_bool bAppendFiles, FILE** fplog) { int len, pid; char buf[256], host[256]; time_t t; char timebuf[STRLEN]; FILE *fp = *fplog; char *tmpnm; debug_gmx(); /* Communicate the filename for logfile */ if (cr->nnodes > 1 && !bMasterOnly #ifdef GMX_THREAD_MPI /* With thread MPI the non-master log files are opened later * when the files names are already known on all nodes. */ && FALSE #endif ) { if (MASTER(cr)) { len = strlen(lognm) + 1; } gmx_bcast(sizeof(len), &len, cr); if (!MASTER(cr)) { snew(tmpnm, len+8); } else { tmpnm = gmx_strdup(lognm); } gmx_bcast(len*sizeof(*tmpnm), tmpnm, cr); } else { tmpnm = gmx_strdup(lognm); } debug_gmx(); if (!bMasterOnly && !MASTER(cr)) { /* Since log always ends with '.log' let's use this info */ par_fn(tmpnm, efLOG, cr, FALSE, !bMasterOnly, buf, 255); fp = gmx_fio_fopen(buf, bAppendFiles ? "a+" : "w+" ); } else if (!bAppendFiles) { fp = gmx_fio_fopen(tmpnm, bAppendFiles ? "a+" : "w+" ); } sfree(tmpnm); gmx_fatal_set_log_file(fp); /* Get some machine parameters */ gmx_gethostname(host, 256); time(&t); #ifndef NO_GETPID # ifdef GMX_NATIVE_WINDOWS pid = _getpid(); # else pid = getpid(); # endif #else pid = 0; #endif if (bAppendFiles) { fprintf(fp, "\n" "\n" "-----------------------------------------------------------\n" "Restarting from checkpoint, appending to previous log file.\n" "\n" ); } gmx_ctime_r(&t, timebuf, STRLEN); fprintf(fp, "Log file opened on %s" "Host: %s pid: %d rank ID: %d number of ranks: %d\n", timebuf, host, pid, cr->nodeid, cr->nnodes); try { gmx::BinaryInformationSettings settings; settings.extendedInfo(true); settings.copyright(!bAppendFiles); gmx::printBinaryInformation(fp, gmx::getProgramContext(), settings); } GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR; fprintf(fp, "\n\n"); fflush(fp); debug_gmx(); *fplog = fp; }
/*! \brief Helper function for reporting GPU usage information * in the mdrun log file * * \param[in] gpu_info Pointer to per-node GPU info struct * \param[in] gpu_opt Pointer to per-node GPU options struct * \param[in] numPpRanks Number of PP ranks per node * \param[in] bPrintHostName Print the hostname in the usage information * \return String to write to the log file * \throws std::bad_alloc if out of memory */ static std::string makeGpuUsageReport(const gmx_gpu_info_t *gpu_info, const gmx_gpu_opt_t *gpu_opt, size_t numPpRanks, bool bPrintHostName) { int ngpu_use = gpu_opt->n_dev_use; int ngpu_comp = gpu_info->n_dev_compatible; char host[HOSTNAMELEN]; if (bPrintHostName) { gmx_gethostname(host, HOSTNAMELEN); } /* Issue a note if GPUs are available but not used */ if (ngpu_comp > 0 && ngpu_use < 1) { return gmx::formatString("%d compatible GPU%s detected in the system, but none will be used.\n" "Consider trying GPU acceleration with the Verlet scheme!\n", ngpu_comp, (ngpu_comp > 1) ? "s" : ""); } std::string output; if (!gpu_opt->bUserSet) { // gpu_opt->dev_compatible is only populated during auto-selection std::string gpuIdsString = formatAndJoin(gmx::constArrayRefFromArray(gpu_opt->dev_compatible, gpu_opt->n_dev_compatible), ",", gmx::StringFormatter("%d")); bool bPluralGpus = gpu_opt->n_dev_compatible > 1; if (bPrintHostName) { output += gmx::formatString("On host %s ", host); } output += gmx::formatString("%d compatible GPU%s %s present, with ID%s %s\n", gpu_opt->n_dev_compatible, bPluralGpus ? "s" : "", bPluralGpus ? "are" : "is", bPluralGpus ? "s" : "", gpuIdsString.c_str()); } { std::vector<int> gpuIdsInUse; for (int i = 0; i < ngpu_use; i++) { gpuIdsInUse.push_back(get_gpu_device_id(gpu_info, gpu_opt, i)); } std::string gpuIdsString = formatAndJoin(gpuIdsInUse, ",", gmx::StringFormatter("%d")); int numGpusInUse = gmx_count_gpu_dev_unique(gpu_info, gpu_opt); bool bPluralGpus = numGpusInUse > 1; if (bPrintHostName) { output += gmx::formatString("On host %s ", host); } output += gmx::formatString("%d GPU%s %sselected for this run.\n" "Mapping of GPU ID%s to the %d PP rank%s in this node: %s\n", numGpusInUse, bPluralGpus ? "s" : "", gpu_opt->bUserSet ? "user-" : "auto-", bPluralGpus ? "s" : "", numPpRanks, (numPpRanks > 1) ? "s" : "", gpuIdsString.c_str()); } return output; }
void gmx_tng_open(const char *filename, char mode, tng_trajectory_t *tng) { #ifdef GMX_USE_TNG /* First check whether we have to make a backup, * only for writing, not for read or append. */ if (mode == 'w') { #ifndef GMX_FAHCORE /* only make backups for normal gromacs */ make_backup(filename); #endif } /* tng must not be pointing at already allocated memory. * Memory will be allocated by tng_util_trajectory_open() and must * later on be freed by tng_util_trajectory_close(). */ if (TNG_SUCCESS != tng_util_trajectory_open(filename, mode, tng)) { /* TNG does return more than one degree of error, but there is no use case for GROMACS handling the non-fatal errors gracefully. */ gmx_fatal(FARGS, "%s while opening %s for %s", gmx_strerror("file"), filename, modeToVerb(mode)); } if (mode == 'w' || mode == 'a') { /* FIXME in TNG: When adding data to the header, subsequent blocks might get * overwritten. This could be solved by moving the first trajectory * frame set(s) to the end of the file. Could that cause other problems, * e.g. when continuing a simulation? */ char hostname[256]; gmx_gethostname(hostname, 256); if (mode == 'w') { tng_first_computer_name_set(*tng, hostname); } /* TODO: This should be implemented when the above fixme is done (adding data to * the header). */ // else // { // tng_last_computer_name_set(*tng, hostname); // } char programInfo[256]; const char *precisionString = ""; #ifdef GMX_DOUBLE precisionString = " (double precision)"; #endif sprintf(programInfo, "%.100s, %.128s%.24s", gmx::getProgramContext().displayName(), GromacsVersion(), precisionString); if (mode == 'w') { tng_first_program_name_set(*tng, programInfo); } /* TODO: This should be implemented when the above fixme is done (adding data to * the header). */ // else // { // tng_last_program_name_set(*tng, programInfo); // } #ifdef HAVE_UNISTD_H char username[256]; getlogin_r(username, 256); if (mode == 'w') { tng_first_user_name_set(*tng, username); } /* TODO: This should be implemented when the above fixme is done (adding data to * the header). */ // else // { // tng_last_user_name_set(*tng, username); // } #endif } #else gmx_file("GROMACS was compiled without TNG support, cannot handle this file type"); GMX_UNUSED_VALUE(filename); GMX_UNUSED_VALUE(mode); GMX_UNUSED_VALUE(tng); #endif }