Blame src/components/nvml/linux-nvml.c

Packit 577717
/****************************
Packit 577717
THIS IS OPEN SOURCE CODE
Packit 577717
Packit 577717
Part of the PAPI software library. Copyright (c) 2005 - 2017,
Packit 577717
Innovative Computing Laboratory, Dept of Electrical Engineering &
Packit 577717
Computer Science University of Tennessee, Knoxville, TN.
Packit 577717
Packit 577717
The open source software license conforms to the 2-clause BSD License
Packit 577717
template.
Packit 577717
Packit 577717
****************************/
Packit 577717
Packit 577717
/**
Packit 577717
 * @file    linux-nvml.c
Packit 577717
 * @author  Kiran Kumar Kasichayanula
Packit 577717
 *          kkasicha@utk.edu
Packit 577717
 * @author  James Ralph
Packit 577717
 *          ralph@eecs.utk.edu
Packit 577717
 * @ingroup papi_components
Packit 577717
 *
Packit 577717
 * @brief This is an NVML component, it demos the component interface
Packit 577717
 *  and implements a number of counters from the Nvidia Management
Packit 577717
 *  Library. Please refer to NVML documentation for details about
Packit 577717
 *  nvmlDeviceGetPowerUsage, nvmlDeviceGetTemperature. Power is
Packit 577717
 *  reported in mW and temperature in Celcius.  The counter
Packit 577717
 *  descriptions should contain the units that the measurement
Packit 577717
 *  returns.
Packit 577717
 */
Packit 577717
#include <dlfcn.h>
Packit 577717
Packit 577717
#include <stdio.h>
Packit 577717
#include <string.h>
Packit 577717
#include <stdlib.h>
Packit 577717
#include <inttypes.h>
Packit 577717
#include <string.h>
Packit 577717
/* Headers required by PAPI */
Packit 577717
#include "papi.h"
Packit 577717
#include "papi_internal.h"
Packit 577717
#include "papi_vector.h"
Packit 577717
#include "papi_memory.h"
Packit 577717
Packit 577717
#include "linux-nvml.h"
Packit 577717
Packit 577717
#include "nvml.h"
Packit 577717
#include "cuda.h"
Packit 577717
#include "cuda_runtime_api.h"
Packit 577717
Packit 577717
void (*_dl_non_dynamic_init)(void) __attribute__((weak));
Packit 577717
Packit 577717
/*****  CHANGE PROTOTYPES TO DECLARE CUDA AND NVML LIBRARY SYMBOLS AS WEAK  *****
Packit 577717
 *  This is done so that a version of PAPI built with the nvml component can    *
Packit 577717
 *  be installed on a system which does not have the cuda libraries installed.  *
Packit 577717
 *                                                                              *
Packit 577717
 *  If this is done without these prototypes, then all papi services on the     *
Packit 577717
 *  system without the cuda libraries installed will fail.  The PAPI libraries  *
Packit 577717
 *  contain references to the cuda libraries which are not installed.  The      *
Packit 577717
 *  load of PAPI commands fails because the cuda library references can not be  *
Packit 577717
 *  resolved.                                                                   *
Packit 577717
 *                                                                              *
Packit 577717
 *  This also defines pointers to the cuda library functions that we call.      *
Packit 577717
 *  These function pointers will be resolved with dlopen/dlsym calls at         *
Packit 577717
 *  component initialization time.  The component then calls the cuda library   *
Packit 577717
 *  functions through these function pointers.                                  *
Packit 577717
 ********************************************************************************/
Packit 577717
#undef CUDAAPI
Packit 577717
#define CUDAAPI __attribute__((weak))
Packit 577717
CUresult CUDAAPI cuInit(unsigned int);
Packit 577717
Packit 577717
CUresult(*cuInitPtr)(unsigned int);
Packit 577717
Packit 577717
#undef CUDARTAPI
Packit 577717
#define CUDARTAPI __attribute__((weak))
Packit 577717
cudaError_t CUDARTAPI cudaGetDevice(int *);
Packit 577717
cudaError_t CUDARTAPI cudaGetDeviceCount(int *);
Packit 577717
cudaError_t CUDARTAPI cudaDeviceGetPCIBusId(char *, int, int);
Packit 577717
Packit 577717
cudaError_t (*cudaGetDevicePtr)(int *);
Packit 577717
cudaError_t (*cudaGetDeviceCountPtr)(int *);
Packit 577717
cudaError_t (*cudaDeviceGetPCIBusIdPtr)(char *, int, int);
Packit 577717
Packit 577717
#undef DECLDIR
Packit 577717
#define DECLDIR __attribute__((weak))
Packit 577717
nvmlReturn_t DECLDIR nvmlDeviceGetClockInfo(nvmlDevice_t, nvmlClockType_t, unsigned int *);
Packit 577717
const char*  DECLDIR nvmlErrorString(nvmlReturn_t);
Packit 577717
nvmlReturn_t DECLDIR nvmlDeviceGetDetailedEccErrors(nvmlDevice_t, nvmlEccBitType_t, nvmlEccCounterType_t, nvmlEccErrorCounts_t *);
Packit 577717
nvmlReturn_t DECLDIR nvmlDeviceGetFanSpeed(nvmlDevice_t, unsigned int *);
Packit 577717
nvmlReturn_t DECLDIR nvmlDeviceGetMemoryInfo(nvmlDevice_t, nvmlMemory_t *);
Packit 577717
nvmlReturn_t DECLDIR nvmlDeviceGetPerformanceState(nvmlDevice_t, nvmlPstates_t *);
Packit 577717
nvmlReturn_t DECLDIR nvmlDeviceGetPowerUsage(nvmlDevice_t, unsigned int *);
Packit 577717
nvmlReturn_t DECLDIR nvmlDeviceGetTemperature(nvmlDevice_t, nvmlTemperatureSensors_t, unsigned int *);
Packit 577717
nvmlReturn_t DECLDIR nvmlDeviceGetTotalEccErrors(nvmlDevice_t, nvmlEccBitType_t, nvmlEccCounterType_t, unsigned long long *);
Packit 577717
nvmlReturn_t DECLDIR nvmlDeviceGetUtilizationRates(nvmlDevice_t, nvmlUtilization_t *);
Packit 577717
nvmlReturn_t DECLDIR nvmlDeviceGetHandleByIndex(unsigned int, nvmlDevice_t *);
Packit 577717
nvmlReturn_t DECLDIR nvmlDeviceGetPciInfo(nvmlDevice_t, nvmlPciInfo_t *);
Packit 577717
nvmlReturn_t DECLDIR nvmlDeviceGetName(nvmlDevice_t, char *, unsigned int);
Packit 577717
nvmlReturn_t DECLDIR nvmlDeviceGetInforomVersion(nvmlDevice_t, nvmlInforomObject_t, char *, unsigned int);
Packit 577717
nvmlReturn_t DECLDIR nvmlDeviceGetEccMode(nvmlDevice_t, nvmlEnableState_t *, nvmlEnableState_t *);
Packit 577717
nvmlReturn_t DECLDIR nvmlInit(void);
Packit 577717
nvmlReturn_t DECLDIR nvmlDeviceGetCount(unsigned int *);
Packit 577717
nvmlReturn_t DECLDIR nvmlShutdown(void);
Packit 577717
nvmlReturn_t DECLDIR nvmlDeviceGetPowerManagementLimit(nvmlDevice_t device, unsigned int* limit);
Packit 577717
nvmlReturn_t DECLDIR nvmlDeviceSetPowerManagementLimit(nvmlDevice_t device, unsigned int  limit);
Packit 577717
nvmlReturn_t DECLDIR nvmlDeviceGetPowerManagementLimitConstraints(nvmlDevice_t device, unsigned int* minLimit, unsigned int* maxLimit);
Packit 577717
Packit 577717
nvmlReturn_t (*nvmlDeviceGetClockInfoPtr)(nvmlDevice_t, nvmlClockType_t, unsigned int *);
Packit 577717
char* (*nvmlErrorStringPtr)(nvmlReturn_t);
Packit 577717
nvmlReturn_t (*nvmlDeviceGetDetailedEccErrorsPtr)(nvmlDevice_t, nvmlEccBitType_t, nvmlEccCounterType_t, nvmlEccErrorCounts_t *);
Packit 577717
nvmlReturn_t (*nvmlDeviceGetFanSpeedPtr)(nvmlDevice_t, unsigned int *);
Packit 577717
nvmlReturn_t (*nvmlDeviceGetMemoryInfoPtr)(nvmlDevice_t, nvmlMemory_t *);
Packit 577717
nvmlReturn_t (*nvmlDeviceGetPerformanceStatePtr)(nvmlDevice_t, nvmlPstates_t *);
Packit 577717
nvmlReturn_t (*nvmlDeviceGetPowerUsagePtr)(nvmlDevice_t, unsigned int *);
Packit 577717
nvmlReturn_t (*nvmlDeviceGetTemperaturePtr)(nvmlDevice_t, nvmlTemperatureSensors_t, unsigned int *);
Packit 577717
nvmlReturn_t (*nvmlDeviceGetTotalEccErrorsPtr)(nvmlDevice_t, nvmlEccBitType_t, nvmlEccCounterType_t, unsigned long long *);
Packit 577717
nvmlReturn_t (*nvmlDeviceGetUtilizationRatesPtr)(nvmlDevice_t, nvmlUtilization_t *);
Packit 577717
nvmlReturn_t (*nvmlDeviceGetHandleByIndexPtr)(unsigned int, nvmlDevice_t *);
Packit 577717
nvmlReturn_t (*nvmlDeviceGetPciInfoPtr)(nvmlDevice_t, nvmlPciInfo_t *);
Packit 577717
nvmlReturn_t (*nvmlDeviceGetNamePtr)(nvmlDevice_t, char *, unsigned int);
Packit 577717
nvmlReturn_t (*nvmlDeviceGetInforomVersionPtr)(nvmlDevice_t, nvmlInforomObject_t, char *, unsigned int);
Packit 577717
nvmlReturn_t (*nvmlDeviceGetEccModePtr)(nvmlDevice_t, nvmlEnableState_t *, nvmlEnableState_t *);
Packit 577717
nvmlReturn_t (*nvmlInitPtr)(void);
Packit 577717
nvmlReturn_t (*nvmlDeviceGetCountPtr)(unsigned int *);
Packit 577717
nvmlReturn_t (*nvmlShutdownPtr)(void);
Packit 577717
nvmlReturn_t (*nvmlDeviceGetPowerManagementLimitPtr)(nvmlDevice_t device, unsigned int* limit);
Packit 577717
nvmlReturn_t (*nvmlDeviceSetPowerManagementLimitPtr)(nvmlDevice_t device, unsigned int  limit);
Packit 577717
nvmlReturn_t (*nvmlDeviceGetPowerManagementLimitConstraintsPtr)(nvmlDevice_t device, unsigned int* minLimit, unsigned int* maxLimit);
Packit 577717
Packit 577717
// file handles used to access cuda libraries with dlopen
Packit 577717
static void* dl1 = NULL;
Packit 577717
static void* dl2 = NULL;
Packit 577717
static void* dl3 = NULL;
Packit 577717
Packit 577717
static int linkCudaLibraries();
Packit 577717
Packit 577717
/* Declare our vector in advance */
Packit 577717
papi_vector_t _nvml_vector;
Packit 577717
Packit 577717
/* upto 25 events per card how many cards per system should we allow for?! */
Packit 577717
#define NVML_MAX_COUNTERS 100
Packit 577717
Packit 577717
/** Holds control flags.  Usually there's one of these per event-set.
Packit 577717
 *    Usually this is out-of band configuration of the hardware
Packit 577717
 */
