Blame src/components/nvml/tests/nvml_power_limiting_test.cu

Packit 577717
/****************************/
Packit 577717
/* THIS IS OPEN SOURCE CODE */
Packit 577717
/****************************/
Packit 577717
Packit 577717
/**
Packit 577717
 * @file    HelloWorld.c
Packit 577717
 * CVS:     $Id$
Packit 577717
 * @author Asim YarKhan (yarkhan@icl.utk.edu) HelloWorld altered to test power capping (October 2017) 
Packit 577717
 * @author Heike Jagode (jagode@icl.utk.edu)
Packit 577717
 * Mods:  <your name here> <your email address>
Packit 577717
 *
Packit 577717
 * @brief
Packit 577717
Packit 577717
 * This file is a very simple HelloWorld C example which serves
Packit 577717
 * (together with its Makefile) as a guideline on how to add tests to
Packit 577717
 * components.  This file tests the ability to do power control using
Packit 577717
 * NVML.
Packit 577717
Packit 577717
 * The papi configure and papi Makefile will take care of the
Packit 577717
 * compilation of the component tests (if all tests are added to a
Packit 577717
 * directory named 'tests' in the specific component dir).  See
Packit 577717
 * components/README for more details.
Packit 577717
 *
Packit 577717
 * The string "Hello World!" is mangled and then restored.
Packit 577717
 */
