Beispiel #1
0
/// @brief Allocate space for batch arrays.
///
/// @param [out] batchsel Storage for batch operations.
///
/// @param [in] batchnum libmsr_data_type_e data type of batch operation.
///
/// @param [out] opssize Size of specific set of batch operations.
///
/// @return 0 if successful, else NULL pointer as a result of libmsr_calloc(),
/// libmsr_malloc(), or libmsr_realloc().
static int batch_storage(struct msr_batch_array **batchsel, const int batchnum, unsigned **opssize)
{
    static struct msr_batch_array *batch = NULL;
    static unsigned arrsize = 1;
    static unsigned *size = NULL;
    int i;

    if (batch == NULL)
    {
#ifdef BATCH_DEBUG
        fprintf(stderr, "BATCH: initializing batch ops\n");
#endif
        arrsize = (batchnum + 1 > arrsize ? batchnum + 1 : arrsize);
        size = (unsigned *) libmsr_calloc(arrsize, sizeof(unsigned));
        batch = (struct msr_batch_array *) libmsr_calloc(arrsize, sizeof(struct msr_batch_array));
        for (i = 0; i < arrsize; i++)
        {
            size[i] = 0;
            batch[i].ops = NULL;
            batch[i].numops = 0;
        }
    }
    if (batchnum + 1 > arrsize)
    {
#ifdef BATCH_DEBUG
        fprintf(stderr, "BATCH: reallocating array of batches for batch %d\n", batchnum);
#endif
        unsigned oldsize = arrsize;
        arrsize = batchnum + 1;
        batch = (struct msr_batch_array *) libmsr_realloc(batch, arrsize * sizeof(struct msr_batch_array));
        size = (unsigned *) libmsr_realloc(size, arrsize * sizeof(unsigned));
        for (; oldsize < arrsize; oldsize++)
        {
            batch[oldsize].ops = NULL;
            batch[oldsize].numops = 0;
            size[oldsize] = 0;
        }
    }
    if (batchsel == NULL)
    {
        libmsr_error_handler("batch_storage(): Loading uninitialized batch", LIBMSR_ERROR_MSR_BATCH, getenv("HOSTNAME"), __FILE__, __LINE__);
    }
    *batchsel = &batch[batchnum];
    if (opssize != NULL)
    {
        *opssize = &size[batchnum];
    }
    return 0;
}
Beispiel #2
0
int allocate_batch(int batchnum, size_t bsize)
{
    unsigned *size = NULL;
    struct msr_batch_array *batch = NULL;
    int i;

#ifdef BATCH_DEBUG
    fprintf(stderr, "BATCH: allocating batch %d\n", batchnum);
#endif
    if (batch_storage(&batch, batchnum, &size))
    {
        return -1;
    }
#ifdef BATCH_DEBUG
    fprintf(stderr, "BATCH: batch %d is at %p\n", batchnum, batch);
#endif
    *size = bsize;
    if (batch->ops != NULL)
    {
        libmsr_error_handler("allocate_batch(): Conflicting batch pointers", LIBMSR_ERROR_MSR_BATCH, getenv("HOSTNAME"), __FILE__, __LINE__);
    }
#ifdef MEMHDLR_DEBUG
    fprintf(stderr, "MEMHDLR: size of batch %d is %d\n", batchnum, *size);
#endif
    batch->ops = (struct msr_batch_op *) libmsr_calloc(*size, sizeof(struct msr_batch_op));
    for (i = batch->numops; i < *size; i++)
    {
        batch->ops[i].err = 0;
    }
    return 0;
}
Beispiel #3
0
void dump_rapl_power_unit(FILE *writedest)
{
    int socket;
    struct rapl_units *r;
    static uint64_t sockets = 0;

    sockets = num_sockets();
    r = (struct rapl_units *) libmsr_calloc(sockets, sizeof(struct rapl_units));
    get_rapl_power_unit(r);

    for (socket = 0; socket < sockets; socket++)
    {
        fprintf(writedest, "Socket: %d\n", socket);
        fprintf(writedest, "   RAW power unit (W) = %8.4lf  energy unit (J^-1) = %8.4lf  time unit (s^-1) = %8.4lf\n", r[socket].watts, r[socket].joules, r[socket].seconds);
        fprintf(writedest, "   ADJ power unit (W) = %f  energy unit (J)    = %f    time unit (s)    = %f\n", r[socket].watts, 1/r[socket].joules, 1/r[socket].seconds);
    }
}
Beispiel #4
0
/// @brief Allocate RAPL data for batch operations.
///
/// @param [in] rapl_flags Platform-specific bit flags indicating availability
///        of RAPL MSRs.
///
/// @param [in] rapl Measurements of energy, time, and power data from a given
///        RAPL power domain.
static void create_rapl_data_batch(uint64_t *rapl_flags, struct rapl_data *rapl)
{
    uint64_t sockets = num_sockets();

    allocate_batch(RAPL_DATA, rapl_data_batch_size(rapl_flags) * sockets);
    if (*rapl_flags & PKG_ENERGY_STATUS)
    {
        rapl->pkg_bits = (uint64_t **) libmsr_calloc(sockets, sizeof(uint64_t *));
        rapl->pkg_joules = (double *) libmsr_calloc(sockets, sizeof(double));
        rapl->old_pkg_bits = (uint64_t *) libmsr_calloc(sockets, sizeof(uint64_t));
        rapl->old_pkg_joules = (double *) libmsr_calloc(sockets, sizeof(double));
        rapl->pkg_delta_joules = (double *) libmsr_calloc(sockets, sizeof(double));
        rapl->pkg_watts = (double *) libmsr_calloc(sockets, sizeof(double));
        load_socket_batch(MSR_PKG_ENERGY_STATUS, rapl->pkg_bits, RAPL_DATA);
    }
    if (*rapl_flags & PKG_PERF_STATUS)
    {
        rapl->pkg_perf_count = (uint64_t **) libmsr_calloc(sockets, sizeof(uint64_t));
        load_socket_batch(MSR_PKG_PERF_STATUS, rapl->pkg_perf_count, RAPL_DATA);
    }
    if (*rapl_flags & DRAM_ENERGY_STATUS)
    {
        rapl->dram_bits = (uint64_t **) libmsr_calloc(sockets, sizeof(uint64_t *));
        rapl->old_dram_bits = (uint64_t *) libmsr_calloc(sockets, sizeof(uint64_t));
        rapl->dram_joules = (double *) libmsr_calloc(sockets, sizeof(double));
        rapl->old_dram_joules = (double *) libmsr_calloc(sockets, sizeof(double));
        rapl->dram_delta_joules = (double *) libmsr_calloc(sockets, sizeof(double));
        rapl->dram_watts = (double *) libmsr_calloc(sockets, sizeof(double));
        load_socket_batch(MSR_DRAM_ENERGY_STATUS, rapl->dram_bits, RAPL_DATA);
    }
    if (*rapl_flags & DRAM_PERF_STATUS)
    {
        rapl->dram_perf_count = (uint64_t **) libmsr_calloc(sockets, sizeof(uint64_t));
        load_socket_batch(MSR_DRAM_PERF_STATUS, rapl->dram_perf_count, RAPL_DATA);
    }
}
Beispiel #5
0
/// @brief Translate any user-desired values to the format expected in the MSRs
/// and vice versa.
///
/// @param [in] socket Unique socket/package identifier.
///
/// @param [out] bits Raw bit field value.
///
/// @param [out] units Human-readable value.
///
/// @param [in] type libmsr_unit_conversions_e unit conversion identifier.
///
/// @return 0 upon function completion or upon converting bits to Joules for
/// DRAM RAPL power domain for 0x3F (Haswell) platform.
static int translate(const unsigned socket, uint64_t *bits, double *units, int type)
{
    static int init = 0;
    double logremainder = 0.0;
    static uint64_t sockets = 0;
    static uint64_t model = 0;
    static struct rapl_units *ru = NULL;
    uint64_t timeval_z = 0;
    uint64_t timeval_y = 0;

#ifdef LIBMSR_DEBUG
    fprintf(stderr, "DEBUG: (translate) bits are at %p\n", bits);
#endif
    if (sockets == 0)
    {
        sockets = num_sockets();
    }
    if (model == 0)
    {
        cpuid_get_model(&model);
    }
    sockets_assert(&socket, __LINE__, __FILE__);

    if (!init)
    {
        init = 1;
        ru = (struct rapl_units *) libmsr_calloc(sockets, sizeof(struct rapl_units));
        get_rapl_power_unit(ru);
    }
    switch(type)
    {
        case BITS_TO_WATTS:
            *units = (double)(*bits) * ru[socket].watts;
            break;
        case BITS_TO_JOULES_DRAM:
            if (model == 0x3F || model == 0x4F || model == 0x55)
            {
                *units = (double)(*bits) / STD_ENERGY_UNIT;
#ifdef LIBMSR_DEBUG
                fprintf(stderr, "DEBUG: (translate_dram) %f is %f joules\n", (double)*bits, *units);
#endif
                return 0;
            }
            /* No break statement, if not Haswell do standard stuff. */
        case BITS_TO_JOULES:
            *units = (double)(*bits) / ru[socket].joules;
            break;
        case WATTS_TO_BITS:
            *bits  = (uint64_t)((*units) / ru[socket].watts);
            break;
        case JOULES_TO_BITS:
            /// @todo Currently unused, but if it ever is used, we need a fix for Haswell.
            *bits  = (uint64_t)((*units) * ru[socket].joules);
            break;
        case BITS_TO_SECONDS_STD:
            timeval_y = *bits & 0x1F;
            timeval_z = (*bits & 0x60) >> 5;
            /* Dividing by time unit because it's stored as (1/(2^TU))^-1. */
            *units = ((1 + 0.25 * timeval_z) * pow(2.0,(double)timeval_y)) / ru[socket].seconds;
            // Temporary fix for haswell
            //    if (model == 0x3F)
            //    {
            //        *units = *units * 2.5 + 15.0;
            //    }
#ifdef LIBMSR_DEBUG
            fprintf(stderr, "%s %s::%d DEBUG: timeval_z is %lx, timeval_y is %lx, units is %lf, bits is %lx\n", getenv("HOSTNAME"), __FILE__, __LINE__, timeval_z, timeval_y, *units, *bits);
#endif
            break;
        case SECONDS_TO_BITS_STD:
            // Temporary fix for haswell
            //    if (model == 0x3F)
            //    {
            //        *units = *units / 2.5 - 15;
            //    }
            /* Store the whole number part of the log2. */
            timeval_y = (uint64_t)log2(*units * ru[socket].seconds);
            /* Store the mantissa of the log2. */
            logremainder = (double)log2(*units * ru[socket].seconds) - (double)timeval_y;
            timeval_z = 0;
            /* Based on the mantissa, choose the appropriate multiplier. */
            if (logremainder > 0.15 && logremainder <= 0.45)
            {
                timeval_z = 1;
            }
            else if (logremainder > 0.45 && logremainder <= 0.7)
            {
                timeval_z = 2;
            }
            else if (logremainder > 0.7)
            {
                timeval_z = 3;
            }
            /* Store the bits in the Intel specified format. */
            *bits = (uint64_t)(timeval_y | (timeval_z << 5));
#ifdef LIBMSR_DEBUG
            fprintf(stderr, "%s %s::%d DEBUG: timeval_z is %lx, timeval_y is %lx, units is %lf, bits is %lx, remainder is %lf\n", getenv("HOSTNAME"), __FILE__, __LINE__, timeval_z, timeval_y, *units, *bits, logremainder);
#endif
            break;
        default:
            fprintf(stderr, "%s:%d  Unknown value %d.  This is bad.\n", __FILE__, __LINE__, type);
            *bits = -1;
            *units= -1.0;
            break;
    }
    return 0;
}
Beispiel #6
0
void get_rapl_power_unit(struct rapl_units *ru)
{
    static int init = 0;
    static uint64_t sockets = 0;
    static uint64_t **val = NULL;
    int i;

    sockets = num_sockets();
    if (!init)
    {
        init = 1;
        val = (uint64_t **) libmsr_calloc(sockets, sizeof(uint64_t *));
        allocate_batch(RAPL_UNIT, sockets);
        load_socket_batch(MSR_RAPL_POWER_UNIT, val, RAPL_UNIT);
    }
    read_batch(RAPL_UNIT);
    /* Initialize the units used for each socket. */
    for (i = 0; i < sockets; i++)
    {
        // See figure 14-16 for bit fields.
        //  1  1 1  1 1
        //  9  6 5  2 1  8 7  4 3  0
        //
        //  1010 0001 0000 0000 0011
        //
        //     A    1    0    0    3
        //ru[i].msr_rapl_power_unit = 0xA1003;

        ru[i].msr_rapl_power_unit = *val[i];
        /* Default is 1010b or 976 microseconds. */
        /* Storing (1/(2^TU))^-1 for maximum precision. */
        ru[i].seconds = (double)(1 << (MASK_VAL(ru[i].msr_rapl_power_unit, 19, 16)));
        /* Default is 10000b or 15.3 microjoules. */
        /* Storing (1/(2^ESU))^-1 for maximum precision. */
        ru[i].joules = (double)(1 << (MASK_VAL(ru[i].msr_rapl_power_unit, 12, 8)));
#ifdef LIBMSR_DEBUG
        fprintf(stderr, "DEBUG: joules unit is %f register has %lx\n", ru[i].joules, ru[i].msr_rapl_power_unit);
#endif
        /* Default is 0011b or 1/8 Watts. */
        ru[i].watts = ((1.0)/((double)(1 << (MASK_VAL(ru[i].msr_rapl_power_unit, 3, 0)))));
#ifdef LIBMSR_DEBUG
        fprintf(stdout, "Pkg %d MSR_RAPL_POWER_UNIT\n", i);
        fprintf(stdout, "Raw: %f sec, %f J, %f watts\n", ru[i].seconds, ru[i].joules, ru[i].watts);
        fprintf(stdout, "Adjusted: %f sec, %f J, %f watts\n", 1/ru[i].seconds, 1/ru[i].joules, ru[i].watts);
#endif
    }

    /* Check consistency between packages. */
    uint64_t *tmp = (uint64_t *) libmsr_calloc(sockets, sizeof(uint64_t));
    for (i = 0; i < sockets; i++)
    {
        read_msr_by_coord(i, 0, 0, MSR_RAPL_POWER_UNIT, tmp);
        double energy = (double)(1 << (MASK_VAL(ru[i].msr_rapl_power_unit, 12, 8)));
        double seconds = (double)(1 << (MASK_VAL(ru[i].msr_rapl_power_unit, 19, 16)));
        double power = ((1.0)/((double)(1 << (MASK_VAL(ru[i].msr_rapl_power_unit, 3, 0)))));
        if (energy != ru[i].joules || power != ru[i].watts || seconds != ru[i].seconds)
        {
            libmsr_error_handler("get_rapl_power_unit(): Inconsistent rapl power units across packages", LIBMSR_ERROR_RUNTIME, getenv("HOSTNAME"), __FILE__, __LINE__);
        }
    }
}