Packit 577717
typedef struct nvml_control_state {
Packit 577717
    int num_events;
Packit 577717
    int which_counter[NVML_MAX_COUNTERS];
Packit 577717
    long long counter[NVML_MAX_COUNTERS];   /**< Copy of counts, holds results when stopped */
Packit 577717
} nvml_control_state_t;
Packit 577717
Packit 577717
/** Holds per-thread information */
Packit 577717
typedef struct nvml_context {
Packit 577717
    nvml_control_state_t state;
Packit 577717
} nvml_context_t;
Packit 577717
Packit 577717
/** This table contains the native events */
Packit 577717
static nvml_native_event_entry_t *nvml_native_table = NULL;
Packit 577717
Packit 577717
/** Number of devices detected at component_init time */
Packit 577717
static int device_count = 0;
Packit 577717
Packit 577717
/** number of events in the table*/
Packit 577717
static int num_events = 0;
Packit 577717
Packit 577717
static nvmlDevice_t* devices = NULL;
Packit 577717
static int* features = NULL;
Packit 577717
static unsigned int *power_management_initial_limit = NULL;
Packit 577717
static unsigned int *power_management_limit_constraint_min = NULL;
Packit 577717
static unsigned int *power_management_limit_constraint_max = NULL;
Packit 577717
Packit 577717
unsigned long long
Packit 577717
getClockSpeed(nvmlDevice_t dev, nvmlClockType_t which_one)
Packit 577717
{
Packit 577717
    unsigned int ret = 0;
Packit 577717
    nvmlReturn_t bad;
Packit 577717
    bad = (*nvmlDeviceGetClockInfoPtr)(dev, which_one, &ret;;
Packit 577717
Packit 577717
    if (NVML_SUCCESS != bad) {
Packit 577717
        SUBDBG("something went wrong %s\n", (*nvmlErrorStringPtr)(bad));
Packit 577717
    }
Packit 577717
Packit 577717
    return (unsigned long long)ret;
Packit 577717
}
Packit 577717
Packit 577717
unsigned long long
Packit 577717
getEccLocalErrors(nvmlDevice_t dev, nvmlEccBitType_t bits, int which_one)
Packit 577717
{
Packit 577717
    nvmlEccErrorCounts_t counts;
Packit 577717
Packit 577717
    nvmlReturn_t bad;
Packit 577717
    bad = (*nvmlDeviceGetDetailedEccErrorsPtr)(dev, bits, NVML_VOLATILE_ECC , &counts);
Packit 577717
Packit 577717
    if (NVML_SUCCESS != bad) {
Packit 577717
        SUBDBG("something went wrong %s\n", (*nvmlErrorStringPtr)(bad));
Packit 577717
    }
Packit 577717
    switch (which_one) {
Packit 577717
    case LOCAL_ECC_REGFILE:
Packit 577717
        return counts.registerFile;
Packit 577717
    case LOCAL_ECC_L1:
Packit 577717
        return counts.l1Cache;
Packit 577717
    case LOCAL_ECC_L2:
Packit 577717
        return counts.l2Cache;
Packit 577717
    case LOCAL_ECC_MEM:
Packit 577717
        return counts.deviceMemory;
Packit 577717
    default:
Packit 577717
        ;
Packit 577717
    }
Packit 577717
    return (unsigned long long) - 1;
Packit 577717
}
Packit 577717
Packit 577717
unsigned long long
Packit 577717
getFanSpeed(nvmlDevice_t dev)
Packit 577717
{
Packit 577717
    unsigned int ret = 0;
Packit 577717
    nvmlReturn_t bad;
Packit 577717
    bad = (*nvmlDeviceGetFanSpeedPtr)(dev, &ret;;
Packit 577717
Packit 577717
    if (NVML_SUCCESS != bad) {
Packit 577717
        SUBDBG("something went wrong %s\n", (*nvmlErrorStringPtr)(bad));
Packit 577717
    }
Packit 577717
    return (unsigned long long)ret;
Packit 577717
}
Packit 577717
Packit 577717
unsigned long long
Packit 577717
getMaxClockSpeed(nvmlDevice_t dev, nvmlClockType_t which_one)
Packit 577717
{
Packit 577717
    unsigned int ret = 0;
Packit 577717
    nvmlReturn_t bad;
Packit 577717
    bad = (*nvmlDeviceGetClockInfoPtr)(dev, which_one, &ret;;
Packit 577717
Packit 577717
    if (NVML_SUCCESS != bad) {
Packit 577717
        SUBDBG("something went wrong %s\n", (*nvmlErrorStringPtr)(bad));
Packit 577717
    }
Packit 577717
    return (unsigned long long) ret;
Packit 577717
}
Packit 577717
Packit 577717
unsigned long long
Packit 577717
getMemoryInfo(nvmlDevice_t dev, int which_one)
Packit 577717
{
Packit 577717
    nvmlMemory_t meminfo;
Packit 577717
    nvmlReturn_t bad;
Packit 577717
    bad = (*nvmlDeviceGetMemoryInfoPtr)(dev, &meminfo);
Packit 577717
Packit 577717
    if (NVML_SUCCESS != bad) {
Packit 577717
        SUBDBG("something went wrong %s\n", (*nvmlErrorStringPtr)(bad));
Packit 577717
    }
Packit 577717
Packit 577717
    switch (which_one) {
Packit 577717
    case MEMINFO_TOTAL_MEMORY:
Packit 577717
        return meminfo.total;
Packit 577717
    case MEMINFO_UNALLOCED:
Packit 577717
        return meminfo.free;
Packit 577717
    case MEMINFO_ALLOCED:
Packit 577717
        return meminfo.used;
Packit 577717
    default:
Packit 577717
        ;
Packit 577717
    }
Packit 577717
    return (unsigned long long) - 1;
Packit 577717
}
Packit 577717
Packit 577717
unsigned long long
Packit 577717
getPState(nvmlDevice_t dev)
Packit 577717
{
Packit 577717
    unsigned int ret = 0;
Packit 577717
    nvmlPstates_t state = NVML_PSTATE_15;
Packit 577717
    nvmlReturn_t bad;
Packit 577717
    bad = (*nvmlDeviceGetPerformanceStatePtr)(dev, &state);
Packit 577717
Packit 577717
    if (NVML_SUCCESS != bad) {
Packit 577717
        SUBDBG("something went wrong %s\n", (*nvmlErrorStringPtr)(bad));
Packit 577717
    }
Packit 577717
    switch (state) {
Packit 577717
    case NVML_PSTATE_15:
Packit 577717
        ret++;
Packit 577717
    case NVML_PSTATE_14:
Packit 577717
        ret++;
Packit 577717
    case NVML_PSTATE_13:
Packit 577717
        ret++;
Packit 577717
    case NVML_PSTATE_12:
Packit 577717
        ret++;
Packit 577717
    case NVML_PSTATE_11:
Packit 577717
        ret++;
Packit 577717
    case NVML_PSTATE_10:
Packit 577717
        ret++;
Packit 577717
    case NVML_PSTATE_9:
Packit 577717
        ret++;
Packit 577717
    case NVML_PSTATE_8:
Packit 577717
        ret++;
Packit 577717
    case NVML_PSTATE_7:
Packit 577717
        ret++;
Packit 577717
    case NVML_PSTATE_6:
Packit 577717
        ret++;
Packit 577717
    case NVML_PSTATE_5:
Packit 577717
        ret++;
Packit 577717
    case NVML_PSTATE_4:
Packit 577717
        ret++;
Packit 577717
    case NVML_PSTATE_3:
Packit 577717
        ret++;
Packit 577717
    case NVML_PSTATE_2:
Packit 577717
        ret++;
Packit 577717
    case NVML_PSTATE_1:
Packit 577717
        ret++;
Packit 577717
    case NVML_PSTATE_0:
Packit 577717
        break;
Packit 577717
    case NVML_PSTATE_UNKNOWN:
Packit 577717
    default:
Packit 577717
        /* This should never happen?
Packit 577717
         * The API docs just state Unknown performance state... */
Packit 577717
        return (unsigned long long) - 1;
Packit 577717
    }
Packit 577717
    return (unsigned long long)ret;
Packit 577717
}
Packit 577717
Packit 577717
unsigned long long
Packit 577717
getPowerUsage(nvmlDevice_t dev)
Packit 577717
{
Packit 577717
    unsigned int power;
Packit 577717
    nvmlReturn_t bad;
Packit 577717
    bad = (*nvmlDeviceGetPowerUsagePtr)(dev, &power);
Packit 577717
Packit 577717
    if (NVML_SUCCESS != bad) {
Packit 577717
        SUBDBG("something went wrong %s\n", (*nvmlErrorStringPtr)(bad));
Packit 577717
    }
Packit 577717
    return (unsigned long long) power;
Packit 577717
}
Packit 577717
Packit 577717
unsigned long long
Packit 577717
getTemperature(nvmlDevice_t dev)
Packit 577717
{
Packit 577717
    unsigned int ret = 0;
Packit 577717
    nvmlReturn_t bad;
Packit 577717
    bad = (*nvmlDeviceGetTemperaturePtr)(dev, NVML_TEMPERATURE_GPU, &ret;;
Packit 577717
Packit 577717
    if (NVML_SUCCESS != bad) {
Packit 577717
        SUBDBG("something went wrong %s\n", (*nvmlErrorStringPtr)(bad));
Packit 577717
    }
Packit 577717
    return (unsigned long long)ret;
Packit 577717
}
Packit 577717
Packit 577717
unsigned long long
Packit 577717
getTotalEccErrors(nvmlDevice_t dev, nvmlEccBitType_t bits)
Packit 577717
{
Packit 577717
    unsigned long long counts = 0;
Packit 577717
    nvmlReturn_t bad;
Packit 577717
    bad = (*nvmlDeviceGetTotalEccErrorsPtr)(dev, bits, NVML_VOLATILE_ECC , &counts);
Packit 577717
Packit 577717
    if (NVML_SUCCESS != bad) {
Packit 577717
        SUBDBG("something went wrong %s\n", (*nvmlErrorStringPtr)(bad));
Packit 577717
    }
Packit 577717
    return counts;
Packit 577717
}
Packit 577717
Packit 577717
/*  0 => gpu util
Packit 577717
    1 => memory util
Packit 577717
 */
Packit 577717
unsigned long long
Packit 577717
getUtilization(nvmlDevice_t dev, int which_one)
Packit 577717
{
Packit 577717
    nvmlUtilization_t util;
Packit 577717
    nvmlReturn_t bad;
Packit 577717
    bad = (*nvmlDeviceGetUtilizationRatesPtr)(dev, &util);
Packit 577717
Packit 577717
    if (NVML_SUCCESS != bad) {
Packit 577717
        SUBDBG("something went wrong %s\n", (*nvmlErrorStringPtr)(bad));
Packit 577717
    }
Packit 577717
Packit 577717
    switch (which_one) {
Packit 577717
    case GPU_UTILIZATION:
Packit 577717
        return (unsigned long long) util.gpu;
Packit 577717
    case MEMORY_UTILIZATION:
Packit 577717
        return (unsigned long long) util.memory;
Packit 577717
    default:
Packit 577717
        ;
Packit 577717
    }
Packit 577717
Packit 577717
    return (unsigned long long) - 1;
Packit 577717
}
Packit 577717
Packit 577717
unsigned long long getPowerManagementLimit(nvmlDevice_t dev)
Packit 577717
{
Packit 577717
    unsigned int limit;
Packit 577717
    nvmlReturn_t rv;
Packit 577717
    rv = (*nvmlDeviceGetPowerManagementLimitPtr)(dev, &limit);
Packit 577717
    if (NVML_SUCCESS != rv) {
Packit 577717
        SUBDBG("something went wrong %s\n", (*nvmlErrorStringPtr)(rv));
Packit 577717
        return (unsigned long long) 0;
Packit 577717
    }
Packit 577717
    return (unsigned long long) limit;
Packit 577717
}
Packit 577717
Packit 577717
static void
Packit 577717
nvml_hardware_reset()
Packit 577717
{
Packit 577717
    /* nvmlDeviceSet* and nvmlDeviceClear* calls require root/admin access, so while
Packit 577717
     * possible to implement a reset on the ECC counters, we pass */
Packit 577717
    /*
Packit 577717
       for ( i=0; i < device_count; i++ )
Packit 577717
       nvmlDeviceClearEccErrorCounts( device[i], NVML_VOLATILE_ECC );
Packit 577717
    */
Packit 577717
    int i;
Packit 577717
    nvmlReturn_t ret;
Packit 577717
    unsigned int templimit = 0;
Packit 577717
    for (i = 0; i < device_count; i++) {
Packit 577717
        if (HAS_FEATURE(features[i], FEATURE_POWER_MANAGEMENT)) {
Packit 577717
            // if power management is available
Packit 577717
            if (power_management_initial_limit[i] != 0) {
Packit 577717
                ret = (*nvmlDeviceGetPowerManagementLimitPtr)(devices[i], &templimit);
Packit 577717
                if ((ret == NVML_SUCCESS) && (templimit != power_management_initial_limit[i])) {
Packit 577717
                    SUBDBG("Reset power_management_limit on device %d to initial value of %d \n", i, power_management_initial_limit[i]);
Packit 577717
                    // if power is not at its initial value
Packit 577717
                    // reset to initial value
Packit 577717
                    ret = (*nvmlDeviceSetPowerManagementLimitPtr)(devices[i], power_management_initial_limit[i]);
Packit 577717
                    if (ret != NVML_SUCCESS)
Packit 577717
                        SUBDBG("Unable to reset the NVML power management limit on device %i to %ull (return code %d) \n", i, power_management_initial_limit[i] , ret);
Packit 577717
                }
Packit 577717
            }
Packit 577717
        }
Packit 577717
    }
Packit 577717
}
Packit 577717
Packit 577717
/** Code that reads event values.                         */
Packit 577717
/*   You might replace this with code that accesses       */
Packit 577717
/*   hardware or reads values from the operatings system. */
Packit 577717
static int
Packit 577717
nvml_hardware_read(long long *value, int which_one)
Packit 577717
//, nvml_context_t *ctx)
Packit 577717
{
Packit 577717
    nvml_native_event_entry_t *entry;
Packit 577717
    nvmlDevice_t handle;
Packit 577717
    int cudaIdx = -1;
Packit 577717
Packit 577717
    entry = &nvml_native_table[which_one];
Packit 577717
    *value = (long long) - 1;
Packit 577717
    /* replace entry->resources with the current cuda_device->nvml device */
Packit 577717
    (*cudaGetDevicePtr)(&cudaIdx);
Packit 577717
Packit 577717
    if (cudaIdx < 0 || cudaIdx > device_count)
Packit 577717
        return PAPI_EINVAL;
Packit 577717
Packit 577717
    /* Make sure the device we are running on has the requested event */
Packit 577717
    if (!HAS_FEATURE(features[cudaIdx] , entry->type))
Packit 577717
        return PAPI_EINVAL;
Packit 577717
Packit 577717
    handle = devices[cudaIdx];
Packit 577717
Packit 577717
    switch (entry->type) {
Packit 577717
    case FEATURE_CLOCK_INFO:
Packit 577717
        *value =  getClockSpeed(handle, (nvmlClockType_t)entry->options.clock);
Packit 577717
        break;
Packit 577717
    case FEATURE_ECC_LOCAL_ERRORS:
Packit 577717
        *value = getEccLocalErrors(handle,
Packit 577717
                                   (nvmlEccBitType_t)entry->options.ecc_opts.bits,
Packit 577717
                                   (int)entry->options.ecc_opts.which_one);
Packit 577717
        break;
Packit 577717
    case FEATURE_FAN_SPEED:
Packit 577717
        *value = getFanSpeed(handle);
Packit 577717
        break;
Packit 577717
    case FEATURE_MAX_CLOCK:
Packit 577717
        *value = getMaxClockSpeed(handle,
Packit 577717
                                  (nvmlClockType_t)entry->options.clock);
Packit 577717
        break;
Packit 577717
    case FEATURE_MEMORY_INFO:
Packit 577717
        *value = getMemoryInfo(handle,
Packit 577717
                               (int)entry->options.which_one);
Packit 577717
        break;
Packit 577717
    case FEATURE_PERF_STATES:
Packit 577717
        *value = getPState(handle);
Packit 577717
        break;
Packit 577717
    case FEATURE_POWER:
Packit 577717
        *value = getPowerUsage(handle);
Packit 577717
        break;
Packit 577717
    case FEATURE_TEMP:
Packit 577717
        *value = getTemperature(handle);
Packit 577717
        break;
Packit 577717
    case FEATURE_ECC_TOTAL_ERRORS:
Packit 577717
        *value = getTotalEccErrors(handle,
Packit 577717
                                   (nvmlEccBitType_t)entry->options.ecc_opts.bits);
Packit 577717
        break;
Packit 577717
    case FEATURE_UTILIZATION:
Packit 577717
        *value = getUtilization(handle,
Packit 577717
                                (int)entry->options.which_one);
Packit 577717
        break;
Packit 577717
    case FEATURE_POWER_MANAGEMENT:
Packit 577717
        *value = getPowerManagementLimit(handle);
Packit 577717
        break;
Packit 577717
Packit 577717
    case FEATURE_NVML_POWER_MANAGEMENT_LIMIT_CONSTRAINT_MIN:
Packit 577717
        *value = power_management_limit_constraint_min[cudaIdx];
Packit 577717
        break;
Packit 577717
Packit 577717
    case FEATURE_NVML_POWER_MANAGEMENT_LIMIT_CONSTRAINT_MAX:
Packit 577717
        *value = power_management_limit_constraint_max[cudaIdx];
Packit 577717
        break;
Packit 577717
Packit 577717
    default:
Packit 577717
        return PAPI_EINVAL;
Packit 577717
    }
Packit 577717
Packit 577717
    return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/** Code that reads event values.                         */
Packit 577717
/*   You might replace this with code that accesses       */
Packit 577717
/*   hardware or reads values from the operatings system. */
Packit 577717
static int nvml_hardware_write(long long *value, int which_one)
Packit 577717
{
Packit 577717
    nvml_native_event_entry_t *entry;
Packit 577717
    nvmlDevice_t handle;
Packit 577717
    int cudaIdx = -1;
Packit 577717
    nvmlReturn_t nvret;
Packit 577717
Packit 577717
    entry = &nvml_native_table[which_one];
Packit 577717
    /* replace entry->resources with the current cuda_device->nvml device */
Packit 577717
    (*cudaGetDevicePtr)(&cudaIdx);
Packit 577717
Packit 577717
    if (cudaIdx < 0 || cudaIdx > device_count)
Packit 577717
        return PAPI_EINVAL;
Packit 577717
Packit 577717
    /* Make sure the device we are running on has the requested event */
Packit 577717
    if (!HAS_FEATURE(features[cudaIdx] , entry->type))
Packit 577717
        return PAPI_EINVAL;
Packit 577717
Packit 577717
    handle = devices[cudaIdx];
Packit 577717
Packit 577717
    switch (entry->type) {
Packit 577717
    case FEATURE_POWER_MANAGEMENT: {
Packit 577717
        unsigned int setToPower = (unsigned int) * value;
Packit 577717
        if (setToPower < power_management_limit_constraint_min[cudaIdx]) {
Packit 577717
            SUBDBG("Error: Desired power %u mW < minimum %u mW on device %d\n", setToPower, power_management_limit_constraint_min[cudaIdx], cudaIdx);
Packit 577717
            return PAPI_EINVAL;
Packit 577717
        }
Packit 577717
        if (setToPower > power_management_limit_constraint_max[cudaIdx]) {
Packit 577717
            SUBDBG("Error: Desired power %u mW > maximum %u mW on device %d\n", setToPower, power_management_limit_constraint_max[cudaIdx], cudaIdx);
Packit 577717
            return PAPI_EINVAL;
Packit 577717
        }
Packit 577717
        if ((nvret = (*nvmlDeviceSetPowerManagementLimitPtr)(handle, setToPower)) != NVML_SUCCESS) {
Packit 577717
            SUBDBG("Error: %s\n", (*nvmlErrorStringPtr)(nvret));
Packit 577717
            return PAPI_EINVAL;
Packit 577717
        }
Packit 577717
    }
Packit 577717
    break;
Packit 577717
Packit 577717
    default:
Packit 577717
        return PAPI_EINVAL;
Packit 577717
    }
Packit 577717
Packit 577717
    return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/********************************************************************/
Packit 577717
/* Below are the functions required by the PAPI component interface */
Packit 577717
/********************************************************************/
Packit 577717
Packit 577717
/** This is called whenever a thread is initialized */
Packit 577717
int
Packit 577717
_papi_nvml_init_thread(hwd_context_t * ctx)
Packit 577717
{
Packit 577717
    (void) ctx;
Packit 577717
Packit 577717
    SUBDBG("Enter: ctx: %p\n", ctx);
Packit 577717
Packit 577717
    return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
static int
Packit 577717
detectDevices()
Packit 577717
{
Packit 577717
    nvmlReturn_t ret;
Packit 577717
    nvmlEnableState_t mode = NVML_FEATURE_DISABLED;
Packit 577717
Packit 577717
    char name[64];
Packit 577717
    char inforomECC[16];
Packit 577717
    char inforomPower[16];
Packit 577717
    char names[device_count][64];
Packit 577717
Packit 577717
    float ecc_version = 0.0;
Packit 577717
    float power_version = 0.0;
Packit 577717
Packit 577717
    int i = 0;
Packit 577717
    int isTesla = 0;
Packit 577717
    int isFermi = 0;
Packit 577717
Packit 577717
    unsigned int temp = 0;
Packit 577717
Packit 577717
    memset(names, 0x0, device_count * 64);
Packit 577717
Packit 577717
    /* So for each card, check whats querable */
Packit 577717
    for (i = 0; i < device_count; i++) {
Packit 577717
        isTesla = 0;
Packit 577717
        isFermi = 1;
Packit 577717
        features[i] = 0;
Packit 577717
        
Packit 577717
        ret = (*nvmlDeviceGetHandleByIndexPtr)(i, &devices[i]);
Packit 577717
        if (NVML_SUCCESS != ret) {
Packit 577717
            SUBDBG("nvmlDeviceGetHandleByIndex(%d, &devices[%d]) failed.\n", i, i);
Packit 577717
            return PAPI_ESYS;
Packit 577717
        }
Packit 577717
Packit 577717
        ret = (*nvmlDeviceGetNamePtr)(devices[i], name, sizeof(name) - 1);
Packit 577717
        if (NVML_SUCCESS != ret) {
Packit 577717
            SUBDBG("nvmlDeviceGetName failed \n");
Packit 577717
            strncpy(name, "deviceNameUnknown", 17);
Packit 577717
        }
Packit 577717
Packit 577717
        name[sizeof(name) - 1] = '\0';   // to safely use strstr operation below, the variable 'name' must be null terminated
Packit 577717
Packit 577717
        ret = (*nvmlDeviceGetInforomVersionPtr)(devices[i], NVML_INFOROM_ECC, inforomECC, 16);
Packit 577717
        if (NVML_SUCCESS != ret) {
Packit 577717
            SUBDBG("nvmlGetInforomVersion fails %s\n", (*nvmlErrorStringPtr)(ret));
Packit 577717
            isFermi = 0;
Packit 577717
        }
Packit 577717
        ret = (*nvmlDeviceGetInforomVersionPtr)(devices[i], NVML_INFOROM_POWER, inforomPower, 16);
Packit 577717
        if (NVML_SUCCESS != ret) {
Packit 577717
            /* This implies the card is older then Fermi */
Packit 577717
            SUBDBG("nvmlGetInforomVersion fails %s\n", (*nvmlErrorStringPtr)(ret));
Packit 577717
            SUBDBG("Based upon the return to nvmlGetInforomVersion, we conclude this card is older then Fermi.\n");
Packit 577717
            isFermi = 0;
Packit 577717
        }
Packit 577717
Packit 577717
        ecc_version = strtof(inforomECC, NULL);
Packit 577717
        power_version = strtof(inforomPower, NULL);
Packit 577717
Packit 577717
        isTesla = (NULL == strstr(name, "Tesla")) ? 0 : 1;
Packit 577717
Packit 577717
        /* For Tesla and Quadro products from Fermi and Kepler families. */
Packit 577717
        if (isFermi) {
Packit 577717
            features[i] |= FEATURE_CLOCK_INFO;
Packit 577717
            num_events += 3;
Packit 577717
        }
Packit 577717
Packit 577717
        /*  For Tesla and Quadro products from Fermi and Kepler families.
Packit 577717
            requires NVML_INFOROM_ECC 2.0 or higher for location-based counts
Packit 577717
            requires NVML_INFOROM_ECC 1.0 or higher for all other ECC counts
Packit 577717
            requires ECC mode to be enabled. */
Packit 577717
        ret = (*nvmlDeviceGetEccModePtr)(devices[i], &mode, NULL);
Packit 577717
        if (NVML_SUCCESS == ret) {
Packit 577717
            if (NVML_FEATURE_ENABLED == mode) {
Packit 577717
                if (ecc_version >= 2.0) {
Packit 577717
                    features[i] |= FEATURE_ECC_LOCAL_ERRORS;
Packit 577717
                    num_events += 8; /* {single bit, two bit errors} x { reg, l1, l2, memory } */
Packit 577717
                }
Packit 577717
                if (ecc_version >= 1.0) {
Packit 577717
                    features[i] |= FEATURE_ECC_TOTAL_ERRORS;
Packit 577717
                    num_events += 2; /* single bit errors, double bit errors */
Packit 577717
                }
Packit 577717
            }
Packit 577717
        } else {
Packit 577717
            SUBDBG("nvmlDeviceGetEccMode does not appear to be supported. (nvml return code %d)\n", ret);
Packit 577717
        }
Packit 577717
Packit 577717
        /* For all discrete products with dedicated fans */
Packit 577717
        features[i] |= FEATURE_FAN_SPEED;
Packit 577717
        num_events++;
Packit 577717
Packit 577717
        /* For Tesla and Quadro products from Fermi and Kepler families. */
Packit 577717
        if (isFermi) {
Packit 577717
            features[i] |= FEATURE_MAX_CLOCK;
Packit 577717
            num_events += 3;
Packit 577717
        }
Packit 577717
Packit 577717
        /* For all products */
Packit 577717
        features[i] |= FEATURE_MEMORY_INFO;
Packit 577717
        num_events += 3; /* total, free, used */
Packit 577717
Packit 577717
        /* For Tesla and Quadro products from the Fermi and Kepler families. */
Packit 577717
        if (isFermi) {
Packit 577717
            features[i] |= FEATURE_PERF_STATES;
Packit 577717
            num_events++;
Packit 577717
        }
Packit 577717
Packit 577717
        /*  For "GF11x" Tesla and Quadro products from the Fermi family
Packit 577717
                requires NVML_INFOROM_POWER 3.0 or higher
Packit 577717
                For Tesla and Quadro products from the Kepler family
Packit 577717
                does not require NVML_INFOROM_POWER */
Packit 577717
        /* Just try reading power, if it works, enable it*/
Packit 577717
        ret = (*nvmlDeviceGetPowerUsagePtr)(devices[i], &temp);
Packit 577717
        if (NVML_SUCCESS == ret) {
Packit 577717
            features[i] |= FEATURE_POWER;
Packit 577717
            num_events++;
Packit 577717
        } else {
Packit 577717
            SUBDBG("nvmlDeviceGetPowerUsage does not appear to be supported on this card. (nvml return code %d)\n", ret);
Packit 577717
        }
Packit 577717
Packit 577717
        /* For all discrete and S-class products. */
Packit 577717
        features[i] |= FEATURE_TEMP;
Packit 577717
        num_events++;
Packit 577717
Packit 577717
        // For power_management_limit
Packit 577717
        {
Packit 577717
            // Just try the call to see if it works
Packit 577717
            unsigned int templimit = 0;
Packit 577717
            ret = (*nvmlDeviceGetPowerManagementLimitPtr)(devices[i], &templimit);
Packit 577717
            if (ret == NVML_SUCCESS && templimit > 0) {
Packit 577717
                power_management_initial_limit[i] = templimit;
Packit 577717
                features[i] |= FEATURE_POWER_MANAGEMENT;
Packit 577717
                num_events += 1;
Packit 577717
            } else {
Packit 577717
                power_management_initial_limit[i] = 0;
Packit 577717
                SUBDBG("nvmlDeviceGetPowerManagementLimit not appear to be supported on this card. (NVML code %d)\n", ret);
Packit 577717
            }
Packit 577717
        }
Packit 577717
Packit 577717
        // For power_management_limit_constraints, minimum and maximum
Packit 577717
        {
Packit 577717
            unsigned int minLimit = 0, maxLimit = 0;
Packit 577717
            ret = (*nvmlDeviceGetPowerManagementLimitConstraintsPtr)(devices[i], &minLimit, &maxLimit);
Packit 577717
            if (ret == NVML_SUCCESS) {
Packit 577717
                power_management_limit_constraint_min[i] = minLimit;
Packit 577717
                features[i] |= FEATURE_NVML_POWER_MANAGEMENT_LIMIT_CONSTRAINT_MIN;
Packit 577717
                num_events += 1;
Packit 577717
                power_management_limit_constraint_max[i] = maxLimit;
Packit 577717
                features[i] |= FEATURE_NVML_POWER_MANAGEMENT_LIMIT_CONSTRAINT_MAX;
Packit 577717
                num_events += 1;
Packit 577717
            } else {
Packit 577717
                power_management_limit_constraint_min[i] = 0;
Packit 577717
                power_management_limit_constraint_max[i] = INT_MAX;
Packit 577717
            }
Packit 577717
            SUBDBG("Done nvmlDeviceGetPowerManagementLimitConstraintsPtr\n");
Packit 577717
        }
Packit 577717
Packit 577717
        /* For Tesla and Quadro products from the Fermi and Kepler families */
Packit 577717
        if (isFermi) {
Packit 577717
            features[i] |= FEATURE_UTILIZATION;
Packit 577717
            num_events += 2;
Packit 577717
        }
Packit 577717
Packit 577717
        int retval = snprintf(names[i], sizeof(name), "%s:device:%d", name, i);
Packit 577717
        if (retval > (int)sizeof(name)) {
Packit 577717
            SUBDBG("Device name is too long %s:device%d", name, i);
Packit 577717
            return (PAPI_EINVAL);
Packit 577717
        }
Packit 577717
        names[i][sizeof(name) - 1] = '\0';
Packit 577717
    }
Packit 577717
    return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
static void
Packit 577717
createNativeEvents()
Packit 577717
{
Packit 577717
    char name[64];
Packit 577717
    char sanitized_name[PAPI_MAX_STR_LEN];
Packit 577717
    char names[device_count][64];
Packit 577717
Packit 577717
    int i, nameLen = 0, j;
Packit 577717
Packit 577717
    nvml_native_event_entry_t* entry;
Packit 577717
    nvmlReturn_t ret;
Packit 577717
Packit 577717
    nvml_native_table = (nvml_native_event_entry_t*) papi_malloc(
Packit 577717
                            sizeof(nvml_native_event_entry_t) * num_events);
Packit 577717
    memset(nvml_native_table, 0x0, sizeof(nvml_native_event_entry_t) * num_events);
Packit 577717
    entry = &nvml_native_table[0];
Packit 577717
Packit 577717
    for (i = 0; i < device_count; i++) {
Packit 577717
        memset(names[i], 0x0, 64);
Packit 577717
        ret = (*nvmlDeviceGetNamePtr)(devices[i], name, sizeof(name) - 1);
Packit 577717
        if (NVML_SUCCESS != ret) {
Packit 577717
            SUBDBG("nvmlDeviceGetName failed \n");
Packit 577717
            strncpy(name, "deviceNameUnknown", 17);
Packit 577717
        }
Packit 577717
        name[sizeof(name) - 1] = '\0';   // to safely use strlen operation below, the variable 'name' must be null terminated
Packit 577717
Packit 577717
        nameLen = strlen(name);
Packit 577717
        strncpy(sanitized_name, name, PAPI_MAX_STR_LEN);
Packit 577717
Packit 577717
        int retval = snprintf(sanitized_name, sizeof(name), "%s:device_%d", name, i);
Packit 577717
        if (retval > (int)sizeof(name)) {
Packit 577717
            SUBDBG("Device name is too long %s:device%d", name, i);
Packit 577717
            return;
Packit 577717
        }
Packit 577717
        sanitized_name[sizeof(name) - 1] = '\0';
Packit 577717
Packit 577717
        for (j = 0; j < nameLen; j++)
Packit 577717
            if (' ' == sanitized_name[j])
Packit 577717
                sanitized_name[j] = '_';
Packit 577717
Packit 577717
        if (HAS_FEATURE(features[i], FEATURE_CLOCK_INFO)) {
Packit 577717
            sprintf(entry->name, "%s:graphics_clock", sanitized_name);
Packit 577717
            strncpy(entry->description, "Graphics clock domain (MHz).", PAPI_MAX_STR_LEN);
Packit 577717
            entry->options.clock = NVML_CLOCK_GRAPHICS;
Packit 577717
            entry->type = FEATURE_CLOCK_INFO;
Packit 577717
            entry++;
Packit 577717
Packit 577717
            sprintf(entry->name, "%s:sm_clock", sanitized_name);
Packit 577717
            strncpy(entry->description, "SM clock domain (MHz).", PAPI_MAX_STR_LEN);
Packit 577717
            entry->options.clock = NVML_CLOCK_SM;
Packit 577717
            entry->type = FEATURE_CLOCK_INFO;
Packit 577717
            entry++;
Packit 577717
Packit 577717
            sprintf(entry->name, "%s:memory_clock", sanitized_name);
Packit 577717
            strncpy(entry->description, "Memory clock domain (MHz).", PAPI_MAX_STR_LEN);
Packit 577717
            entry->options.clock = NVML_CLOCK_MEM;
Packit 577717
            entry->type = FEATURE_CLOCK_INFO;
Packit 577717
            entry++;
Packit 577717
        }
Packit 577717
Packit 577717
        if (HAS_FEATURE(features[i], FEATURE_ECC_LOCAL_ERRORS)) {
Packit 577717
            sprintf(entry->name, "%s:l1_single_ecc_errors", sanitized_name);
Packit 577717
            strncpy(entry->description, "L1 cache single bit ECC", PAPI_MAX_STR_LEN);
Packit 577717
            entry->options.ecc_opts = (struct local_ecc) {
Packit 577717
                .bits = NVML_SINGLE_BIT_ECC,
Packit 577717
                 .which_one = LOCAL_ECC_L1,
Packit 577717
            };
Packit 577717
            entry->type = FEATURE_ECC_LOCAL_ERRORS;
Packit 577717
            entry++;
Packit 577717
Packit 577717
            sprintf(entry->name, "%s:l2_single_ecc_errors", sanitized_name);
Packit 577717
            strncpy(entry->description, "L2 cache single bit ECC", PAPI_MAX_STR_LEN);
Packit 577717
            entry->options.ecc_opts = (struct local_ecc) {
Packit 577717
                .bits = NVML_SINGLE_BIT_ECC,
Packit 577717
                 .which_one = LOCAL_ECC_L2,
Packit 577717
            };
Packit 577717
            entry->type = FEATURE_ECC_LOCAL_ERRORS;
Packit 577717
            entry++;
Packit 577717
Packit 577717
            sprintf(entry->name, "%s:memory_single_ecc_errors", sanitized_name);
Packit 577717
            strncpy(entry->description, "Device memory single bit ECC", PAPI_MAX_STR_LEN);
Packit 577717
            entry->options.ecc_opts = (struct local_ecc) {
Packit 577717
                .bits = NVML_SINGLE_BIT_ECC,
Packit 577717
                 .which_one = LOCAL_ECC_MEM,
Packit 577717
            };
Packit 577717
            entry->type = FEATURE_ECC_LOCAL_ERRORS;
Packit 577717
            entry++;
Packit 577717
Packit 577717
            sprintf(entry->name, "%s:regfile_single_ecc_errors", sanitized_name);
Packit 577717
            strncpy(entry->description, "Register file single bit ECC", PAPI_MAX_STR_LEN);
Packit 577717
            entry->options.ecc_opts = (struct local_ecc) {
Packit 577717
                .bits = NVML_SINGLE_BIT_ECC,
Packit 577717
                 .which_one = LOCAL_ECC_REGFILE,
Packit 577717
            };
Packit 577717
            entry->type = FEATURE_ECC_LOCAL_ERRORS;
Packit 577717
            entry++;
Packit 577717
Packit 577717
            sprintf(entry->name, "%s:1l_double_ecc_errors", sanitized_name);
Packit 577717
            strncpy(entry->description, "L1 cache double bit ECC", PAPI_MAX_STR_LEN);
Packit 577717
            entry->options.ecc_opts = (struct local_ecc) {
Packit 577717
                .bits = NVML_DOUBLE_BIT_ECC,
Packit 577717
                 .which_one = LOCAL_ECC_L1,
Packit 577717
            };
Packit 577717
            entry->type = FEATURE_ECC_LOCAL_ERRORS;
Packit 577717
            entry++;
Packit 577717
Packit 577717
            sprintf(entry->name, "%s:l2_double_ecc_errors", sanitized_name);
Packit 577717
            strncpy(entry->description, "L2 cache double bit ECC", PAPI_MAX_STR_LEN);
Packit 577717
            entry->options.ecc_opts = (struct local_ecc) {
Packit 577717
                .bits = NVML_DOUBLE_BIT_ECC,
Packit 577717
                 .which_one = LOCAL_ECC_L2,
Packit 577717
            };
Packit 577717
            entry->type = FEATURE_ECC_LOCAL_ERRORS;
Packit 577717
            entry++;
Packit 577717
Packit 577717
            sprintf(entry->name, "%s:memory_double_ecc_errors", sanitized_name);
Packit 577717
            strncpy(entry->description, "Device memory double bit ECC", PAPI_MAX_STR_LEN);
Packit 577717
            entry->options.ecc_opts = (struct local_ecc) {
Packit 577717
                .bits = NVML_DOUBLE_BIT_ECC,
Packit 577717
                 .which_one = LOCAL_ECC_MEM,
Packit 577717
            };
Packit 577717
            entry->type = FEATURE_ECC_LOCAL_ERRORS;
Packit 577717
            entry++;
Packit 577717
Packit 577717
            sprintf(entry->name, "%s:regfile_double_ecc_errors", sanitized_name);
Packit 577717
            strncpy(entry->description, "Register file double bit ECC", PAPI_MAX_STR_LEN);
Packit 577717
            entry->options.ecc_opts = (struct local_ecc) {
Packit 577717
                .bits = NVML_DOUBLE_BIT_ECC,
Packit 577717
                 .which_one = LOCAL_ECC_REGFILE,
Packit 577717
            };
Packit 577717
            entry->type = FEATURE_ECC_LOCAL_ERRORS;
Packit 577717
            entry++;
Packit 577717
        }
Packit 577717
Packit 577717
        if (HAS_FEATURE(features[i], FEATURE_FAN_SPEED)) {
Packit 577717
            sprintf(entry->name, "%s:fan_speed", sanitized_name);
Packit 577717
            strncpy(entry->description, "The fan speed expressed as a percent of the maximum, i.e. full speed is 100%", PAPI_MAX_STR_LEN);
Packit 577717
            entry->type = FEATURE_FAN_SPEED;
Packit 577717
            entry++;
Packit 577717
        }
Packit 577717
Packit 577717
        if (HAS_FEATURE(features[i], FEATURE_MAX_CLOCK)) {
Packit 577717
            sprintf(entry->name, "%s:graphics_max_clock", sanitized_name);
Packit 577717
            strncpy(entry->description, "Maximal Graphics clock domain (MHz).", PAPI_MAX_STR_LEN);
Packit 577717
            entry->options.clock = NVML_CLOCK_GRAPHICS;
Packit 577717
            entry->type = FEATURE_MAX_CLOCK;
Packit 577717
            entry++;
Packit 577717
Packit 577717
            sprintf(entry->name, "%s:sm_max_clock", sanitized_name);
Packit 577717
            strncpy(entry->description, "Maximal SM clock domain (MHz).", PAPI_MAX_STR_LEN);
Packit 577717
            entry->options.clock = NVML_CLOCK_SM;
Packit 577717
            entry->type = FEATURE_MAX_CLOCK;
Packit 577717
            entry++;
Packit 577717
Packit 577717
            sprintf(entry->name, "%s:memory_max_clock", sanitized_name);
Packit 577717
            strncpy(entry->description, "Maximal Memory clock domain (MHz).", PAPI_MAX_STR_LEN);
Packit 577717
            entry->options.clock = NVML_CLOCK_MEM;
Packit 577717
            entry->type = FEATURE_MAX_CLOCK;
Packit 577717
            entry++;
Packit 577717
        }
Packit 577717
Packit 577717
        if (HAS_FEATURE(features[i], FEATURE_MEMORY_INFO)) {
Packit 577717
            sprintf(entry->name, "%s:total_memory", sanitized_name);
Packit 577717
            strncpy(entry->description, "Total installed FB memory (in bytes).", PAPI_MAX_STR_LEN);
Packit 577717
            entry->options.which_one = MEMINFO_TOTAL_MEMORY;
Packit 577717
            entry->type = FEATURE_MEMORY_INFO;
Packit 577717
            entry++;
Packit 577717
Packit 577717
            sprintf(entry->name, "%s:unallocated_memory", sanitized_name);
Packit 577717
            strncpy(entry->description, "Uncallocated FB memory (in bytes).", PAPI_MAX_STR_LEN);
Packit 577717
            entry->options.which_one = MEMINFO_UNALLOCED;
Packit 577717
            entry->type = FEATURE_MEMORY_INFO;
Packit 577717
            entry++;
Packit 577717
Packit 577717
            sprintf(entry->name, "%s:allocated_memory", sanitized_name);
Packit 577717
            strncpy(entry->description, "Allocated FB memory (in bytes). Note that the driver/GPU always sets aside a small amount of memory for bookkeeping.", PAPI_MAX_STR_LEN);
Packit 577717
            entry->options.which_one = MEMINFO_ALLOCED;
Packit 577717
            entry->type = FEATURE_MEMORY_INFO;
Packit 577717
            entry++;
Packit 577717
        }
Packit 577717
Packit 577717
        if (HAS_FEATURE(features[i], FEATURE_PERF_STATES)) {
Packit 577717
            sprintf(entry->name, "%s:pstate", sanitized_name);
Packit 577717
            strncpy(entry->description, "The performance state of the device.", PAPI_MAX_STR_LEN);
Packit 577717
            entry->type = FEATURE_PERF_STATES;
Packit 577717
            entry++;
Packit 577717
        }
Packit 577717
Packit 577717
        if (HAS_FEATURE(features[i], FEATURE_POWER)) {
Packit 577717
            sprintf(entry->name, "%s:power", sanitized_name);
Packit 577717
            // set the power event units value to "mW" for miliwatts
Packit 577717
            strncpy(entry->units, "mW", PAPI_MIN_STR_LEN);
Packit 577717
            strncpy(entry->description, "Power usage reading for the device, in miliwatts. This is the power draw (+/-5 watts) for the entire board: GPU, memory, etc.", PAPI_MAX_STR_LEN);
Packit 577717
            entry->type = FEATURE_POWER;
Packit 577717
            entry++;
Packit 577717
        }
Packit 577717
Packit 577717
        if (HAS_FEATURE(features[i], FEATURE_TEMP)) {
Packit 577717
            sprintf(entry->name, "%s:temperature", sanitized_name);
Packit 577717
            strncpy(entry->description, "Current temperature readings for the device, in degrees C.", PAPI_MAX_STR_LEN);
Packit 577717
            entry->type = FEATURE_TEMP;
Packit 577717
            entry++;
Packit 577717
        }
Packit 577717
Packit 577717
        if (HAS_FEATURE(features[i], FEATURE_ECC_TOTAL_ERRORS)) {
Packit 577717
            sprintf(entry->name, "%s:total_ecc_errors", sanitized_name);
Packit 577717
            strncpy(entry->description, "Total single bit errors.", PAPI_MAX_STR_LEN);
Packit 577717
            entry->options.ecc_opts = (struct local_ecc) {
Packit 577717
                .bits = NVML_SINGLE_BIT_ECC,
Packit 577717
            };
Packit 577717
            entry->type = FEATURE_ECC_TOTAL_ERRORS;
Packit 577717
            entry++;
Packit 577717
Packit 577717
            sprintf(entry->name, "%s:total_ecc_errors", sanitized_name);
Packit 577717
            strncpy(entry->description, "Total double bit errors.", PAPI_MAX_STR_LEN);
Packit 577717
            entry->options.ecc_opts = (struct local_ecc) {
Packit 577717
                .bits = NVML_DOUBLE_BIT_ECC,
Packit 577717
            };
Packit 577717
            entry->type = FEATURE_ECC_TOTAL_ERRORS;
Packit 577717
            entry++;
Packit 577717
        }
Packit 577717
Packit 577717
        if (HAS_FEATURE(features[i], FEATURE_UTILIZATION)) {
Packit 577717
            sprintf(entry->name, "%s:gpu_utilization", sanitized_name);
Packit 577717
            strncpy(entry->description, "Percent of time over the past second during which one or more kernels was executing on the GPU.", PAPI_MAX_STR_LEN);
Packit 577717
            entry->options.which_one = GPU_UTILIZATION;
Packit 577717
            entry->type = FEATURE_UTILIZATION;
Packit 577717
            entry++;
Packit 577717
Packit 577717
            sprintf(entry->name, "%s:memory_utilization", sanitized_name);
Packit 577717
            strncpy(entry->description, "Percent of time over the past second during which global (device) memory was being read or written.", PAPI_MAX_STR_LEN);
Packit 577717
            entry->options.which_one = MEMORY_UTILIZATION;
Packit 577717
            entry->type = FEATURE_UTILIZATION;
Packit 577717
            entry++;
Packit 577717
        }
Packit 577717
Packit 577717
        if (HAS_FEATURE(features[i], FEATURE_POWER_MANAGEMENT)) {
Packit 577717
            sprintf(entry->name, "%s:power_management_limit", sanitized_name);
Packit 577717
            // set the power event units value to "mW" for milliwatts
Packit 577717
            strncpy(entry->units, "mW", PAPI_MIN_STR_LEN);
Packit 577717
            strncpy(entry->description, "Power management limit in milliwatts associated with the device.  The power limit defines the upper boundary for the cards power draw. If the cards total power draw reaches this limit the power management algorithm kicks in. This should be writable (with appropriate privileges) on supported Kepler or later (unit milliWatts). ", PAPI_MAX_STR_LEN);
Packit 577717
            entry->type = FEATURE_POWER_MANAGEMENT;
Packit 577717
            entry++;
Packit 577717
        }
Packit 577717
        if (HAS_FEATURE(features[i], FEATURE_NVML_POWER_MANAGEMENT_LIMIT_CONSTRAINT_MIN)) {
Packit 577717
            sprintf(entry->name, "%s:power_management_limit_constraint_min", sanitized_name);
Packit 577717
            strncpy(entry->units, "mW", PAPI_MIN_STR_LEN);
Packit 577717
            strncpy(entry->description, "The minimum power management limit in milliwatts.", PAPI_MAX_STR_LEN);
Packit 577717
            entry->type = FEATURE_NVML_POWER_MANAGEMENT_LIMIT_CONSTRAINT_MIN;
Packit 577717
            entry++;
Packit 577717
        }
Packit 577717
Packit 577717
        if (HAS_FEATURE(features[i], FEATURE_NVML_POWER_MANAGEMENT_LIMIT_CONSTRAINT_MAX)) {
Packit 577717
            sprintf(entry->name, "%s:power_management_limit_constraint_max", sanitized_name);
Packit 577717
            strncpy(entry->units, "mW", PAPI_MIN_STR_LEN);
Packit 577717
            strncpy(entry->description, "The maximum power management limit in milliwatts.", PAPI_MAX_STR_LEN);
Packit 577717
            entry->type = FEATURE_NVML_POWER_MANAGEMENT_LIMIT_CONSTRAINT_MAX;
Packit 577717
            entry++;
Packit 577717
        }
Packit 577717
Packit 577717
        strncpy(names[i], name, sizeof(names[0]) - 1);
Packit 577717
        names[i][sizeof(names[0]) - 1] = '\0';
Packit 577717
    }
Packit 577717
}
Packit 577717
Packit 577717
/** Initialize hardware counters, setup the function vector table
Packit 577717
 * and get hardware information, this routine is called when the
Packit 577717
 * PAPI process is initialized (IE PAPI_library_init)
Packit 577717
 */
Packit 577717
int
Packit 577717
_papi_nvml_init_component(int cidx)
Packit 577717
{
Packit 577717
    SUBDBG("Entry: cidx: %d\n", cidx);
Packit 577717
    nvmlReturn_t ret;
Packit 577717
    cudaError_t cuerr;
Packit 577717
    int papi_errorcode;
Packit 577717
Packit 577717
    int cuda_count = 0;
Packit 577717
    unsigned int nvml_count = 0;
Packit 577717
Packit 577717
    /* link in the cuda and nvml libraries and resolve the symbols we need to use */
Packit 577717
    if (linkCudaLibraries() != PAPI_OK) {
Packit 577717
        SUBDBG("Dynamic link of CUDA libraries failed, component will be disabled.\n");
Packit 577717
        SUBDBG("See disable reason in papi_component_avail output for more details.\n");
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
Packit 577717
    ret = (*nvmlInitPtr)();
Packit 577717
    if (NVML_SUCCESS != ret) {
Packit 577717
        strcpy(_nvml_vector.cmp_info.disabled_reason, "The NVIDIA managament library failed to initialize.");
Packit 577717
        return PAPI_ENOSUPP;
Packit 577717
    }
Packit 577717
Packit 577717
    cuerr = (*cuInitPtr)(0);
Packit 577717
    if (cudaSuccess != cuerr) {
Packit 577717
        strcpy(_nvml_vector.cmp_info.disabled_reason, "The CUDA library failed to initialize.");
Packit 577717
        return PAPI_ENOSUPP;
Packit 577717
    }
Packit 577717
Packit 577717
    /* Figure out the number of CUDA devices in the system */
Packit 577717
    ret = (*nvmlDeviceGetCountPtr)(&nvml_count);
Packit 577717
    if (NVML_SUCCESS != ret) {
Packit 577717
        strcpy(_nvml_vector.cmp_info.disabled_reason, "Unable to get a count of devices from the NVIDIA managament library.");
Packit 577717
        return PAPI_ENOSUPP;
Packit 577717
    }
Packit 577717
Packit 577717
    cuerr = (*cudaGetDeviceCountPtr)(&cuda_count);
Packit 577717
    if (cudaSuccess != cuerr) {
Packit 577717
        strcpy(_nvml_vector.cmp_info.disabled_reason, "Unable to get a device count from CUDA.");
Packit 577717
        return PAPI_ENOSUPP;
Packit 577717
    }
Packit 577717
Packit 577717
    /* We can probably recover from this, when we're clever */
Packit 577717
    if ((cuda_count > 0) && (nvml_count != (unsigned int)cuda_count)) {
Packit 577717
        strcpy(_nvml_vector.cmp_info.disabled_reason, "CUDA and the NVIDIA managament library have different device counts.");
Packit 577717
        return PAPI_ENOSUPP;
Packit 577717
    }
Packit 577717
Packit 577717
    device_count = cuda_count;
Packit 577717
    SUBDBG("Need to setup NVML with %d devices\n", device_count);
Packit 577717
Packit 577717
    /* A per device representation of what events are present */
Packit 577717
    features = (int*)papi_malloc(sizeof(int) * device_count);
Packit 577717
Packit 577717
    /* Handles to each device */
Packit 577717
    devices = (nvmlDevice_t*)papi_malloc(sizeof(nvmlDevice_t) * device_count);
Packit 577717
Packit 577717
    /* For each device, store the intial power value to enable reset if power is altered */
Packit 577717
    power_management_initial_limit = (unsigned int*)papi_malloc(sizeof(unsigned int) * device_count);
Packit 577717
    power_management_limit_constraint_min = (unsigned int*)papi_malloc(sizeof(unsigned int) * device_count);
Packit 577717
    power_management_limit_constraint_max = (unsigned int*)papi_malloc(sizeof(unsigned int) * device_count);
Packit 577717
Packit 577717
    /* Figure out what events are supported on each card. */
Packit 577717
    if ((papi_errorcode = detectDevices()) != PAPI_OK) {
Packit 577717
        papi_free(features);
Packit 577717
        papi_free(devices);
Packit 577717
        sprintf(_nvml_vector.cmp_info.disabled_reason, "An error occured in device feature detection, please check your NVIDIA Management Library and CUDA install.");
Packit 577717
        return PAPI_ENOSUPP;
Packit 577717
    }
Packit 577717
Packit 577717
    /* The assumption is that if everything went swimmingly in detectDevices,
Packit 577717
        all nvml calls here should be fine. */
Packit 577717
    createNativeEvents();
Packit 577717
Packit 577717
    /* Export the total number of events available */
Packit 577717
    _nvml_vector.cmp_info.num_native_events = num_events;
Packit 577717
Packit 577717
    /* Export the component id */
Packit 577717
    _nvml_vector.cmp_info.CmpIdx = cidx;
Packit 577717
Packit 577717
    /* Export the number of 'counters' */
Packit 577717
    _nvml_vector.cmp_info.num_cntrs = num_events;
Packit 577717
    _nvml_vector.cmp_info.num_mpx_cntrs = num_events;
Packit 577717
Packit 577717
    return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/*
Packit 577717
 * Link the necessary CUDA libraries to use the cuda component.  If any of them can not be found, then
Packit 577717
 * the CUDA component will just be disabled.  This is done at runtime so that a version of PAPI built
Packit 577717
 * with the CUDA component can be installed and used on systems which have the CUDA libraries installed
Packit 577717
 * and on systems where these libraries are not installed.
Packit 577717
 */
Packit 577717
static int
Packit 577717
linkCudaLibraries()
Packit 577717
{
Packit 577717
    /* Attempt to guess if we were statically linked to libc, if so bail */
Packit 577717
    if (_dl_non_dynamic_init != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML component does not support statically linking of libc.", PAPI_MAX_STR_LEN);
Packit 577717
        return PAPI_ENOSUPP;
Packit 577717
    }
Packit 577717
Packit 577717
    /* Need to link in the cuda libraries, if not found disable the component */
Packit 577717
    dl1 = dlopen("libcuda.so", RTLD_NOW | RTLD_GLOBAL);
Packit 577717
    if (!dl1) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "CUDA library libcuda.so not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    cuInitPtr = dlsym(dl1, "cuInit");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "CUDA function cuInit not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
Packit 577717
    dl2 = dlopen("libcudart.so", RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
Packit 577717
    if (!dl2) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "CUDA runtime library libcudart.so not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    cudaGetDevicePtr = dlsym(dl2, "cudaGetDevice");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "CUDART function cudaGetDevice not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    cudaGetDeviceCountPtr = dlsym(dl2, "cudaGetDeviceCount");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "CUDART function cudaGetDeviceCount not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    cudaDeviceGetPCIBusIdPtr = dlsym(dl2, "cudaDeviceGetPCIBusId");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "CUDART function cudaDeviceGetPCIBusId not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
Packit 577717
    dl3 = dlopen("libnvidia-ml.so", RTLD_NOW | RTLD_GLOBAL);
Packit 577717
    if (!dl3) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML runtime library libnvidia-ml.so not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    nvmlDeviceGetClockInfoPtr = dlsym(dl3, "nvmlDeviceGetClockInfo");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML function nvmlDeviceGetClockInfo not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    nvmlErrorStringPtr = dlsym(dl3, "nvmlErrorString");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML function nvmlErrorString not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    nvmlDeviceGetDetailedEccErrorsPtr = dlsym(dl3, "nvmlDeviceGetDetailedEccErrors");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML function nvmlDeviceGetDetailedEccErrors not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    nvmlDeviceGetFanSpeedPtr = dlsym(dl3, "nvmlDeviceGetFanSpeed");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML function nvmlDeviceGetFanSpeed not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    nvmlDeviceGetMemoryInfoPtr = dlsym(dl3, "nvmlDeviceGetMemoryInfo");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML function nvmlDeviceGetMemoryInfo not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    nvmlDeviceGetPerformanceStatePtr = dlsym(dl3, "nvmlDeviceGetPerformanceState");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML function nvmlDeviceGetPerformanceState not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    nvmlDeviceGetPowerUsagePtr = dlsym(dl3, "nvmlDeviceGetPowerUsage");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML function nvmlDeviceGetPowerUsage not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    nvmlDeviceGetTemperaturePtr = dlsym(dl3, "nvmlDeviceGetTemperature");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML function nvmlDeviceGetTemperature not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    nvmlDeviceGetTotalEccErrorsPtr = dlsym(dl3, "nvmlDeviceGetTotalEccErrors");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML function nvmlDeviceGetTotalEccErrors not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    nvmlDeviceGetUtilizationRatesPtr = dlsym(dl3, "nvmlDeviceGetUtilizationRates");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML function nvmlDeviceGetUtilizationRates not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    nvmlDeviceGetHandleByIndexPtr = dlsym(dl3, "nvmlDeviceGetHandleByIndex");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML function nvmlDeviceGetHandleByIndex not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    nvmlDeviceGetPciInfoPtr = dlsym(dl3, "nvmlDeviceGetPciInfo");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML function nvmlDeviceGetPciInfo not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    nvmlDeviceGetNamePtr = dlsym(dl3, "nvmlDeviceGetName");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML function nvmlDeviceGetName not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    nvmlDeviceGetInforomVersionPtr = dlsym(dl3, "nvmlDeviceGetInforomVersion");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML function nvmlDeviceGetInforomVersion not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    nvmlDeviceGetEccModePtr = dlsym(dl3, "nvmlDeviceGetEccMode");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML function nvmlDeviceGetEccMode not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    nvmlInitPtr = dlsym(dl3, "nvmlInit");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML function nvmlInit not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    nvmlDeviceGetCountPtr = dlsym(dl3, "nvmlDeviceGetCount");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML function nvmlDeviceGetCount not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    nvmlShutdownPtr = dlsym(dl3, "nvmlShutdown");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML function nvmlShutdown not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    nvmlDeviceGetPowerManagementLimitPtr = dlsym(dl3, "nvmlDeviceGetPowerManagementLimit");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML function nvmlDeviceGetPowerManagementLimit not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    nvmlDeviceSetPowerManagementLimitPtr = dlsym(dl3, "nvmlDeviceSetPowerManagementLimit");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML function nvmlDeviceSetPowerManagementLimit not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    nvmlDeviceGetPowerManagementLimitConstraintsPtr = dlsym(dl3, "nvmlDeviceGetPowerManagementLimitConstraints");
Packit 577717
    if (dlerror() != NULL) {
Packit 577717
        strncpy(_nvml_vector.cmp_info.disabled_reason, "NVML function nvmlDeviceGetPowerManagementLimitConstraints not found.", PAPI_MAX_STR_LEN);
Packit 577717
        return (PAPI_ENOSUPP);
Packit 577717
    }
Packit 577717
    return (PAPI_OK);
Packit 577717
}
Packit 577717
Packit 577717
/** Setup a counter control state.
Packit 577717
 *   In general a control state holds the hardware info for an
Packit 577717
 *   EventSet.
Packit 577717
 */
Packit 577717
Packit 577717
int
Packit 577717
_papi_nvml_init_control_state(hwd_control_state_t * ctl)
Packit 577717
{
Packit 577717
    SUBDBG("nvml_init_control_state... %p\n", ctl);
Packit 577717
    nvml_control_state_t *nvml_ctl = (nvml_control_state_t *) ctl;
Packit 577717
    memset(nvml_ctl, 0, sizeof(nvml_control_state_t));
Packit 577717
Packit 577717
    return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/** Triggered by eventset operations like add or remove */
Packit 577717
int
Packit 577717
_papi_nvml_update_control_state(hwd_control_state_t *ctl,
Packit 577717
                                NativeInfo_t *native,
Packit 577717
                                int count,
Packit 577717
                                hwd_context_t *ctx)
Packit 577717
{
Packit 577717
    SUBDBG("Enter: ctl: %p, ctx: %p\n", ctl, ctx);
Packit 577717
    int i, index;
Packit 577717
Packit 577717
    nvml_control_state_t *nvml_ctl = (nvml_control_state_t *) ctl;
Packit 577717
    (void) ctx;
Packit 577717
Packit 577717
    /* if no events, return */
Packit 577717
    if (count == 0) return PAPI_OK;
Packit 577717
Packit 577717
    for (i = 0; i < count; i++) {
Packit 577717
        index = native[i].ni_event;
Packit 577717
        nvml_ctl->which_counter[i] = index;
Packit 577717
        /* We have no constraints on event position, so any event */
Packit 577717
        /* can be in any slot.                                    */
Packit 577717
        native[i].ni_position = i;
Packit 577717
    }
Packit 577717
    nvml_ctl->num_events = count;
Packit 577717
    return PAPI_OK;
Packit 577717
}
Packit 577717
/** Triggered by PAPI_start() */
Packit 577717
int
Packit 577717
_papi_nvml_start(hwd_context_t *ctx, hwd_control_state_t *ctl)
Packit 577717
{
Packit 577717
    SUBDBG("Enter: ctx: %p, ctl: %p\n", ctx, ctl);
Packit 577717
Packit 577717
    (void) ctx;
Packit 577717
    (void) ctl;
Packit 577717
Packit 577717
    /* anything that would need to be set at counter start time */
Packit 577717
Packit 577717
    /* reset */
Packit 577717
    /* start the counting */
Packit 577717
Packit 577717
    return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/** Triggered by PAPI_stop() */
Packit 577717
int
Packit 577717
_papi_nvml_stop(hwd_context_t *ctx, hwd_control_state_t *ctl)
Packit 577717
{
Packit 577717
    SUBDBG("Enter: ctx: %p, ctl: %p\n", ctx, ctl);
Packit 577717
Packit 577717
    int i;
Packit 577717
    (void) ctx;
Packit 577717
    (void) ctl;
Packit 577717
    int ret;
Packit 577717
Packit 577717
    nvml_control_state_t* nvml_ctl = (nvml_control_state_t*) ctl;
Packit 577717
Packit 577717
    for (i = 0; i < nvml_ctl->num_events; i++) {
Packit 577717
        if (PAPI_OK !=
Packit 577717
                (ret = nvml_hardware_read(&nvml_ctl->counter[i],
Packit 577717
                                          nvml_ctl->which_counter[i])))
Packit 577717
            return ret;
Packit 577717
Packit 577717
    }
Packit 577717
Packit 577717
    return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/** Triggered by PAPI_read() */
Packit 577717
int
Packit 577717
_papi_nvml_read(hwd_context_t *ctx, hwd_control_state_t *ctl,
Packit 577717
                long long **events, int flags)
Packit 577717
{
Packit 577717
    SUBDBG("Enter: ctx: %p, flags: %d\n", ctx, flags);
Packit 577717
Packit 577717
    (void) ctx;
Packit 577717
    (void) flags;
Packit 577717
    int i;
Packit 577717
    int ret;
Packit 577717
    nvml_control_state_t* nvml_ctl = (nvml_control_state_t*) ctl;
Packit 577717
Packit 577717
    for (i = 0; i < nvml_ctl->num_events; i++) {
Packit 577717
        if (PAPI_OK !=
Packit 577717
                (ret = nvml_hardware_read(&nvml_ctl->counter[i],
Packit 577717
                                          nvml_ctl->which_counter[i])))
Packit 577717
            return ret;
Packit 577717
Packit 577717
    }
Packit 577717
    /* return pointer to the values we read */
Packit 577717
    *events = nvml_ctl->counter;
Packit 577717
    return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/** Triggered by PAPI_write(), but only if the counters are running */
Packit 577717
/*    otherwise, the updated state is written to ESI->hw_start      */
Packit 577717
int
Packit 577717
_papi_nvml_write(hwd_context_t *ctx, hwd_control_state_t *ctl, long long *events)
Packit 577717
{
Packit 577717
    SUBDBG("Enter: ctx: %p, ctl: %p\n", ctx, ctl);
Packit 577717
    (void) ctx;
Packit 577717
    nvml_control_state_t* nvml_ctl = (nvml_control_state_t*) ctl;
Packit 577717
    int i;
Packit 577717
    int ret;
Packit 577717
Packit 577717
    /* You can change ECC mode and compute exclusivity modes on the cards */
Packit 577717
    /* But I don't see this as a function of a PAPI component at this time */
Packit 577717
    /* All implementation issues aside. */
Packit 577717
Packit 577717
    // Currently POWER_MANAGEMENT can be written
Packit 577717
    for (i = 0; i < nvml_ctl->num_events; i++) {
Packit 577717
        if (PAPI_OK != (ret = nvml_hardware_write(&events[i], nvml_ctl->which_counter[i])))
Packit 577717
            return ret;
Packit 577717
    }
Packit 577717
Packit 577717
    /* return pointer to the values we read */
Packit 577717
    return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/** Triggered by PAPI_reset() but only if the EventSet is currently running */
Packit 577717
/*  If the eventset is not currently running, then the saved value in the   */
Packit 577717
/*  EventSet is set to zero without calling this routine.                   */
Packit 577717
int
Packit 577717
_papi_nvml_reset(hwd_context_t * ctx, hwd_control_state_t * ctl)
Packit 577717
{
Packit 577717
    SUBDBG("Enter: ctx: %p, ctl: %p\n", ctx, ctl);
Packit 577717
Packit 577717
    (void) ctx;
Packit 577717
    (void) ctl;
Packit 577717
Packit 577717
    /* Reset the hardware */
Packit 577717
    nvml_hardware_reset();
Packit 577717
Packit 577717
    return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/** Triggered by PAPI_shutdown() */
Packit 577717
int
Packit 577717
_papi_nvml_shutdown_component()
Packit 577717
{
Packit 577717
    SUBDBG("Enter:\n");
Packit 577717
    nvml_hardware_reset();
Packit 577717
    if (nvml_native_table != NULL) papi_free(nvml_native_table);
Packit 577717
    if (devices != NULL) papi_free(devices);
Packit 577717
    if (features != NULL) papi_free(features);
Packit 577717
    if (power_management_initial_limit) papi_free(power_management_initial_limit);
Packit 577717
    if (power_management_limit_constraint_min) papi_free(power_management_limit_constraint_min);
Packit 577717
    if (power_management_limit_constraint_max) papi_free(power_management_limit_constraint_max);
Packit 577717
   (*nvmlShutdownPtr)();
Packit 577717
Packit 577717
    device_count = 0;
Packit 577717
    num_events = 0;
Packit 577717
Packit 577717
    // close the dynamic libraries needed by this component (opened in the init component call)
Packit 577717
    if (dl3) dlclose(dl3); dl3=NULL;
Packit 577717
    if (dl2) dlclose(dl2); dl2=NULL;
Packit 577717
    if (dl1) dlclose(dl1); dl1=NULL;
Packit 577717
Packit 577717
    return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/** Called at thread shutdown */
Packit 577717
int
Packit 577717
_papi_nvml_shutdown_thread(hwd_context_t *ctx)
Packit 577717
{
Packit 577717
    SUBDBG("Enter: ctx: %p\n", ctx);
Packit 577717
Packit 577717
    (void) ctx;
Packit 577717
Packit 577717
    /* Last chance to clean up thread */
Packit 577717
Packit 577717
    return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/** This function sets various options in the component
Packit 577717
  @param code valid are PAPI_SET_DEFDOM, PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL and PAPI_SET_INHERIT
Packit 577717
 */
Packit 577717
int
Packit 577717
_papi_nvml_ctl(hwd_context_t * ctx, int code, _papi_int_option_t * option)
Packit 577717
{
Packit 577717
    SUBDBG("Enter: ctx: %p, code: %d\n", ctx, code);
Packit 577717
Packit 577717
    (void) ctx;
Packit 577717
    (void) code;
Packit 577717
    (void) option;
Packit 577717
Packit 577717
    /* FIXME.  This should maybe set up more state, such as which counters are active and */
Packit 577717
    /*         counter mappings. */
Packit 577717
Packit 577717
    return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/** This function has to set the bits needed to count different domains
Packit 577717
  In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER
Packit 577717
  By default return PAPI_EINVAL if none of those are specified
Packit 577717
  and PAPI_OK with success
Packit 577717
  PAPI_DOM_USER is only user context is counted
Packit 577717
  PAPI_DOM_KERNEL is only the Kernel/OS context is counted
Packit 577717
  PAPI_DOM_OTHER  is Exception/transient mode (like user TLB misses)
Packit 577717
  PAPI_DOM_ALL   is all of the domains
Packit 577717
 */
Packit 577717
int
Packit 577717
_papi_nvml_set_domain(hwd_control_state_t * cntrl, int domain)
Packit 577717
{
Packit 577717
    SUBDBG("Enter: cntrl: %p, domain: %d\n", cntrl, domain);
Packit 577717
Packit 577717
    (void) cntrl;
Packit 577717
Packit 577717
    int found = 0;
Packit 577717
Packit 577717
    if (PAPI_DOM_USER & domain) {
Packit 577717
        SUBDBG(" PAPI_DOM_USER \n");
Packit 577717
        found = 1;
Packit 577717
    }
Packit 577717
    if (PAPI_DOM_KERNEL & domain) {
Packit 577717
        SUBDBG(" PAPI_DOM_KERNEL \n");
Packit 577717
        found = 1;
Packit 577717
    }
Packit 577717
    if (PAPI_DOM_OTHER & domain) {
Packit 577717
        SUBDBG(" PAPI_DOM_OTHER \n");
Packit 577717
        found = 1;
Packit 577717
    }
Packit 577717
    if (PAPI_DOM_ALL & domain) {
Packit 577717
        SUBDBG(" PAPI_DOM_ALL \n");
Packit 577717
        found = 1;
Packit 577717
    }
Packit 577717
    if (!found)
Packit 577717
        return (PAPI_EINVAL);
Packit 577717
Packit 577717
    return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/**************************************************************/
Packit 577717
/* Naming functions, used to translate event numbers to names */
Packit 577717
/**************************************************************/
Packit 577717
Packit 577717
/** Enumerate Native Events
Packit 577717
 *   @param EventCode is the event of interest
Packit 577717
 *   @param modifier is one of PAPI_ENUM_FIRST, PAPI_ENUM_EVENTS
Packit 577717
 *  If your component has attribute masks then these need to
Packit 577717
 *   be handled here as well.
Packit 577717
 */
Packit 577717
int
Packit 577717
_papi_nvml_ntv_enum_events(unsigned int *EventCode, int modifier)
Packit 577717
{
Packit 577717
    int index;
Packit 577717
Packit 577717
    switch (modifier) {
Packit 577717
Packit 577717
    /* return EventCode of first event */
Packit 577717
    case PAPI_ENUM_FIRST:
Packit 577717
        /* return the first event that we support */
Packit 577717
Packit 577717
        *EventCode = 0;
Packit 577717
        return PAPI_OK;
Packit 577717
Packit 577717
    /* return EventCode of next available event */
Packit 577717
    case PAPI_ENUM_EVENTS:
Packit 577717
        index = *EventCode;
Packit 577717
Packit 577717
        /* Make sure we are in range */
Packit 577717
        if (index < num_events - 1) {
Packit 577717
Packit 577717
            /* This assumes a non-sparse mapping of the events */
Packit 577717
            *EventCode = *EventCode + 1;
Packit 577717
            return PAPI_OK;
Packit 577717
        } else {
Packit 577717
            return PAPI_ENOEVNT;
Packit 577717
        }
Packit 577717
        break;
Packit 577717
Packit 577717
    default:
Packit 577717
        return PAPI_EINVAL;
Packit 577717
    }
Packit 577717
Packit 577717
    return PAPI_EINVAL;
Packit 577717
}
Packit 577717
Packit 577717
/** Takes a native event code and passes back the name
Packit 577717
 * @param EventCode is the native event code
Packit 577717
 * @param name is a pointer for the name to be copied to
Packit 577717
 * @param len is the size of the name string
Packit 577717
 */
Packit 577717
int
Packit 577717
_papi_nvml_ntv_code_to_name(unsigned int EventCode, char *name, int len)
Packit 577717
{
Packit 577717
    SUBDBG("Entry: EventCode: %#x, name: %s, len: %d\n", EventCode, name, len);
Packit 577717
    int index;
Packit 577717
Packit 577717
    index = EventCode;
Packit 577717
Packit 577717
    /* Make sure we are in range */
Packit 577717
    if (index >= num_events) return PAPI_ENOEVNT;
Packit 577717
Packit 577717
    strncpy(name, nvml_native_table[index].name, len);
Packit 577717
Packit 577717
    return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/** Takes a native event code and passes back the event description
Packit 577717
 * @param EventCode is the native event code
Packit 577717
 * @param descr is a pointer for the description to be copied to
Packit 577717
 * @param len is the size of the descr string
Packit 577717
 */
Packit 577717
int
Packit 577717
_papi_nvml_ntv_code_to_descr(unsigned int EventCode, char *descr, int len)
Packit 577717
{
Packit 577717
    int index;
Packit 577717
    index = EventCode;
Packit 577717
Packit 577717
    if (index >= num_events) return PAPI_ENOEVNT;
Packit 577717
Packit 577717
    strncpy(descr, nvml_native_table[index].description, len);
Packit 577717
Packit 577717
    return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/** Takes a native event code and passes back the event info
Packit 577717
 * @param EventCode is the native event code
Packit 577717
 * @param info is a pointer for the info to be copied to
Packit 577717
 */
Packit 577717
int
Packit 577717
_papi_nvml_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info)
Packit 577717
{
Packit 577717
Packit 577717
    int index = EventCode;
Packit 577717
Packit 577717
    if ((index < 0) || (index >= num_events)) return PAPI_ENOEVNT;
Packit 577717
Packit 577717
    strncpy(info->symbol, nvml_native_table[index].name, sizeof(info->symbol) - 1);
Packit 577717
    info->symbol[sizeof(info->symbol) - 1] = '\0';
Packit 577717
Packit 577717
    strncpy(info->units, nvml_native_table[index].units, sizeof(info->units) - 1);
Packit 577717
    info->units[sizeof(info->units) - 1] = '\0';
Packit 577717
Packit 577717
    strncpy(info->long_descr, nvml_native_table[index].description, sizeof(info->long_descr) - 1);
Packit 577717
    info->long_descr[sizeof(info->long_descr) - 1] = '\0';
Packit 577717
Packit 577717
//  info->data_type = nvml_native_table[index].return_type;
Packit 577717
Packit 577717
    return PAPI_OK;
Packit 577717
}
Packit 577717
Packit 577717
/** Vector that points to entry points for our component */
Packit 577717
papi_vector_t _nvml_vector = {
Packit 577717
    .cmp_info = {
Packit 577717
        /* default component information */
Packit 577717
        /* (unspecified values are initialized to 0) */
Packit 577717
Packit 577717
        .name = "nvml",
Packit 577717
        .short_name = "nvml",
Packit 577717
        .version = "1.0",
Packit 577717
        .description = "NVML provides the API for monitoring NVIDIA hardware (power usage, temperature, fan speed, etc)",
Packit 577717
        .support_version = "n/a",
Packit 577717
        .kernel_version = "n/a",
Packit 577717
Packit 577717
        .num_preset_events = 0,
Packit 577717
        .num_native_events = 0, /* set by init_component */
Packit 577717
        .default_domain = PAPI_DOM_USER,
Packit 577717
        .available_domains = PAPI_DOM_USER,
Packit 577717
        .default_granularity = PAPI_GRN_THR,
Packit 577717
        .available_granularities = PAPI_GRN_THR,
Packit 577717
        .hardware_intr_sig = PAPI_INT_SIGNAL,
Packit 577717
Packit 577717
        /* component specific cmp_info initializations */
Packit 577717
        .hardware_intr = 0,
Packit 577717
        .precise_intr = 0,
Packit 577717
        .posix1b_timers = 0,
Packit 577717
        .kernel_profile = 0,
Packit 577717
        .kernel_multiplex = 0,
Packit 577717
        .fast_counter_read = 0,
Packit 577717
        .fast_real_timer = 0,
Packit 577717
        .fast_virtual_timer = 0,
Packit 577717
        .attach = 0,
Packit 577717
        .attach_must_ptrace = 0,
Packit 577717
        .cntr_umasks = 0,
Packit 577717
        .cpu = 0,
Packit 577717
        .inherit = 0,
Packit 577717
    },
Packit 577717
Packit 577717
    /* sizes of framework-opaque component-private structures */
Packit 577717
    .size = {
Packit 577717
        .context = sizeof(nvml_context_t),
Packit 577717
        .control_state = sizeof(nvml_control_state_t),
Packit 577717
        .reg_value = sizeof(nvml_register_t),
Packit 577717
        // .reg_alloc = sizeof ( nvml_reg_alloc_t ),
Packit 577717
    },
Packit 577717
Packit 577717
    /* function pointers */
Packit 577717
Packit 577717
    /* Used for general PAPI interactions */
Packit 577717
    .start =                _papi_nvml_start,
Packit 577717
    .stop =                 _papi_nvml_stop,
Packit 577717
    .read =                 _papi_nvml_read,
Packit 577717
    .reset =                _papi_nvml_reset,
Packit 577717
    .write =                _papi_nvml_write,
Packit 577717
    .init_component =       _papi_nvml_init_component,
Packit 577717
    .init_thread =          _papi_nvml_init_thread,
Packit 577717
    .init_control_state =   _papi_nvml_init_control_state,
Packit 577717
    .update_control_state = _papi_nvml_update_control_state,
Packit 577717
    .ctl =                  _papi_nvml_ctl,
Packit 577717
    .shutdown_thread =      _papi_nvml_shutdown_thread,
Packit 577717
    .shutdown_component =   _papi_nvml_shutdown_component,
Packit 577717
    .set_domain =           _papi_nvml_set_domain,
Packit 577717
    .cleanup_eventset =     NULL,
Packit 577717
    /* called in add_native_events() */
Packit 577717
    .allocate_registers =   NULL,
Packit 577717
Packit 577717
    /* Used for overflow/profiling */
Packit 577717
    .dispatch_timer =       NULL,
Packit 577717
    .get_overflow_address = NULL,
Packit 577717
    .stop_profiling =       NULL,
Packit 577717
    .set_overflow =         NULL,
Packit 577717
    .set_profile =          NULL,
Packit 577717
Packit 577717
    /* Name Mapping Functions */
Packit 577717
    .ntv_enum_events =   _papi_nvml_ntv_enum_events,
Packit 577717
    .ntv_name_to_code  = NULL,
Packit 577717
    .ntv_code_to_name =  _papi_nvml_ntv_code_to_name,
Packit 577717
    .ntv_code_to_descr = _papi_nvml_ntv_code_to_descr,
Packit 577717
    .ntv_code_to_info = _papi_nvml_ntv_code_to_info,
Packit 577717
Packit 577717
};
Packit 577717