|
PAPI
5.0.1.0
|
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 }