|
PAPI
5.0.1.0
|
Go to the source code of this file.
Functions | |
| static int | _bpt_map_avail (hwd_reg_alloc_t *dst, int ctr) |
| static void | _bpt_map_set (hwd_reg_alloc_t *dst, int ctr) |
| static int | _bpt_map_exclusive (hwd_reg_alloc_t *dst) |
| static int | _bpt_map_shared (hwd_reg_alloc_t *dst, hwd_reg_alloc_t *src) |
| static void | _bpt_map_preempt (hwd_reg_alloc_t *dst, hwd_reg_alloc_t *src) |
| static void | _bpt_map_update (hwd_reg_alloc_t *dst, hwd_reg_alloc_t *src) |
| static int | _papi_bipartite_alloc (hwd_reg_alloc_t *event_list, int count, int cidx) |
| static int _bpt_map_avail | ( | hwd_reg_alloc_t * | dst, |
| int | ctr | ||
| ) | [static] |

| static int _bpt_map_exclusive | ( | hwd_reg_alloc_t * | dst | ) | [static] |

| static void _bpt_map_preempt | ( | hwd_reg_alloc_t * | dst, |
| hwd_reg_alloc_t * | src | ||
| ) | [static] |

| static void _bpt_map_set | ( | hwd_reg_alloc_t * | dst, |
| int | ctr | ||
| ) | [static] |

| static int _bpt_map_shared | ( | hwd_reg_alloc_t * | dst, |
| hwd_reg_alloc_t * | src | ||
| ) | [static] |

| static void _bpt_map_update | ( | hwd_reg_alloc_t * | dst, |
| hwd_reg_alloc_t * | src | ||
| ) | [static] |

| static int _papi_bipartite_alloc | ( | hwd_reg_alloc_t * | event_list, |
| int | count, | ||
| int | cidx | ||
| ) | [static] |
Definition at line 60 of file papi_bipartite.h.
{
int i, j;
char *ptr = ( char * ) event_list;
int idx_q[count]; /* queue of indexes of lowest rank events */
int map_q[count]; /* queue of mapped events (TRUE if mapped) */
int head, tail;
int size = _papi_hwd[cidx]->size.reg_alloc;
/* build a queue of indexes to all events
that live on one counter only (rank == 1) */
head = 0; /* points to top of queue */
tail = 0; /* points to bottom of queue */
for ( i = 0; i < count; i++ ) {
map_q[i] = 0;
if ( _bpt_map_exclusive( ( hwd_reg_alloc_t * ) & ptr[size * i] ) )
idx_q[tail++] = i;
}
/* scan the single counter queue looking for events that share counters.
If two events can live only on one counter, return failure.
If the second event lives on more than one counter, remove shared counter
from its selector and reduce its rank.
Mark first event as mapped to its counter. */
while ( head < tail ) {
for ( i = 0; i < count; i++ ) {
if ( i != idx_q[head] ) {
if ( _bpt_map_shared( ( hwd_reg_alloc_t * ) & ptr[size * i],
( hwd_reg_alloc_t * ) & ptr[size *
idx_q
[head]] ) ) {
/* both share a counter; if second is exclusive, mapping fails */
if ( _bpt_map_exclusive( ( hwd_reg_alloc_t * ) &
ptr[size * i] ) )
return 0;
else {
_bpt_map_preempt( ( hwd_reg_alloc_t * ) &
ptr[size * i],
( hwd_reg_alloc_t * ) & ptr[size *
idx_q
[head]] );
if ( _bpt_map_exclusive( ( hwd_reg_alloc_t * ) &
ptr[size * i] ) )
idx_q[tail++] = i;
}
}
}
}
map_q[idx_q[head]] = 1; /* mark this event as mapped */
head++;
}
if ( tail == count ) {
return 1; /* idx_q includes all events; everything is successfully mapped */
} else {
char *rest_event_list;
char *copy_rest_event_list;
int remainder;
rest_event_list =
papi_calloc( _papi_hwd[cidx]->cmp_info.num_cntrs,
size );
copy_rest_event_list =
papi_calloc( _papi_hwd[cidx]->cmp_info.num_cntrs,
size );
if ( !rest_event_list || !copy_rest_event_list ) {
if ( rest_event_list )
papi_free( rest_event_list );
if ( copy_rest_event_list )
papi_free( copy_rest_event_list );
return ( 0 );
}
/* copy all unmapped events to a second list and make a backup */
for ( i = 0, j = 0; i < count; i++ ) {
if ( map_q[i] == 0 ) {
memcpy( ©_rest_event_list[size * j++], &ptr[size * i],
( size_t ) size );
}
}
remainder = j;
memcpy( rest_event_list, copy_rest_event_list,
( size_t ) size * ( size_t ) remainder );
/* try each possible mapping until you fail or find one that works */
for ( i = 0; i < _papi_hwd[cidx]->cmp_info.num_cntrs; i++ ) {
/* for the first unmapped event, try every possible counter */
if ( _bpt_map_avail( ( hwd_reg_alloc_t * ) rest_event_list, i ) ) {
_bpt_map_set( ( hwd_reg_alloc_t * ) rest_event_list, i );
/* remove selected counter from all other unmapped events */
for ( j = 1; j < remainder; j++ ) {
if ( _bpt_map_shared( ( hwd_reg_alloc_t * ) &
rest_event_list[size * j],
( hwd_reg_alloc_t * )
rest_event_list ) )
_bpt_map_preempt( ( hwd_reg_alloc_t * ) &
rest_event_list[size * j],
( hwd_reg_alloc_t * )
rest_event_list );
}
/* if recursive call to allocation works, break out of the loop */
if ( _papi_bipartite_alloc
( ( hwd_reg_alloc_t * ) rest_event_list, remainder,
cidx ) )
break;
/* recursive mapping failed; copy the backup list and try the next combination */
memcpy( rest_event_list, copy_rest_event_list,
( size_t ) size * ( size_t ) remainder );
}
}
if ( i == _papi_hwd[cidx]->cmp_info.num_cntrs ) {
papi_free( rest_event_list );
papi_free( copy_rest_event_list );
return 0; /* fail to find mapping */
}
for ( i = 0, j = 0; i < count; i++ ) {
if ( map_q[i] == 0 )
_bpt_map_update( ( hwd_reg_alloc_t * ) & ptr[size * i],
( hwd_reg_alloc_t * ) & rest_event_list[size
*
j++] );
}
papi_free( rest_event_list );
papi_free( copy_rest_event_list );
return 1;
}
}
