PAPI  5.0.1.0
papi_hl.c
Go to the documentation of this file.
00001 /****************************/
00002 /* THIS IS OPEN SOURCE CODE */
00003 /****************************/
00004 
00016 #include "papi.h"
00017 #include "papi_internal.h"
00018 #include "papi_memory.h"
00019 #include <string.h>
00020 
00021 /* high level papi functions*/
00022 
00023 /*
00024  * Which high-level interface are we using?
00025  */
00026 #define HL_START_COUNTERS   1
00027 #define HL_FLIPS        2
00028 #define HL_IPC          3
00029 #define HL_FLOPS        4
00030 
00031 /* Definitions for reading */
00032 #define PAPI_HL_READ        1
00033 #define PAPI_HL_ACCUM       2
00034 
00038 typedef struct _HighLevelInfo
00039 {
00040     int EventSet;                  
00041     short int num_evts;
00042     short int running;
00043     long long initial_time;            
00044     float total_proc_time;             
00045     float total_ins;               
00046 } HighLevelInfo;
00047 
00048 int _hl_rate_calls( float *real_time, float *proc_time, long long *ins,
00049                     float *rate, unsigned int EVENT, HighLevelInfo * state );
00050 void _internal_cleanup_hl_info( HighLevelInfo * state );
00051 int _internal_check_state( HighLevelInfo ** state );
00052 int _internal_start_hl_counters( HighLevelInfo * state );
00053 int _internal_hl_read_cnts( long long *values, int array_len, int flag );
00054 
00055 /* CHANGE LOG:
00056   - ksl 10/17/03
00057    Pretty much a complete rewrite of the high level interface.  Now
00058    the interface is thread safe and you don't have to worry as much
00059    about mixing the various high level calls.
00060 
00061   - dkt 11/19/01:
00062    After much discussion with users and developers, removed FMA and SLOPE
00063    fudge factors. SLOPE was not being used, and we decided the place to
00064    apply FMA was at a higher level where there could be a better understanding
00065    of platform discrepancies and code implications.
00066    ALL PAPI CALLS NOW RETURN EXACTLY WHAT THE HARDWARE REPORTS
00067   - dkt 08/14/01:
00068    Added reinitialization of values and proc_time to new reinit code.
00069    Added SLOPE and FMA constants to correct for systemic errors on a
00070    platform-by-platform basis.
00071    SLOPE is a factor subtracted from flpins on each call to compensate
00072    for platform overhead in the call.
00073    FMA is a shifter that doubles floating point counts on platforms that
00074    count FMA as one op instead of two.
00075    NOTE: We are making the FLAWED assumption that ALL flpins are FMA!
00076    This will result in counts that are TOO HIGH on the affected platforms
00077    in instances where the code is NOT mostly FMA.
00078   - dkt 08/01/01:
00079    NOTE: Calling semantics have changed!
00080    Now, if flpins < 0 (an invalid value) a PAPI_reset is issued to reset the
00081    counter values. The internal start time is also reset. This should be a 
00082    benign change, exept in the rare case where a user passes an uninitialized
00083    (and possibly negative) value for flpins to the routine *AFTER* it has been
00084    called the first time. This is unlikely, since the first call clears and
00085    returns th is value.
00086   - dkt 08/01/01:
00087    Internal sequencing changes:
00088    -- initial PAPI_get_real_usec() call moved above PAPI_start to avoid unwanted flops.
00089    -- PAPI_accum() replaced with PAPI_start() / PAPI_stop pair for same reason.
00090 */
00091 
00097 int
00098 _internal_check_state( HighLevelInfo ** outgoing )
00099 {
00100     int retval;
00101     HighLevelInfo *state = NULL;
00102 
00103     /* Only allow one thread at a time in here */
00104     if ( init_level == PAPI_NOT_INITED ) {
00105         retval = PAPI_library_init( PAPI_VER_CURRENT );
00106         if ( retval != PAPI_VER_CURRENT ) {
00107             return ( retval );
00108         } else {
00109             _papi_hwi_lock( HIGHLEVEL_LOCK );
00110             init_level = PAPI_HIGH_LEVEL_INITED;
00111             _papi_hwi_unlock( HIGHLEVEL_LOCK );
00112         }
00113     }
00114 
00115     /*
00116      * Do we have the thread specific data setup yet?
00117      */
00118     if ( ( retval =
00119            PAPI_get_thr_specific( PAPI_HIGH_LEVEL_TLS, ( void * ) &state ) )
00120          != PAPI_OK || state == NULL ) {
00121         state = ( HighLevelInfo * ) papi_malloc( sizeof ( HighLevelInfo ) );
00122         if ( state == NULL )
00123             return ( PAPI_ENOMEM );
00124 
00125         memset( state, 0, sizeof ( HighLevelInfo ) );
00126         state->EventSet = -1;
00127 
00128         if ( ( retval = PAPI_create_eventset( &state->EventSet ) ) != PAPI_OK )
00129             return ( retval );
00130 
00131         if ( ( retval =
00132                PAPI_set_thr_specific( PAPI_HIGH_LEVEL_TLS,
00133                                       state ) ) != PAPI_OK )
00134             return ( retval );
00135     }
00136     *outgoing = state;
00137     return ( PAPI_OK );
00138 }
00139 
00143 int
00144 _internal_start_hl_counters( HighLevelInfo * state )
00145 {
00146     return ( PAPI_start( state->EventSet ) );
00147 }
00148 
00149 void
00150 _internal_cleanup_hl_info( HighLevelInfo * state )
00151 {
00152     state->num_evts = 0;
00153     state->running = 0;
00154     state->initial_time = -1;
00155     state->total_proc_time = 0;
00156     state->total_ins = 0;
00157     return;
00158 }
00159 
00202 int
00203 PAPI_flips( float *rtime, float *ptime, long long *flpins, float *mflips )
00204 {
00205     if ( rtime == NULL || ptime == NULL || flpins == NULL || mflips == NULL )
00206         return PAPI_EINVAL;
00207 
00208     HighLevelInfo *state = NULL;
00209     int retval;
00210 
00211     if ( ( retval = _internal_check_state( &state ) ) != PAPI_OK ) {
00212         return ( retval );
00213         }
00214 
00215     if ( ( retval =
00216            _hl_rate_calls( rtime, ptime, flpins, mflips,
00217                            ( unsigned int ) PAPI_FP_INS, state ) ) != PAPI_OK )
00218         return ( retval );
00219 
00220     return ( PAPI_OK );
00221 }
00222 
00271 int
00272 PAPI_flops( float *rtime, float *ptime, long long *flpops, float *mflops )
00273 {
00274     if ( rtime == NULL || ptime == NULL || flpops == NULL || mflops == NULL )
00275         return PAPI_EINVAL;
00276 
00277     HighLevelInfo *state = NULL;
00278     int retval;
00279 
00280     if ( ( retval = _internal_check_state( &state ) ) != PAPI_OK )
00281         return ( retval );
00282 
00283     if ( ( retval =
00284            _hl_rate_calls( rtime, ptime, flpops, mflops,
00285                            ( unsigned int ) PAPI_FP_OPS, state ) ) != PAPI_OK )
00286         return ( retval );
00287 
00288     return ( PAPI_OK );
00289 }
00290 
00325 int
00326 PAPI_ipc( float *rtime, float *ptime, long long *ins, float *ipc )
00327 {
00328     if ( rtime == NULL || ptime == NULL || ins == NULL || ipc == NULL )
00329         return PAPI_EINVAL;
00330 
00331     HighLevelInfo *state = NULL;
00332     int retval;
00333 
00334     if ( ( retval = _internal_check_state( &state ) ) != PAPI_OK )
00335         return ( retval );
00336 
00337     return _hl_rate_calls( rtime, ptime, ins, ipc,
00338                            ( unsigned int ) PAPI_TOT_INS, state );
00339 }
00340 
00341 int
00342 _hl_rate_calls( float *real_time, float *proc_time, long long *ins, 
00343         float *rate, unsigned int EVENT, HighLevelInfo *state )
00344 {
00345      long long values[2] = { 0, 0 };
00346      int retval = 0;
00347      int level = 0;
00348 
00349      if ( EVENT == ( unsigned int ) PAPI_FP_INS )
00350     level = HL_FLIPS;
00351      else if ( EVENT == ( unsigned int ) PAPI_TOT_INS )
00352     level = HL_IPC;
00353      else if ( EVENT == ( unsigned int ) PAPI_FP_OPS )
00354     level = HL_FLOPS;
00355 
00356      if ( state->running != 0 && state->running != level ) {
00357     return PAPI_EINVAL;
00358      }
00359 
00360      if ( state->running == 0 ) {
00361         if ( PAPI_query_event( ( int ) EVENT ) != PAPI_OK ) {
00362        return PAPI_ENOEVNT;
00363         }
00364 
00365     if ((retval=PAPI_add_event(state->EventSet,(int)EVENT))!=PAPI_OK ) {
00366        _internal_cleanup_hl_info( state );
00367        PAPI_cleanup_eventset( state->EventSet );
00368        return retval;
00369     }
00370 
00371     if ( PAPI_query_event( ( int ) PAPI_TOT_CYC ) != PAPI_OK ) {
00372        return PAPI_ENOEVNT;
00373     }
00374 
00375     if ((retval=PAPI_add_event(state->EventSet,(int)PAPI_TOT_CYC))!=PAPI_OK) {
00376        _internal_cleanup_hl_info( state );
00377        PAPI_cleanup_eventset( state->EventSet );
00378        return retval;
00379     }
00380 
00381     state->initial_time = PAPI_get_real_usec(  );
00382     if ( ( retval = PAPI_start( state->EventSet ) ) != PAPI_OK ) {
00383        return retval;
00384     }
00385 
00386     state->running = ( short ) level;
00387 
00388      } else {
00389         if ( ( retval = PAPI_stop( state->EventSet, values ) ) != PAPI_OK ) {
00390        return retval;
00391         }
00392 
00393     /* Use Multiplication because it is much faster */
00394     *real_time = (float) ((double) (PAPI_get_real_usec() -
00395                     state->initial_time ) * .000001 );
00396     *proc_time = (float) ((double) values[1] * .000001 /
00397              (( _papi_hwi_system_info.hw_info.cpu_max_mhz == 0 ) ?
00398                              1 : _papi_hwi_system_info.hw_info.cpu_max_mhz ) );
00399 
00400     if ( *proc_time > 0 ) {
00401        *rate = (float) ((float)values[0] *
00402                ( EVENT == ( unsigned int ) PAPI_TOT_INS ? 1 :
00403                    _papi_hwi_system_info.hw_info.cpu_max_mhz ) /
00404                    (float) ( values[1] == 0 ? 1 : values[1] ) );
00405     }
00406 
00407     state->total_proc_time += *proc_time;
00408     state->total_ins += ( float ) values[0];
00409     *proc_time = state->total_proc_time;
00410     *ins = ( long long ) state->total_ins;
00411     if ( ( retval = PAPI_start( state->EventSet ) ) != PAPI_OK ) {
00412        state->running = 0;
00413        return retval;
00414     }
00415      }
00416 
00417      return PAPI_OK;
00418 }
00419 
00454 int
00455 PAPI_num_counters( void )
00456 {
00457     int retval;
00458     HighLevelInfo *tmp = NULL;
00459 
00460     /* Make sure the Library is initialized, etc... */
00461     if ( ( retval = _internal_check_state( &tmp ) ) != PAPI_OK )
00462         return ( retval );
00463 
00464     return ( PAPI_get_opt( PAPI_MAX_HWCTRS, NULL ) );
00465 }
00466 
00510 int
00511 PAPI_start_counters( int *events, int array_len )
00512 {
00513     int i, retval;
00514     HighLevelInfo *state = NULL;
00515 
00516     if ( events == NULL || array_len <= 0 )
00517         return PAPI_EINVAL;
00518 
00519     if ( ( retval = _internal_check_state( &state ) ) != PAPI_OK )
00520         return ( retval );
00521 
00522     if ( state->running != 0 )
00523         return ( PAPI_EINVAL );
00524 
00525     /* load events to the new EventSet */
00526     for ( i = 0; i < array_len; i++ ) {
00527         retval = PAPI_add_event( state->EventSet, events[i] );
00528         if ( retval == PAPI_EISRUN )
00529             return ( retval );
00530 
00531         if ( retval ) {
00532             /* remove any prior events that may have been added 
00533              * and cleanup the high level information
00534              */
00535             _internal_cleanup_hl_info( state );
00536             PAPI_cleanup_eventset( state->EventSet );
00537             return ( retval );
00538         }
00539     }
00540     /* start the EventSet */
00541     if ( ( retval = _internal_start_hl_counters( state ) ) == PAPI_OK ) {
00542         state->running = HL_START_COUNTERS;
00543         state->num_evts = ( short ) array_len;
00544     }
00545     return ( retval );
00546 }
00547 
00548 /*========================================================================*/
00549 /* int PAPI_read_counters(long long *values, int array_len)      */
00550 /*                                                                        */
00551 /* Read the running counters into the values array. This call             */
00552 /* implicitly initializes the internal counters to zero and allows        */
00553 /* them continue to run upon return.                                      */
00554 /*========================================================================*/
00555 
00556 int
00557 _internal_hl_read_cnts( long long *values, int array_len, int flag )
00558 {
00559     int retval;
00560     HighLevelInfo *state = NULL;
00561 
00562     if ( ( retval = _internal_check_state( &state ) ) != PAPI_OK )
00563         return ( retval );
00564 
00565     if ( state->running != HL_START_COUNTERS || array_len < state->num_evts )
00566         return ( PAPI_EINVAL );
00567 
00568     if ( flag == PAPI_HL_ACCUM )
00569         return ( PAPI_accum( state->EventSet, values ) );
00570     else if ( flag == PAPI_HL_READ ) {
00571         if ( ( retval = PAPI_read( state->EventSet, values ) ) != PAPI_OK )
00572             return ( retval );
00573         return ( PAPI_reset( state->EventSet ) );
00574     }
00575 
00576     /* Invalid flag passed in */
00577     return ( PAPI_EINVAL );
00578 }
00579 
00623 int
00624 PAPI_read_counters( long long *values, int array_len )
00625 {
00626     return ( _internal_hl_read_cnts( values, array_len, PAPI_HL_READ ) );
00627 }
00628 
00629 
00673 int
00674 PAPI_accum_counters( long long *values, int array_len )
00675 {
00676     if ( values == NULL || array_len <= 0 )
00677         return PAPI_EINVAL;
00678 
00679     return ( _internal_hl_read_cnts( values, array_len, PAPI_HL_ACCUM ) );
00680 }
00681 
00720 int
00721 PAPI_stop_counters( long long *values, int array_len )
00722 {
00723     int retval;
00724     HighLevelInfo *state = NULL;
00725 
00726     if ( values == NULL || array_len <= 0 )
00727         return PAPI_EINVAL;
00728 
00729     if ( ( retval = _internal_check_state( &state ) ) != PAPI_OK )
00730         return ( retval );
00731 
00732     if ( state->running == 0 )
00733         return ( PAPI_ENOTRUN );
00734 
00735     if ( state->running == HL_FLOPS || state->running == HL_FLIPS ||
00736          state->running == HL_IPC ) {
00737         long long tmp_values[2];
00738         retval = PAPI_stop( state->EventSet, tmp_values );
00739     } else if ( state->running != HL_START_COUNTERS ||
00740                 array_len < state->num_evts )
00741         return ( PAPI_EINVAL );
00742     else
00743         retval = PAPI_stop( state->EventSet, values );
00744 
00745     if ( retval == PAPI_OK ) {
00746         _internal_cleanup_hl_info( state );
00747         PAPI_cleanup_eventset( state->EventSet );
00748     }
00749     APIDBG( "PAPI_stop_counters returns %d\n", retval );
00750     return retval;
00751 }
00752 
00753 void
00754 _papi_hwi_shutdown_highlevel(  )
00755 {
00756     HighLevelInfo *state = NULL;
00757 
00758     if ( PAPI_get_thr_specific( PAPI_HIGH_LEVEL_TLS, ( void * ) &state ) ==
00759          PAPI_OK ) {
00760         if ( state )
00761             papi_free( state );
00762     }
00763 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines