Blame src/components/cuda/tests/cuda_ld_preload_example.c

Packit Service a1973e
/*
Packit Service a1973e
  Example of using LD_PRELOAD with the CUDA component.  
Packit Service a1973e
  Asim YarKhan
Packit Service a1973e
Packit Service a1973e
  This is designed to work with the simpleMultiGPU_no_counters binary
Packit Service a1973e
  in the PAPI CUDA component tests directory.  First trace the library
Packit Service a1973e
  calls in simpleMultiGPU_no_counters binary using ltrace.  Note in
Packit Service a1973e
  the ltrace output that the CUDA C APIs are different from the CUDA
Packit Service a1973e
  calls visible to nvcc. Then figure out appropriate place to attach
Packit Service a1973e
  the PAPI calls.  The initialization is attached to the first entry
Packit Service a1973e
  to cudaSetDevice.  Each cudaSetDevice is also used to setup the PAPI
Packit Service a1973e
  events for that device.  It was harder to figure out where to attach
Packit Service a1973e
  the PAPI_start.  After running some tests, I attached it to the 18th
Packit Service a1973e
  invocation of gettimeofday (kind of arbitrary! Sorry!).  The
Packit Service a1973e
  PAPI_stop was attached to the first invocation of cudaFreeHost.
Packit Service a1973e
Packit Service a1973e
*/
Packit Service a1973e
Packit Service a1973e
#define _GNU_SOURCE
Packit Service a1973e
Packit Service a1973e
#include <stdio.h>
Packit Service a1973e
#include <dlfcn.h>
Packit Service a1973e
Packit Service a1973e
#include "papi.h"
Packit Service a1973e
Packit Service a1973e
#define MAXDEVICES 5
Packit Service a1973e
int EventSet = PAPI_NULL;
Packit Service a1973e
int devseen[MAXDEVICES] = {0};
Packit Service a1973e
Packit Service a1973e
static void *dl1;
Packit Service a1973e
int (*PAPI_library_init_ptr)(int version); /**< initialize the PAPI library */
Packit Service a1973e
int (*PAPI_create_eventset_ptr)(int *EventSet); /**< create a new empty PAPI event set */
Packit Service a1973e
int (*PAPI_add_named_event_ptr)(int EventSet, char *EventName); /**< add an event by name to a PAPI event set */
Packit Service a1973e
int (*PAPI_start_ptr)(int EventSet); /**< start counting hardware events in an event set */
Packit Service a1973e
int (*PAPI_stop_ptr)(int EventSet, long long * values); /**< stop counting hardware events in an event set and return current events */
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
int cudaSetDevice(int devnum, int n1, int n2, int n3, void *ptr1) 
Packit Service a1973e
{
Packit Service a1973e
    static int onetime = 0;
Packit Service a1973e
    int retval, retval_cudaSetDevice;
Packit Service a1973e
    //printf("cudaSetDevice wrapper %d\n", devnum);
Packit Service a1973e
    if ( onetime==0 ) {
Packit Service a1973e
        onetime=1;
Packit Service a1973e
        // Load the papi library dynamically and read the relevant functions
Packit Service a1973e
        dl1 = dlopen( "libpapi.so", RTLD_NOW | RTLD_GLOBAL );
Packit Service a1973e
        if ( dl1==NULL ) printf("Intercept cudaSetDevice: Cannot load libpapi.so\n");
Packit Service a1973e
        PAPI_library_init_ptr = dlsym( dl1, "PAPI_library_init" );
Packit Service a1973e
        PAPI_create_eventset_ptr = dlsym( dl1, "PAPI_create_eventset" );
Packit Service a1973e
        PAPI_add_named_event_ptr = dlsym( dl1, "PAPI_add_named_event" );
Packit Service a1973e
        PAPI_start_ptr = dlsym( dl1, "PAPI_start" );
Packit Service a1973e
        PAPI_stop_ptr = dlsym( dl1, "PAPI_stop" );
Packit Service a1973e
        // Start using PAPI
Packit Service a1973e
        printf("Intercept cudaSetDevice: Initializing PAPI on device %d\n", devnum);
Packit Service a1973e
        retval = (PAPI_library_init_ptr)( PAPI_VER_CURRENT );
Packit Service a1973e
        if( retval != PAPI_VER_CURRENT ) fprintf( stdout, "PAPI_library_init failed\n" );
Packit Service a1973e
        printf( "PAPI version: %d.%d.%d\n", PAPI_VERSION_MAJOR( PAPI_VERSION ), PAPI_VERSION_MINOR( PAPI_VERSION ), PAPI_VERSION_REVISION( PAPI_VERSION ) );
Packit Service a1973e
        retval = (PAPI_create_eventset_ptr)( &EventSet );
Packit Service a1973e
        if( retval != PAPI_OK ) fprintf( stdout, "PAPI_create_eventset failed\n" );
Packit Service a1973e
    }
Packit Service a1973e
    int (*original_function)(int devnum, int n1, int n2, int n3, void *ptr1);
Packit Service a1973e
    original_function = dlsym(RTLD_NEXT, "cudaSetDevice");
Packit Service a1973e
    retval_cudaSetDevice = (*original_function)( devnum, n1, n2, n3, ptr1 );
Packit Service a1973e
    if ( devseen[devnum]==0 ) {
Packit Service a1973e
        devseen[devnum]=1;
Packit Service a1973e
        char tmpEventName[120];
Packit Service a1973e
        printf("Intercept cudaSetDevice: Attaching events for device on device %d\n", devnum);
Packit Service a1973e
        snprintf( tmpEventName, 110, "cuda:::device:%d:%s", devnum, "inst_executed" );
Packit Service a1973e
        retval = (PAPI_add_named_event_ptr)( EventSet, tmpEventName );
Packit Service a1973e
        if (retval!=PAPI_OK) printf( "Could not add event %s\n", tmpEventName );
Packit Service a1973e
    }
Packit Service a1973e
    return retval_cudaSetDevice;
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
Packit Service a1973e
int gettimeofday(void *ptr1, void *ptr2)
Packit Service a1973e
{
Packit Service a1973e
    static int onetime = 0;
Packit Service a1973e
    onetime++;
Packit Service a1973e
    // printf("gettimeofday onetime %d\n", onetime);
Packit Service a1973e
    // Use above print statement to determine that the N-th gettime of day works
Packit Service a1973e
    if ( onetime==17 ) {
Packit Service a1973e
        printf("Intercept gettimeofday: Attaching PAPI_start to the %d th call to gettimeofday (this may need to be adjusted)\n", onetime);
Packit Service a1973e
        int retval = (PAPI_start_ptr)( EventSet );
Packit Service a1973e
        printf("Starting PAPI\n");
Packit Service a1973e
        if( retval!=PAPI_OK ) fprintf( stdout, "PAPI_start failed\n" );
Packit Service a1973e
    }
Packit Service a1973e
    int (*original_function)(void *ptr1, void *ptr2);
Packit Service a1973e
    original_function = dlsym(RTLD_NEXT, "gettimeofday");
Packit Service a1973e
    return (*original_function)(ptr1, ptr2);
Packit Service a1973e
}
Packit Service a1973e
Packit Service a1973e
int cudaFreeHost(void *ptr1, void *ptr2, int n1, int n2, void *ptr3) 
Packit Service a1973e
{
Packit Service a1973e
    static int onetime = 0;
Packit Service a1973e
    long long values[10];
Packit Service a1973e
    int retval, devnum;
Packit Service a1973e
    onetime++;
Packit Service a1973e
    if ( onetime==1 ) {
Packit Service a1973e
        printf("Intercept cudaFreeHost: Used to get PAPI results\n" );
Packit Service a1973e
        retval = (PAPI_stop_ptr)( EventSet, values );
Packit Service a1973e
        if( retval != PAPI_OK )  fprintf( stderr, "PAPI_stop failed\n" );
Packit Service a1973e
        for( devnum = 0; devnum < MAXDEVICES && devseen[devnum]==1  ; devnum++ )
Packit Service a1973e
            printf( "PAPI counterValue: cuda::device:%d:%s: %12lld \n", devnum, "inst_executed", values[devnum] );
Packit Service a1973e
    }
Packit Service a1973e
    int (*original_function)(void *ptr1, void *ptr2, int n1, int n2, void *ptr3);
Packit Service a1973e
    original_function = dlsym(RTLD_NEXT, "cudaFreeHost");
Packit Service a1973e
    return (*original_function)(ptr1, ptr2, n1, n2, ptr3);
Packit Service a1973e
}
Packit Service a1973e