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);
    }
}
Beispiel #2
0
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;
}
Beispiel #5
0
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
}