|
PAPI
5.0.1.0
|
00001 /* This file performs the following test: overflow dispatch with pthreads 00002 00003 - This tests the dispatch of overflow calls from PAPI. These are counted 00004 in the default counting domain and default granularity, depending on 00005 the platform. Usually this is the user domain (PAPI_DOM_USER) and 00006 thread context (PAPI_GRN_THR). 00007 00008 The Eventset contains: 00009 + PAPI_FP_INS (overflow monitor) 00010 + PAPI_TOT_CYC 00011 00012 - Set up overflow 00013 - Start eventset 1 00014 - Do flops 00015 - Stop eventset 1 00016 */ 00017 00018 #include <pthread.h> 00019 #include "papi_test.h" 00020 00021 static const PAPI_hw_info_t *hw_info = NULL; 00022 static int total[NUM_THREADS]; 00023 static int expected[NUM_THREADS]; 00024 static pthread_t myid[NUM_THREADS]; 00025 00026 void 00027 handler( int EventSet, void *address, long long overflow_vector, void *context ) 00028 { 00029 #if 0 00030 printf( "handler(%d,0x%lx,%llx) Overflow %d in thread %lx\n", 00031 EventSet, ( unsigned long ) address, overflow_vector, 00032 total[EventSet], PAPI_thread_id( ) ); 00033 printf( "%lx vs %lx\n", myid[EventSet], PAPI_thread_id( ) ); 00034 #else /* eliminate unused parameter warning message */ 00035 ( void ) address; 00036 ( void ) overflow_vector; 00037 ( void ) context; 00038 #endif 00039 total[EventSet]++; 00040 } 00041 00042 long long mythreshold=0; 00043 00044 void * 00045 Thread( void *arg ) 00046 { 00047 int retval, num_tests = 1; 00048 int EventSet1 = PAPI_NULL; 00049 int mask1, papi_event; 00050 int num_events1; 00051 long long **values; 00052 long long elapsed_us, elapsed_cyc; 00053 char event_name[PAPI_MAX_STR_LEN]; 00054 00055 retval = PAPI_register_thread( ); 00056 if ( retval != PAPI_OK ) 00057 test_fail( __FILE__, __LINE__, "PAPI_register_thread", retval ); 00058 00059 /* add PAPI_TOT_CYC and one of the events in PAPI_FP_INS, PAPI_FP_OPS or 00060 PAPI_TOT_INS, depends on the availability of the event on the 00061 platform */ 00062 EventSet1 = 00063 add_two_nonderived_events( &num_events1, &papi_event, &mask1 ); 00064 00065 if (EventSet1 < 0) return NULL; 00066 00067 /* Wait, we're indexing a per-thread array with the EventSet number? */ 00068 /* does that make any sense at all???? -- vmw */ 00069 expected[EventSet1] = *( int * ) arg / mythreshold; 00070 myid[EventSet1] = PAPI_thread_id( ); 00071 00072 values = allocate_test_space( num_tests, num_events1 ); 00073 00074 elapsed_us = PAPI_get_real_usec( ); 00075 00076 elapsed_cyc = PAPI_get_real_cyc( ); 00077 00078 if ((retval = PAPI_overflow( EventSet1, papi_event, 00079 mythreshold, 0, handler ) ) != PAPI_OK ) { 00080 test_fail( __FILE__, __LINE__, "PAPI_overflow", retval ); 00081 } 00082 00083 /* start_timer(1); */ 00084 if ( ( retval = PAPI_start( EventSet1 ) ) != PAPI_OK ) 00085 test_fail( __FILE__, __LINE__, "PAPI_start", retval ); 00086 00087 do_stuff( ); 00088 00089 if ( ( retval = PAPI_stop( EventSet1, values[0] ) ) != PAPI_OK ) 00090 test_fail( __FILE__, __LINE__, "PAPI_stop", retval ); 00091 00092 elapsed_us = PAPI_get_real_usec( ) - elapsed_us; 00093 00094 elapsed_cyc = PAPI_get_real_cyc( ) - elapsed_cyc; 00095 00096 if ( ( retval = 00097 PAPI_overflow( EventSet1, papi_event, 0, 0, NULL ) ) != PAPI_OK ) 00098 test_fail( __FILE__, __LINE__, "PAPI_overflow", retval ); 00099 00100 remove_test_events( &EventSet1, mask1 ); 00101 00102 if ( ( retval = 00103 PAPI_event_code_to_name( papi_event, event_name ) ) != PAPI_OK ) 00104 test_fail( __FILE__, __LINE__, "PAPI_event_code_to_name", retval ); 00105 00106 if ( !TESTS_QUIET ) { 00107 printf( "Thread 0x%x %s : \t%lld\n", ( int ) pthread_self( ), 00108 event_name, ( values[0] )[0] ); 00109 printf( "Thread 0x%x PAPI_TOT_CYC: \t%lld\n", ( int ) pthread_self( ), 00110 ( values[0] )[1] ); 00111 printf( "Thread 0x%x Real usec : \t%lld\n", ( int ) pthread_self( ), 00112 elapsed_us ); 00113 printf( "Thread 0x%x Real cycles : \t%lld\n", ( int ) pthread_self( ), 00114 elapsed_cyc ); 00115 } 00116 free_test_space( values, num_tests ); 00117 retval = PAPI_unregister_thread( ); 00118 if ( retval != PAPI_OK ) 00119 test_fail( __FILE__, __LINE__, "PAPI_unregister_thread", retval ); 00120 return ( NULL ); 00121 } 00122 00123 int 00124 main( int argc, char **argv ) 00125 { 00126 pthread_t id[NUM_THREADS]; 00127 int flops[NUM_THREADS]; 00128 int i, rc, retval; 00129 pthread_attr_t attr; 00130 float ratio; 00131 00132 memset( total, 0x0, NUM_THREADS * sizeof ( *total ) ); 00133 memset( expected, 0x0, NUM_THREADS * sizeof ( *expected ) ); 00134 memset( myid, 0x0, NUM_THREADS * sizeof ( *myid ) ); 00135 tests_quiet( argc, argv ); /* Set TESTS_QUIET variable */ 00136 00137 if ( ( retval = 00138 PAPI_library_init( PAPI_VER_CURRENT ) ) != PAPI_VER_CURRENT ) 00139 test_fail( __FILE__, __LINE__, "PAPI_library_init", retval ); 00140 00141 hw_info = PAPI_get_hardware_info( ); 00142 if ( hw_info == NULL ) 00143 test_fail( __FILE__, __LINE__, "PAPI_get_hardware_info", 2 ); 00144 00145 if ( ( retval = 00146 PAPI_thread_init( ( unsigned 00147 long ( * )( void ) ) ( pthread_self ) ) ) != 00148 PAPI_OK ) { 00149 if ( retval == PAPI_ECMP ) 00150 test_skip( __FILE__, __LINE__, "PAPI_thread_init", retval ); 00151 else 00152 test_fail( __FILE__, __LINE__, "PAPI_thread_init", retval ); 00153 } 00154 #if defined(linux) 00155 mythreshold = hw_info->cpu_max_mhz * 10000 * 2; 00156 #else 00157 mythreshold = THRESHOLD * 2; 00158 #endif 00159 00160 pthread_attr_init( &attr ); 00161 #ifdef PTHREAD_CREATE_UNDETACHED 00162 pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_UNDETACHED ); 00163 #endif 00164 #ifdef PTHREAD_SCOPE_SYSTEM 00165 retval = pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM ); 00166 if ( retval != 0 ) 00167 test_skip( __FILE__, __LINE__, "pthread_attr_setscope", retval ); 00168 #endif 00169 00170 for ( i = 0; i < NUM_THREADS; i++ ) { 00171 flops[i] = NUM_FLOPS * ( i + 1 ); 00172 rc = pthread_create( &id[i], &attr, Thread, ( void * ) &flops[i] ); 00173 if ( rc ) 00174 test_fail( __FILE__, __LINE__, "pthread_create", PAPI_ESYS ); 00175 } 00176 for ( i = 0; i < NUM_THREADS; i++ ) 00177 pthread_join( id[i], NULL ); 00178 00179 pthread_attr_destroy( &attr ); 00180 00181 { 00182 long long t = 0, r = 0; 00183 for ( i = 0; i < NUM_THREADS; i++ ) { 00184 t += ( NUM_FLOPS * ( i + 1 ) ) / mythreshold; 00185 r += total[i]; 00186 } 00187 printf( "Expected total overflows: %lld\n", t ); 00188 printf( "Received total overflows: %lld\n", r ); 00189 } 00190 00191 /* ratio = (float)total[0] / (float)expected[0]; */ 00192 /* printf("Ratio of total to expected: %f\n",ratio); */ 00193 ratio = 1.0; 00194 for ( i = 0; i < NUM_THREADS; i++ ) { 00195 printf( "Overflows thread %d: %d, expected %d\n", 00196 i, total[i], ( int ) ( ratio * ( float ) expected[i] ) ); 00197 } 00198 00199 for ( i = 0; i < NUM_THREADS; i++ ) { 00200 if ( total[i] < ( int ) ( ( ratio * ( float ) expected[i] ) / 2.0 ) ) 00201 test_fail( __FILE__, __LINE__, "not enough overflows", PAPI_EMISC ); 00202 } 00203 00204 test_pass( __FILE__, NULL, 0 ); 00205 pthread_exit( NULL ); 00206 exit( 1 ); 00207 }