|
PAPI
5.0.1.0
|
00001 /* 00002 * File: papi_bipartite.h 00003 * Author: Dan Terpstra 00004 * terpstra@eecs.utk.edu 00005 * Mods: 00006 * 00007 */ 00008 /* This file contains one function: _papi_bipartite_alloc() 00009 Its role is to act as an execution harness for implementing a recursive 00010 Modified Bipartite Graph allocation of counter resources for those 00011 platforms that don't have built-in smart counter allocation. 00012 It is intended to be #included in the cpu component source to minimize 00013 other disruption to the build process. 00014 00015 This routine presumes the existence of a half dozen "bpt_" helper routines. 00016 Prototypes for these routines are given below. 00017 00018 success return 1 00019 fail return 0 00020 */ 00021 00022 /* This function examines the event to determine 00023 if it can be mapped to counter ctr. 00024 Returns true if it can, false if it can't. */ 00025 static int 00026 _bpt_map_avail( hwd_reg_alloc_t * dst, int ctr ); 00027 00028 /* This function forces the event to 00029 be mapped to only counter ctr. 00030 Returns nothing. */ 00031 static void 00032 _bpt_map_set( hwd_reg_alloc_t * dst, int ctr ); 00033 00034 /* This function examines the event to determine 00035 if it has a single exclusive mapping. 00036 Returns true if exlusive, false if non-exclusive. */ 00037 static int 00038 _bpt_map_exclusive( hwd_reg_alloc_t * dst ); 00039 00040 /* This function compares the dst and src events 00041 to determine if any resources are shared. Typically the src event 00042 is exclusive, so this detects a conflict if true. 00043 Returns true if conflict, false if no conflict. */ 00044 static int 00045 _bpt_map_shared( hwd_reg_alloc_t * dst, hwd_reg_alloc_t * src ); 00046 00047 /* This function removes shared resources available to the src event 00048 from the resources available to the dst event, 00049 and reduces the rank of the dst event accordingly. Typically, 00050 the src event will be exclusive, but the code shouldn't assume it. 00051 Returns nothing. */ 00052 static void 00053 _bpt_map_preempt( hwd_reg_alloc_t * dst, hwd_reg_alloc_t * src ); 00054 00055 static void 00056 _bpt_map_update( hwd_reg_alloc_t * dst, hwd_reg_alloc_t * src ); 00057 00058 00059 static int 00060 _papi_bipartite_alloc( hwd_reg_alloc_t * event_list, int count, int cidx ) 00061 { 00062 int i, j; 00063 char *ptr = ( char * ) event_list; 00064 int idx_q[count]; /* queue of indexes of lowest rank events */ 00065 int map_q[count]; /* queue of mapped events (TRUE if mapped) */ 00066 int head, tail; 00067 int size = _papi_hwd[cidx]->size.reg_alloc; 00068 00069 /* build a queue of indexes to all events 00070 that live on one counter only (rank == 1) */ 00071 head = 0; /* points to top of queue */ 00072 tail = 0; /* points to bottom of queue */ 00073 for ( i = 0; i < count; i++ ) { 00074 map_q[i] = 0; 00075 if ( _bpt_map_exclusive( ( hwd_reg_alloc_t * ) & ptr[size * i] ) ) 00076 idx_q[tail++] = i; 00077 } 00078 /* scan the single counter queue looking for events that share counters. 00079 If two events can live only on one counter, return failure. 00080 If the second event lives on more than one counter, remove shared counter 00081 from its selector and reduce its rank. 00082 Mark first event as mapped to its counter. */ 00083 while ( head < tail ) { 00084 for ( i = 0; i < count; i++ ) { 00085 if ( i != idx_q[head] ) { 00086 if ( _bpt_map_shared( ( hwd_reg_alloc_t * ) & ptr[size * i], 00087 ( hwd_reg_alloc_t * ) & ptr[size * 00088 idx_q 00089 [head]] ) ) { 00090 /* both share a counter; if second is exclusive, mapping fails */ 00091 if ( _bpt_map_exclusive( ( hwd_reg_alloc_t * ) & 00092 ptr[size * i] ) ) 00093 return 0; 00094 else { 00095 _bpt_map_preempt( ( hwd_reg_alloc_t * ) & 00096 ptr[size * i], 00097 ( hwd_reg_alloc_t * ) & ptr[size * 00098 idx_q 00099 [head]] ); 00100 if ( _bpt_map_exclusive( ( hwd_reg_alloc_t * ) & 00101 ptr[size * i] ) ) 00102 idx_q[tail++] = i; 00103 } 00104 } 00105 } 00106 } 00107 map_q[idx_q[head]] = 1; /* mark this event as mapped */ 00108 head++; 00109 } 00110 if ( tail == count ) { 00111 return 1; /* idx_q includes all events; everything is successfully mapped */ 00112 } else { 00113 char *rest_event_list; 00114 char *copy_rest_event_list; 00115 int remainder; 00116 00117 rest_event_list = 00118 papi_calloc( _papi_hwd[cidx]->cmp_info.num_cntrs, 00119 size ); 00120 00121 copy_rest_event_list = 00122 papi_calloc( _papi_hwd[cidx]->cmp_info.num_cntrs, 00123 size ); 00124 00125 if ( !rest_event_list || !copy_rest_event_list ) { 00126 if ( rest_event_list ) 00127 papi_free( rest_event_list ); 00128 if ( copy_rest_event_list ) 00129 papi_free( copy_rest_event_list ); 00130 return ( 0 ); 00131 } 00132 00133 /* copy all unmapped events to a second list and make a backup */ 00134 for ( i = 0, j = 0; i < count; i++ ) { 00135 if ( map_q[i] == 0 ) { 00136 memcpy( ©_rest_event_list[size * j++], &ptr[size * i], 00137 ( size_t ) size ); 00138 } 00139 } 00140 remainder = j; 00141 00142 memcpy( rest_event_list, copy_rest_event_list, 00143 ( size_t ) size * ( size_t ) remainder ); 00144 00145 /* try each possible mapping until you fail or find one that works */ 00146 for ( i = 0; i < _papi_hwd[cidx]->cmp_info.num_cntrs; i++ ) { 00147 /* for the first unmapped event, try every possible counter */ 00148 if ( _bpt_map_avail( ( hwd_reg_alloc_t * ) rest_event_list, i ) ) { 00149 _bpt_map_set( ( hwd_reg_alloc_t * ) rest_event_list, i ); 00150 /* remove selected counter from all other unmapped events */ 00151 for ( j = 1; j < remainder; j++ ) { 00152 if ( _bpt_map_shared( ( hwd_reg_alloc_t * ) & 00153 rest_event_list[size * j], 00154 ( hwd_reg_alloc_t * ) 00155 rest_event_list ) ) 00156 _bpt_map_preempt( ( hwd_reg_alloc_t * ) & 00157 rest_event_list[size * j], 00158 ( hwd_reg_alloc_t * ) 00159 rest_event_list ); 00160 } 00161 /* if recursive call to allocation works, break out of the loop */ 00162 if ( _papi_bipartite_alloc 00163 ( ( hwd_reg_alloc_t * ) rest_event_list, remainder, 00164 cidx ) ) 00165 break; 00166 00167 /* recursive mapping failed; copy the backup list and try the next combination */ 00168 memcpy( rest_event_list, copy_rest_event_list, 00169 ( size_t ) size * ( size_t ) remainder ); 00170 } 00171 } 00172 if ( i == _papi_hwd[cidx]->cmp_info.num_cntrs ) { 00173 papi_free( rest_event_list ); 00174 papi_free( copy_rest_event_list ); 00175 return 0; /* fail to find mapping */ 00176 } 00177 for ( i = 0, j = 0; i < count; i++ ) { 00178 if ( map_q[i] == 0 ) 00179 _bpt_map_update( ( hwd_reg_alloc_t * ) & ptr[size * i], 00180 ( hwd_reg_alloc_t * ) & rest_event_list[size 00181 * 00182 j++] ); 00183 } 00184 papi_free( rest_event_list ); 00185 papi_free( copy_rest_event_list ); 00186 return 1; 00187 } 00188 } 00189