PAPI  5.0.1.0
prof_utils.c
Go to the documentation of this file.
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 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines