|
PAPI
5.0.1.0
|
00001 /* 00002 * File: prof_utils.c 00003 * CVS: $Id$ 00004 * Author: Dan Terpstra 00005 * terpstra@cs.utk.edu 00006 * Mods: <your name here> 00007 * <your email address> 00008 */ 00009 00010 /* This file contains utility functions useful for all profiling tests 00011 It can be used by: 00012 - profile.c, 00013 - sprofile.c, 00014 - profile_pthreads.c, 00015 - profile_twoevents.c, 00016 - earprofile.c, 00017 - future profiling tests. 00018 */ 00019 00020 #include "papi_test.h" 00021 #include "prof_utils.h" 00022 00023 /* variables global to profiling tests */ 00024 long long **values; 00025 char event_name[PAPI_MAX_STR_LEN]; 00026 int PAPI_event; 00027 int EventSet = PAPI_NULL; 00028 void *profbuf[5]; 00029 00030 /* This function does the generic initialization stuff found at the top of most 00031 profile tests (most tests in general). This includes: 00032 - setting the QUIET flag; 00033 - initing the PAPI library; 00034 - setting the debug level; 00035 - getting hardware and executable info. 00036 It assumes that prginfo is global to the parent routine. 00037 */ 00038 void 00039 prof_init( int argc, char **argv, const PAPI_exe_info_t ** prginfo ) 00040 { 00041 int retval; 00042 00043 tests_quiet( argc, argv ); /* Set TESTS_QUIET variable */ 00044 00045 if ( ( retval = 00046 PAPI_library_init( PAPI_VER_CURRENT ) ) != PAPI_VER_CURRENT ) 00047 test_fail( __FILE__, __LINE__, "PAPI_library_init", retval ); 00048 00049 if ( ( *prginfo = PAPI_get_executable_info( ) ) == NULL ) 00050 test_fail( __FILE__, __LINE__, "PAPI_get_executable_info", 1 ); 00051 } 00052 00053 /* Many profiling tests count one of {FP_INS, FP_OPS, TOT_INS} and TOT_CYC. 00054 This function creates an event set containing the appropriate pair of events. 00055 It also initializes the global event_name string to the event selected. 00056 Assumed globals: EventSet, PAPI_event, event_name. 00057 */ 00058 int 00059 prof_events( int num_tests) 00060 { 00061 int retval; 00062 int num_events, mask; 00063 00064 /* add PAPI_TOT_CYC and one of the events in PAPI_FP_INS, PAPI_FP_OPS or 00065 PAPI_TOT_INS, depends on the availability of the event on the 00066 platform */ 00067 EventSet = 00068 add_two_nonderived_events( &num_events, &PAPI_event, &mask ); 00069 00070 values = allocate_test_space( num_tests, num_events ); 00071 00072 if ( ( retval = 00073 PAPI_event_code_to_name( PAPI_event, event_name ) ) != PAPI_OK ) 00074 test_fail( __FILE__, __LINE__, "PAPI_event_code_to_name", retval ); 00075 00076 return ( mask ); 00077 } 00078 00079 /* This function displays info from the prginfo structure in a standardized format. 00080 */ 00081 void 00082 prof_print_address( char *title, const PAPI_exe_info_t * prginfo ) 00083 { 00084 printf( "%s\n", title ); 00085 printf 00086 ( "----------------------------------------------------------------\n" ); 00087 printf( "Text start: %p, Text end: %p, Text length: 0x%x\n", 00088 prginfo->address_info.text_start, prginfo->address_info.text_end, 00089 ( unsigned int ) ( prginfo->address_info.text_end - 00090 prginfo->address_info.text_start ) ); 00091 printf( "Data start: %p, Data end: %p\n", prginfo->address_info.data_start, 00092 prginfo->address_info.data_end ); 00093 printf( "BSS start : %p, BSS end : %p\n", prginfo->address_info.bss_start, 00094 prginfo->address_info.bss_end ); 00095 00096 printf 00097 ( "----------------------------------------------------------------\n" ); 00098 } 00099 00100 /* This function displays profining information useful for several profile tests. 00101 It (probably inappropriately) assumes use of a common THRESHOLD. This should 00102 probably be a passed parameter. 00103 Assumed globals: event_name, start, stop. 00104 */ 00105 void 00106 prof_print_prof_info( caddr_t start, caddr_t end, int threshold, 00107 char *event_name ) 00108 { 00109 printf( "Profiling event : %s\n", event_name ); 00110 printf( "Profile Threshold: %d\n", threshold ); 00111 printf( "Profile Iters : %d\n", 00112 ( getenv( "NUM_ITERS" ) ? atoi( getenv( "NUM_ITERS" ) ) : 00113 NUM_ITERS ) ); 00114 printf( "Profile Range : %p to %p\n", start, end ); 00115 printf 00116 ( "----------------------------------------------------------------\n" ); 00117 printf( "\n" ); 00118 } 00119 00120 /* Most profile tests begin by counting the eventset with no profiling enabled. 00121 This function does that work. It assumes that the 'work' routine is do_both(). 00122 A better implementation would pass a pointer to the work function. 00123 Assumed globals: EventSet, values, event_name. 00124 */ 00125 void 00126 do_no_profile( void ) 00127 { 00128 int retval; 00129 00130 if ( ( retval = PAPI_start( EventSet ) ) != PAPI_OK ) 00131 test_fail( __FILE__, __LINE__, "PAPI_start", retval ); 00132 00133 do_flops( getenv( "NUM_ITERS" ) ? atoi( getenv( "NUM_ITERS" ) ) : 00134 NUM_ITERS ); 00135 00136 if ( ( retval = PAPI_stop( EventSet, values[0] ) ) != PAPI_OK ) 00137 test_fail( __FILE__, __LINE__, "PAPI_stop", retval ); 00138 00139 printf( "Test type : \t%s\n", "No profiling" ); 00140 printf( TAB1, event_name, ( values[0] )[0] ); 00141 printf( TAB1, "PAPI_TOT_CYC", ( values[0] )[1] ); 00142 } 00143 00144 /* This routine allocates and initializes up to 5 equal sized profiling buffers. 00145 They need to be freed when profiling is completed. 00146 The number and size are passed parameters. 00147 The profbuf[] array of void * pointers is an assumed global. 00148 It should be cast to the required type by the parent routine. 00149 */ 00150 void 00151 prof_alloc( int num, unsigned long blength ) 00152 { 00153 int i; 00154 00155 for ( i = 0; i < num; i++ ) { 00156 profbuf[i] = malloc( blength ); 00157 if ( profbuf[i] == NULL ) { 00158 test_fail( __FILE__, __LINE__, "malloc", PAPI_ESYS ); 00159 } 00160 memset( profbuf[i], 0x00, blength ); 00161 } 00162 } 00163 00164 /* Given the profiling type (16, 32, or 64) this function returns the 00165 bucket size in bytes. NOTE: the bucket size does not ALWAYS correspond 00166 to the expected value, esp on architectures like Cray with weird data types. 00167 This is necessary because the posix_profile routine in extras.c relies on 00168 the data types and sizes produced by the compiler. 00169 */ 00170 int 00171 prof_buckets( int bucket ) 00172 { 00173 int bucket_size; 00174 switch ( bucket ) { 00175 case PAPI_PROFIL_BUCKET_16: 00176 bucket_size = sizeof ( short ); 00177 break; 00178 case PAPI_PROFIL_BUCKET_32: 00179 bucket_size = sizeof ( int ); 00180 break; 00181 case PAPI_PROFIL_BUCKET_64: 00182 bucket_size = sizeof ( unsigned long long ); 00183 break; 00184 default: 00185 bucket_size = 0; 00186 break; 00187 } 00188 return ( bucket_size ); 00189 } 00190 00191 /* A standardized header printing routine. No assumed globals. 00192 */ 00193 void 00194 prof_head( unsigned long blength, int bucket, int num_buckets, char *header ) 00195 { 00196 int bucket_size = prof_buckets( bucket ); 00197 printf 00198 ( "\n------------------------------------------------------------\n" ); 00199 printf( "PAPI_profil() hash table, Bucket size: %d bits.\n", 00200 bucket_size * 8 ); 00201 printf( "Number of buckets: %d.\nLength of buffer: %ld bytes.\n", 00202 num_buckets, blength ); 00203 printf( "------------------------------------------------------------\n" ); 00204 printf( "%s\n", header ); 00205 } 00206 00207 /* This function prints a standardized profile output based on the bucket size. 00208 A row consisting of an address and 'n' data elements is displayed for each 00209 address with at least one non-zero bucket. 00210 Assumes global profbuf[] array pointers. 00211 */ 00212 void 00213 prof_out( caddr_t start, int n, int bucket, int num_buckets, 00214 unsigned int scale ) 00215 { 00216 int i, j; 00217 unsigned short buf_16; 00218 unsigned int buf_32; 00219 unsigned long long buf_64; 00220 unsigned short **buf16 = ( unsigned short ** ) profbuf; 00221 unsigned int **buf32 = ( unsigned int ** ) profbuf; 00222 unsigned long long **buf64 = ( unsigned long long ** ) profbuf; 00223 00224 if ( !TESTS_QUIET ) { 00225 /* printf("0x%lx\n",(unsigned long) start + (unsigned long) (2 * i)); */ 00226 /* printf("start: %p; i: %x; scale: %x; i*scale: %x; i*scale >>15: %x\n", start, i, scale, i*scale, (i*scale)>>15); */ 00227 switch ( bucket ) { 00228 case PAPI_PROFIL_BUCKET_16: 00229 for ( i = 0; i < num_buckets; i++ ) { 00230 for ( j = 0, buf_16 = 0; j < n; j++ ) 00231 buf_16 |= ( buf16[j] )[i]; 00232 if ( buf_16 ) { 00233 /* On 32bit builds with gcc 4.3 gcc complained about casting caddr_t => long long 00234 * Thus the unsigned long to long long cast */ 00235 printf( "0x%-16llx", 00236 (long long) (unsigned long)start + 00237 ( ( ( long long ) i * scale ) >> 15 ) ); 00238 for ( j = 0, buf_16 = 0; j < n; j++ ) 00239 printf( "\t%d", ( buf16[j] )[i] ); 00240 printf( "\n" ); 00241 } 00242 } 00243 break; 00244 case PAPI_PROFIL_BUCKET_32: 00245 for ( i = 0; i < num_buckets; i++ ) { 00246 for ( j = 0, buf_32 = 0; j < n; j++ ) 00247 buf_32 |= ( buf32[j] )[i]; 00248 if ( buf_32 ) { 00249 printf( "0x%-16llx", 00250 (long long) (unsigned long)start + 00251 ( ( ( long long ) i * scale ) >> 15 ) ); 00252 for ( j = 0, buf_32 = 0; j < n; j++ ) 00253 printf( "\t%d", ( buf32[j] )[i] ); 00254 printf( "\n" ); 00255 } 00256 } 00257 break; 00258 case PAPI_PROFIL_BUCKET_64: 00259 for ( i = 0; i < num_buckets; i++ ) { 00260 for ( j = 0, buf_64 = 0; j < n; j++ ) 00261 buf_64 |= ( buf64[j] )[i]; 00262 if ( buf_64 ) { 00263 printf( "0x%-16llx", 00264 (long long) (unsigned long)start + 00265 ( ( ( long long ) i * scale ) >> 15 ) ); 00266 for ( j = 0, buf_64 = 0; j < n; j++ ) 00267 printf( "\t%lld", ( buf64[j] )[i] ); 00268 printf( "\n" ); 00269 } 00270 } 00271 break; 00272 } 00273 printf 00274 ( "------------------------------------------------------------\n\n" ); 00275 } 00276 } 00277 00278 /* This function checks to make sure that some buffer value somewhere is nonzero. 00279 If all buffers are empty, zero is returned. This usually indicates a profiling 00280 failure. Assumes global profbuf[]. 00281 */ 00282 int 00283 prof_check( int n, int bucket, int num_buckets ) 00284 { 00285 int i, j; 00286 int retval = 0; 00287 unsigned short **buf16 = ( unsigned short ** ) profbuf; 00288 unsigned int **buf32 = ( unsigned int ** ) profbuf; 00289 unsigned long long **buf64 = ( unsigned long long ** ) profbuf; 00290 00291 switch ( bucket ) { 00292 case PAPI_PROFIL_BUCKET_16: 00293 for ( i = 0; i < num_buckets; i++ ) 00294 for ( j = 0; j < n; j++ ) 00295 retval = retval || buf16[j][i]; 00296 break; 00297 case PAPI_PROFIL_BUCKET_32: 00298 for ( i = 0; i < num_buckets; i++ ) 00299 for ( j = 0; j < n; j++ ) 00300 retval = retval || buf32[j][i]; 00301 break; 00302 case PAPI_PROFIL_BUCKET_64: 00303 for ( i = 0; i < num_buckets; i++ ) 00304 for ( j = 0; j < n; j++ ) 00305 retval = retval || buf64[j][i]; 00306 break; 00307 } 00308 return ( retval ); 00309 } 00310 00311 /* Computes the length (in bytes) of the buffer required for profiling. 00312 'plength' is the profile length, or address range to be profiled. 00313 By convention, it is assumed that there are half as many buckets as addresses. 00314 The scale factor is a fixed point fraction in which 0xffff = ~1 00315 0x8000 = 1/2 00316 0x4000 = 1/4, etc. 00317 Thus, the number of profile buckets is (plength/2) * (scale/65536), 00318 and the length (in bytes) of the profile buffer is buckets * bucket size. 00319 */ 00320 unsigned long 00321 prof_size( unsigned long plength, unsigned scale, int bucket, int *num_buckets ) 00322 { 00323 unsigned long blength; 00324 long long llength = ( ( long long ) plength * scale ); 00325 int bucket_size = prof_buckets( bucket ); 00326 *num_buckets = ( int ) ( llength / 65536 / 2 ); 00327 blength = ( unsigned long ) ( *num_buckets * bucket_size ); 00328 return ( blength ); 00329 }