|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* File: byte_profile.c
|
|
Packit |
577717 |
* Author: Dan Terpstra
|
|
Packit |
577717 |
* terpstra@cs.utk.edu
|
|
Packit |
577717 |
* Mods: Maynard Johnson
|
|
Packit |
577717 |
* maynardj@us.ibm.com
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* This file profiles multiple events with byte level address resolution.
|
|
Packit |
577717 |
It's patterned after code suggested by John Mellor-Crummey, Rob Fowler,
|
|
Packit |
577717 |
and Nathan Tallent.
|
|
Packit |
577717 |
It is intended to illustrate the use of Multiprofiling on a very tight
|
|
Packit |
577717 |
block of code at byte level resolution of the instruction addresses.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#include <stdio.h>
|
|
Packit |
577717 |
#include <stdlib.h>
|
|
Packit |
577717 |
#include <string.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#include "papi.h"
|
|
Packit |
577717 |
#include "papi_test.h"
|
|
Packit |
577717 |
#include "prof_utils.h"
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#include "do_loops.h"
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define PROFILE_ALL
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static const PAPI_hw_info_t *hw_info;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int num_events = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define N (1 << 23)
|
|
Packit |
577717 |
#define T (10)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
double aa[N], bb[N];
|
|
Packit |
577717 |
double s = 0, s2 = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
cleara( double a[N] )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for ( i = 0; i < N; i++ ) {
|
|
Packit |
577717 |
a[i] = 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
my_dummy( int i )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return ( i + 1 );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
my_main( void )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int i, j;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for ( j = 0; j < T; j++ ) {
|
|
Packit |
577717 |
for ( i = 0; i < N; i++ ) {
|
|
Packit |
577717 |
bb[i] = 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
cleara( aa );
|
|
Packit |
577717 |
memset( aa, 0, sizeof ( aa ) );
|
|
Packit |
577717 |
for ( i = 0; i < N; i++ ) {
|
|
Packit |
577717 |
s += aa[i] * bb[i];
|
|
Packit |
577717 |
s2 += aa[i] * aa[i] + bb[i] * bb[i];
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
do_profile( caddr_t start, unsigned long plength, unsigned scale, int thresh,
|
|
Packit |
577717 |
int bucket, unsigned int mask ) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int i, retval;
|
|
Packit |
577717 |
unsigned long blength;
|
|
Packit |
577717 |
int num_buckets,j=0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int num_bufs = num_events;
|
|
Packit |
577717 |
int event = num_events;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int events[MAX_TEST_EVENTS];
|
|
Packit |
577717 |
char header[BUFSIZ];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
strncpy(header,"address\t\t",BUFSIZ);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
//= "address\t\t\tcyc\tins\tfp_ins\n";
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i=0;i
|
|
Packit |
577717 |
if (mask & test_events[i].mask) {
|
|
Packit |
577717 |
events[j]=test_events[i].event;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (events[j]==PAPI_TOT_CYC) {
|
|
Packit |
577717 |
strncat(header,"\tcyc",BUFSIZ-1);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (events[j]==PAPI_TOT_INS) {
|
|
Packit |
577717 |
strncat(header,"\tins",BUFSIZ-1);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (events[j]==PAPI_FP_INS) {
|
|
Packit |
577717 |
strncat(header,"\tfp_ins",BUFSIZ-1);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (events[j]==PAPI_FP_OPS) {
|
|
Packit |
577717 |
strncat(header,"\tfp_ops",BUFSIZ-1);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (events[j]==PAPI_L2_TCM) {
|
|
Packit |
577717 |
strncat(header,"\tl2_tcm",BUFSIZ-1);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
j++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
strncat(header,"\n",BUFSIZ-1);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
blength = prof_size( plength, scale, bucket, &num_buckets );
|
|
Packit |
577717 |
prof_alloc( num_bufs, blength );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( !TESTS_QUIET ) printf( "Overall event counts:\n" );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for ( i = 0; i < num_events; i++ ) {
|
|
Packit |
577717 |
if ( ( retval =
|
|
Packit |
577717 |
PAPI_profil( profbuf[i], ( unsigned int ) blength, start, scale,
|
|
Packit |
577717 |
EventSet, events[i], thresh,
|
|
Packit |
577717 |
PAPI_PROFIL_POSIX | bucket ) ) != PAPI_OK ) {
|
|
Packit |
577717 |
if (retval == PAPI_EINVAL) {
|
|
Packit |
577717 |
test_warn( __FILE__, __LINE__, "Trying to profile with derived event", 1);
|
|
Packit |
577717 |
num_events=i;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
else {
|
|
Packit |
577717 |
printf("Failed with event %d %#x\n",i,events[i]);
|
|
Packit |
577717 |
test_fail( __FILE__, __LINE__, "PAPI_profil", retval );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( ( retval = PAPI_start( EventSet ) ) != PAPI_OK )
|
|
Packit |
577717 |
test_fail( __FILE__, __LINE__, "PAPI_start", retval );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
my_main( );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( ( retval = PAPI_stop( EventSet, values[0] ) ) != PAPI_OK )
|
|
Packit |
577717 |
test_fail( __FILE__, __LINE__, "PAPI_stop", retval );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( !TESTS_QUIET ) {
|
|
Packit |
577717 |
printf( TAB1, "PAPI_TOT_CYC:", ( values[0] )[--event] );
|
|
Packit |
577717 |
if ( strcmp( hw_info->model_string, "POWER6" ) != 0 ) {
|
|
Packit |
577717 |
printf( TAB1, "PAPI_TOT_INS:", ( values[0] )[--event] );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#if defined(__powerpc__)
|
|
Packit |
577717 |
printf( TAB1, "PAPI_FP_INS", ( values[0] )[--event] );
|
|
Packit |
577717 |
#else
|
|
Packit |
577717 |
if ( strcmp( hw_info->model_string, "Intel Pentium III" ) != 0 ) {
|
|
Packit |
577717 |
printf( TAB1, "PAPI_FP_OPS:", ( values[0] )[--event] );
|
|
Packit |
577717 |
printf( TAB1, "PAPI_L2_TCM:", ( values[0] )[--event] );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for ( i = 0; i < num_events; i++ ) {
|
|
Packit |
577717 |
if ( ( retval =
|
|
Packit |
577717 |
PAPI_profil( profbuf[i], ( unsigned int ) blength, start, scale,
|
|
Packit |
577717 |
EventSet, events[i], 0,
|
|
Packit |
577717 |
PAPI_PROFIL_POSIX ) ) != PAPI_OK )
|
|
Packit |
577717 |
test_fail( __FILE__, __LINE__, "PAPI_profil", retval );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!TESTS_QUIET) {
|
|
Packit |
577717 |
prof_head( blength, bucket, num_buckets, header );
|
|
Packit |
577717 |
prof_out( start, num_events, bucket, num_buckets, scale );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
retval = prof_check( num_bufs, bucket, num_buckets );
|
|
Packit |
577717 |
for ( i = 0; i < num_bufs; i++ ) {
|
|
Packit |
577717 |
free( profbuf[i] );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return retval;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
main( int argc, char **argv )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
long length;
|
|
Packit |
577717 |
int mask;
|
|
Packit |
577717 |
int retval;
|
|
Packit |
577717 |
const PAPI_exe_info_t *prginfo;
|
|
Packit |
577717 |
caddr_t start, end;
|
|
Packit |
577717 |
int quiet;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Set TESTS_QUIET variable */
|
|
Packit |
577717 |
quiet=tests_quiet( argc, argv );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
retval = PAPI_library_init( PAPI_VER_CURRENT );
|
|
Packit |
577717 |
if (retval != PAPI_VER_CURRENT) {
|
|
Packit |
577717 |
test_fail( __FILE__, __LINE__, "PAPI_library_init", retval );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ( ( prginfo = PAPI_get_executable_info( ) ) == NULL ) {
|
|
Packit |
577717 |
test_fail( __FILE__, __LINE__, "PAPI_get_executable_info", 1 );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
hw_info = PAPI_get_hardware_info( );
|
|
Packit |
577717 |
if ( hw_info == NULL ) {
|
|
Packit |
577717 |
test_fail( __FILE__, __LINE__, "PAPI_get_hardware_info", 2 );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
mask = MASK_TOT_CYC | MASK_TOT_INS | MASK_FP_OPS | MASK_L2_TCM;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#if defined(__powerpc__)
|
|
Packit |
577717 |
if ( strcmp( hw_info->model_string, "POWER6" ) == 0 )
|
|
Packit |
577717 |
mask = MASK_TOT_CYC | MASK_FP_INS;
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
mask = MASK_TOT_CYC | MASK_TOT_INS | MASK_FP_INS;
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#if defined(ITANIUM2)
|
|
Packit |
577717 |
mask = MASK_TOT_CYC | MASK_FP_OPS | MASK_L2_TCM | MASK_L1_DCM;
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
EventSet = add_test_events( &num_events, &mask, 0 );
|
|
Packit |
577717 |
if (num_events==0) {
|
|
Packit |
577717 |
if (!quiet) printf("Trouble adding events\n");
|
|
Packit |
577717 |
test_skip(__FILE__,__LINE__,"add_test_events",2);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
values = allocate_test_space( 1, num_events );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* profile the cleara and my_main address space */
|
|
Packit |
577717 |
start = ( caddr_t ) cleara;
|
|
Packit |
577717 |
end = ( caddr_t ) my_dummy;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Itanium and PowerPC64 processors return function descriptors instead
|
|
Packit |
577717 |
* of function addresses. You must dereference the descriptor to get the address.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#if defined(ITANIUM1) || defined(ITANIUM2) \
|
|
Packit |
577717 |
|| (defined(__powerpc64__) && (_CALL_ELF != 2))
|
|
Packit |
577717 |
start = ( caddr_t ) ( ( ( struct fdesc * ) start )->ip );
|
|
Packit |
577717 |
end = ( caddr_t ) ( ( ( struct fdesc * ) end )->ip );
|
|
Packit |
577717 |
/* PPC64 Big Endian is ELF version 1 which uses function descriptors.
|
|
Packit |
577717 |
* PPC64 Little Endian is ELF version 2 which does not use
|
|
Packit |
577717 |
* function descriptors
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* call dummy so it doesn't get optimized away */
|
|
Packit |
577717 |
retval = my_dummy( 1 );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
length = end - start;
|
|
Packit |
577717 |
if ( length < 0 )
|
|
Packit |
577717 |
test_fail( __FILE__, __LINE__, "Profile length < 0!", ( int ) length );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!quiet) {
|
|
Packit |
577717 |
prof_print_address( "Test case byte_profile: "
|
|
Packit |
577717 |
"Multi-event profiling at byte resolution.\n",
|
|
Packit |
577717 |
prginfo );
|
|
Packit |
577717 |
prof_print_prof_info( start, end, THRESHOLD, event_name );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
retval = do_profile( start, ( unsigned ) length,
|
|
Packit |
577717 |
FULL_SCALE * 2, THRESHOLD,
|
|
Packit |
577717 |
PAPI_PROFIL_BUCKET_32, mask );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
remove_test_events( &EventSet, mask );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (retval == 0) {
|
|
Packit |
577717 |
test_fail( __FILE__, __LINE__, "No information in buffers", 1 );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
test_pass( __FILE__ );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|