Packit 577717
Packit 577717
#include <cuda.h>
Packit 577717
#include <stdio.h>
Packit 577717
#include "papi.h"
Packit 577717
#include "papi_test.h"
Packit 577717
Packit 577717
#define PAPI
Packit 577717
Packit 577717
// Prototypes
Packit 577717
__global__ void helloWorld( char* );
Packit 577717
Packit 577717
// Host function
Packit 577717
int main( int argc, char** argv )
Packit 577717
{
Packit 577717
Packit 577717
#ifdef PAPI
Packit 577717
#define NUM_EVENTS 1
Packit 577717
    int retval, i;
Packit 577717
    int EventSet = PAPI_NULL;
Packit 577717
    long long values[NUM_EVENTS];
Packit 577717
    /* REPLACE THE EVENT NAME 'PAPI_FP_OPS' WITH A CUDA EVENT
Packit 577717
       FOR THE CUDA DEVICE YOU ARE RUNNING ON.
Packit 577717
       RUN papi_native_avail to get a list of CUDA events that are
Packit 577717
       supported on your machine */
Packit 577717
    // e.g. on a P100 nvml:::Tesla_P100-SXM2-16GB:power
Packit 577717
    char *EventName[NUM_EVENTS];
Packit 577717
    int events[NUM_EVENTS];
Packit 577717
    int eventCount = 0;
Packit 577717
    const PAPI_component_info_t *cmpinfo;
Packit 577717
    char event_name[PAPI_MAX_STR_LEN];
Packit 577717
Packit 577717
    /* PAPI Initialization */
Packit 577717
    retval = PAPI_library_init( PAPI_VER_CURRENT );
Packit 577717
    if( retval != PAPI_VER_CURRENT ) fprintf( stderr, "PAPI_library_init failed\n" );
Packit 577717
Packit 577717
    printf( "PAPI_VERSION : %4d %6d %7d\n",
Packit 577717
            PAPI_VERSION_MAJOR( PAPI_VERSION ),
Packit 577717
            PAPI_VERSION_MINOR( PAPI_VERSION ),
Packit 577717
            PAPI_VERSION_REVISION( PAPI_VERSION ) );
Packit 577717
Packit 577717
    int numcmp = PAPI_num_components();
Packit 577717
    // printf( "Searching for nvml component among %d components\n", numcmp );
Packit 577717
    int cid = 0;
Packit 577717
    for( cid=0; cid
Packit 577717
        cmpinfo = PAPI_get_component_info( cid );
Packit 577717
        // printf( "Component %d (%d): %s: %d events\n", cid, cmpinfo->CmpIdx, cmpinfo->name, cmpinfo->num_native_events );
Packit 577717
        if ( cmpinfo == NULL )
Packit 577717
            test_fail( __FILE__, __LINE__,"PAPI_get_component_info failed\n",-1 );
Packit 577717
        else if ( strstr( cmpinfo->name, "nvml" ) )
Packit 577717
            break;
Packit 577717
    }
Packit 577717
    if ( cid==numcmp )
Packit 577717
        test_skip( __FILE__, __LINE__,"Component nvml is not present\n",-1 );
Packit 577717
Packit 577717
    printf( "nvml component found: Component Index %d: %s: %d events\n", cmpinfo->CmpIdx, cmpinfo->name, cmpinfo->num_native_events );
Packit 577717
    if ( cmpinfo->disabled )
Packit 577717
        test_skip( __FILE__,__LINE__,"Component nvml is disabled", 0 );
Packit 577717
Packit 577717
    int code = PAPI_NATIVE_MASK;
Packit 577717
    int ii=0;
Packit 577717
    int event_modifier = PAPI_ENUM_FIRST;
Packit 577717
    for ( ii=0; ii<cmpinfo->num_native_events; ii++ ) {
Packit 577717
        retval = PAPI_enum_cmp_event( &code, event_modifier, cid );
Packit 577717
        event_modifier = PAPI_ENUM_EVENTS;
Packit 577717
        if ( retval != PAPI_OK ) test_fail( __FILE__, __LINE__, "PAPI_event_code_to_name", retval );
Packit 577717
        retval = PAPI_event_code_to_name( code, event_name );
Packit 577717
        // printf( "Look at event %d %d %s \n", ii, code, event_name );
Packit 577717
        if ( strstr( event_name, "power_management_limit" ) )
Packit 577717
            break;
Packit 577717
    }
Packit 577717
    if ( ii==cmpinfo->num_native_events )
Packit 577717
        test_skip( __FILE__,__LINE__,"Component nvml does not have a power_management_limit event", 0 );
Packit 577717
    printf( "nvml power_management_limit event found (%s)\n", event_name );
Packit 577717
Packit 577717
    EventName[0] = event_name;
Packit 577717
Packit 577717
    /* convert PAPI native events to PAPI code */
Packit 577717
    for( i = 0; i < NUM_EVENTS; i++ ) {
Packit 577717
        retval = PAPI_event_name_to_code( ( char * )EventName[i], &events[i] );
Packit 577717
        if( retval != PAPI_OK )
Packit 577717
            test_fail( __FILE__,__LINE__,"PAPI_event_name_to_code failed", retval );
Packit 577717
        eventCount++;
Packit 577717
        // printf( "Event: %s: Code: %#x\n", EventName[i], events[i] );
Packit 577717
    }
Packit 577717
Packit 577717
    /* if we did not find any valid events, just report test failed. */
Packit 577717
    if ( eventCount == 0 )
Packit 577717
        test_skip( __FILE__,__LINE__,"No valid events found", retval );
Packit 577717
Packit 577717
    retval = PAPI_create_eventset( &EventSet );
Packit 577717
    if( retval != PAPI_OK )
Packit 577717
        test_fail( __FILE__,__LINE__,"PAPI_create_eventset failed", retval );
Packit 577717
Packit 577717
    retval = PAPI_add_events( EventSet, events, eventCount );
Packit 577717
    if( retval != PAPI_OK )
Packit 577717
        test_fail( __FILE__,__LINE__,"PAPI_add_events failed", retval );
Packit 577717
#endif
Packit 577717
Packit 577717
    int j;
Packit 577717
    int device_count;
Packit 577717
    int cuda_device;
Packit 577717
Packit 577717
    cudaGetDeviceCount( &device_count );
Packit 577717
    printf( "Found %d cuda devices\n", device_count );
Packit 577717
Packit 577717
Packit 577717
///////////////////////   AYK
Packit 577717
    for ( cuda_device = 0; cuda_device < device_count; cuda_device++ ) {
Packit 577717
        // for ( cuda_device = 0; cuda_device < 1; cuda_device++ ) {
Packit 577717
        printf( "cuda_device %d is being used\n", cuda_device );
Packit 577717
        cudaSetDevice( cuda_device );
Packit 577717
Packit 577717
#ifdef PAPI
Packit 577717
        retval = PAPI_start( EventSet );
Packit 577717
        if( retval != PAPI_OK )
Packit 577717
            test_fail( __FILE__,__LINE__,"PAPI_start failed", retval );
Packit 577717
Packit 577717
        retval = PAPI_read( EventSet, values );
Packit 577717
        if( retval != PAPI_OK ) fprintf( stderr, "PAPI_read failed\n" );
Packit 577717
        for( i = 0; i < eventCount; i++ )
Packit 577717
            printf( "%s = %lld (read initial power management limit)\n", EventName[i], values[i]);
Packit 577717
        long long int initial_power_management_limit = values[0];
Packit 577717
Packit 577717
        if ( cuda_device==0 ) {
Packit 577717
            printf("On device_num %d the power_management_limit is going to be reduced by 30\n", cuda_device);
Packit 577717
            // values[0] = 235000
Packit 577717
            values[0] = initial_power_management_limit - 30;
Packit 577717
            retval = PAPI_write( EventSet, values );
Packit 577717
            if ( retval!=PAPI_OK ) {
Packit 577717
                test_skip( __FILE__,__LINE__,"Attempted write of power_management_limit failed:  Possible reasons: Insufficient permissions; Power management unavailable. Outside min/max limits", retval );
Packit 577717
            } else {
Packit 577717
                printf( "Set power_management_limit to %llu milliWatts\n", values[0] );
Packit 577717
            }
Packit 577717
        }
Packit 577717
            
Packit 577717
Packit 577717
Packit 577717
#endif
Packit 577717
Packit 577717
        // desired output
Packit 577717
        char str[] = "Hello World!";
Packit 577717
Packit 577717
        // mangle contents of output
Packit 577717
        // the null character is left intact for simplicity
Packit 577717
        for(j = 0; j < 12; j++) 
Packit 577717
            str[j] -= j;
Packit 577717
        printf( "This mangled string need to be fixed=%s\n", str );
Packit 577717
Packit 577717
        // allocate memory on the device
Packit 577717
        char *d_str;
Packit 577717
        size_t size = sizeof( str );
Packit 577717
        cudaMalloc( ( void** )&d_str, size );
Packit 577717
Packit 577717
        // copy the string to the device
Packit 577717
        cudaMemcpy( d_str, str, size, cudaMemcpyHostToDevice );
Packit 577717
Packit 577717
        // set the grid and block sizes
Packit 577717
        dim3 dimGrid( 2 ); // one block per word
Packit 577717
        dim3 dimBlock( sizeof( str )/2 ); // one thread per character
Packit 577717
Packit 577717
        // invoke the kernel
Packit 577717
        helloWorld<<< dimGrid, dimBlock >>>( d_str );
Packit 577717
Packit 577717
        // retrieve the results from the device
Packit 577717
        cudaMemcpy( str, d_str, size, cudaMemcpyDeviceToHost );
Packit 577717
Packit 577717
        // free up the allocated memory on the device
Packit 577717
        cudaFree( d_str );
Packit 577717
Packit 577717
        printf( "Device %d Unmangled string = %s\n", cuda_device, str );
Packit 577717
Packit 577717
#ifdef PAPI
Packit 577717
        if ( cuda_device==0 ) {
Packit 577717
            retval = PAPI_read( EventSet, values );
Packit 577717
            if( retval != PAPI_OK ) fprintf( stderr, "PAPI_read failed\n" );
Packit 577717
            for( i = 0; i < eventCount; i++ )
Packit 577717
                printf( "%s = %lld (read power management limit after reducing it... was it reduced?) \n", EventName[i], values[i] );
Packit 577717
            
Packit 577717
            if ( values[0] != initial_power_management_limit - 30 ) {
Packit 577717
                printf( "Mismatch: power_management_limit on device %d set to %llu but read as %llu\n", cuda_device, initial_power_management_limit-30, values[0] );
Packit 577717
                test_fail( __FILE__,__LINE__,"Mismatch: power_management_limit on device set to one value but read as a different value", -1 );
Packit 577717
                
Packit 577717
            }
Packit 577717
Packit 577717
            // AYK papi_reset
Packit 577717
            long long resetvalues[NUM_EVENTS];
Packit 577717
            resetvalues[0] = initial_power_management_limit;
Packit 577717
            retval = PAPI_write( EventSet, resetvalues );
Packit 577717
            retval = PAPI_stop( EventSet, values );
Packit 577717
        }
Packit 577717
#endif
Packit 577717
        
Packit 577717
    }
Packit 577717
Packit 577717
    test_pass( __FILE__);
Packit 577717
    return 0;
Packit 577717
}
Packit 577717
Packit 577717
Packit 577717
// Device kernel
Packit 577717
__global__ void
Packit 577717
helloWorld( char* str )
Packit 577717
{
Packit 577717
    // determine where in the thread grid we are
Packit 577717
    int idx = blockIdx.x * blockDim.x + threadIdx.x;
Packit 577717
    // unmangle output
Packit 577717
    str[idx] += idx;
Packit 577717
}
Packit 577717