Blame src/ctests/val_omp.c

Packit 577717
/* This file performs the following test: each OMP thread measures flops
Packit 577717
for its provided tasks, and compares this to expected flop counts, each
Packit 577717
thread having been provided with a random amount of work, such that the
Packit 577717
time and order that they complete their measurements varies.
Packit 577717
Specifically tested is the case where the value returned for some threads
Packit 577717
actually corresponds to that for another thread reading its counter values
Packit 577717
at the same time.
Packit 577717
Packit 577717
   - It is based on zero_omp.c but ignored much of its functionality.
Packit 577717
   - It attempts to use the following two counters. It may use less
Packit 577717
depending on hardware counter resource limitations. These are counted
Packit 577717
in the default counting domain and default granularity, depending on
Packit 577717
the platform. Usually this is the user domain (PAPI_DOM_USER) and
Packit 577717
thread context (PAPI_GRN_THR).
Packit 577717
Packit 577717
     + PAPI_FP_INS
Packit 577717
     + PAPI_TOT_CYC
Packit 577717
Packit 577717
Each thread inside the Thread routine:
Packit 577717
   - Do prework (MAX_FLOPS - flops)
Packit 577717
   - Get cyc.
Packit 577717
   - Get us.
Packit 577717
   - Start counters
Packit 577717
   - Do flops
Packit 577717
   - Stop and read counters
Packit 577717
   - Get us.
Packit 577717
   - Get cyc.
Packit 577717
   - Return flops
Packit 577717
*/
Packit 577717
Packit 577717
#include "papi_test.h"
Packit 577717
Packit 577717
#ifdef _OPENMP
Packit 577717
#include <omp.h>
Packit 577717
#else
Packit 577717
#error "This compiler does not understand OPENMP"
Packit 577717
#endif
Packit 577717
Packit 577717
const int MAX_FLOPS = NUM_FLOPS;
Packit 577717
Packit 577717
extern int TESTS_QUIET;				   /* Declared in test_utils.c */
Packit 577717
const PAPI_hw_info_t *hw_info = NULL;
Packit 577717
Packit 577717
long long
Packit 577717
Thread( int n )
Packit 577717
{
Packit 577717
	int retval, num_tests = 1;
Packit 577717
	int EventSet1 = PAPI_NULL;
Packit 577717
	int PAPI_event, mask1;
Packit 577717
	int num_events1;
Packit 577717
	long long flops;
Packit 577717
	long long **values;
Packit 577717
	long long elapsed_us, elapsed_cyc;
Packit 577717
	char event_name[PAPI_MAX_STR_LEN];
Packit 577717
Packit 577717
	/* printf("Thread(n=%d) %#x started\n", n, omp_get_thread_num()); */
Packit 577717
	num_events1 = 2;
Packit 577717
Packit 577717
	/* add PAPI_TOT_CYC and one of the events in PAPI_FP_INS, PAPI_FP_OPS or
Packit 577717
	   PAPI_TOT_INS, depending on the availability of the event on the
Packit 577717
	   platform */
Packit 577717
	EventSet1 = add_two_events( &num_events1, &PAPI_event, &mask1 );
Packit 577717
Packit 577717
	retval = PAPI_event_code_to_name( PAPI_event, event_name );
Packit 577717
	if ( retval != PAPI_OK )
Packit 577717
		test_fail( __FILE__, __LINE__, "PAPI_event_code_to_name", retval );
Packit 577717
Packit 577717
	values = allocate_test_space( num_tests, num_events1 );
Packit 577717
Packit 577717
	do_flops( MAX_FLOPS - n );	/* prework for balance */
Packit 577717
Packit 577717
	elapsed_us = PAPI_get_real_usec(  );
Packit 577717
Packit 577717
	elapsed_cyc = PAPI_get_real_cyc(  );
Packit 577717
Packit 577717
	retval = PAPI_start( EventSet1 );
Packit 577717
	if ( retval != PAPI_OK )
Packit 577717
		test_fail( __FILE__, __LINE__, "PAPI_start", retval );
Packit 577717
Packit 577717
	do_flops( n );
Packit 577717
Packit 577717
	retval = PAPI_stop( EventSet1, values[0] );
Packit 577717
	if ( retval != PAPI_OK )
Packit 577717
		test_fail( __FILE__, __LINE__, "PAPI_stop", retval );
Packit 577717
Packit 577717
	flops = ( values[0] )[0];
Packit 577717
Packit 577717
	elapsed_us = PAPI_get_real_usec(  ) - elapsed_us;
Packit 577717
Packit 577717
	elapsed_cyc = PAPI_get_real_cyc(  ) - elapsed_cyc;
Packit 577717
Packit 577717
	remove_test_events( &EventSet1, mask1 );
Packit 577717
Packit 577717
	if ( !TESTS_QUIET ) {
Packit 577717
		/*printf("Thread %#x %-12s : \t%lld\t%d\n", omp_get_thread_num(), event_name,
Packit 577717
		   (values[0])[0], n); */
Packit 577717
#if 0
Packit 577717
		printf( "Thread %#x PAPI_TOT_CYC: \t%lld\n", omp_get_thread_num(  ),
Packit 577717
				values[0][0] );
Packit 577717
		printf( "Thread %#x Real usec   : \t%lld\n", omp_get_thread_num(  ),
Packit 577717
				elapsed_us );
Packit 577717
		printf( "Thread %#x Real cycles : \t%lld\n", omp_get_thread_num(  ),
Packit 577717
				elapsed_cyc );
Packit 577717
#endif
Packit 577717
	}
Packit 577717
Packit 577717
	/* It is illegal for the threads to exit in OpenMP */
Packit 577717
	/* test_pass(__FILE__,0,0); */
Packit 577717
	free_test_space( values, num_tests );
Packit 577717
Packit 577717
	PAPI_unregister_thread(  );
Packit 577717
	/* printf("Thread %#x finished\n", omp_get_thread_num()); */
Packit 577717
	return flops;
Packit 577717
}
Packit 577717
Packit 577717
int
Packit 577717
main( int argc, char **argv )
Packit 577717
{
Packit 577717
	int tid, retval;
Packit 577717
	int maxthr = omp_get_max_threads(  );
Packit 577717
	int flopper = 0;
Packit 577717
	long long *flops = calloc( maxthr, sizeof ( long long ) );
Packit 577717
	long long *flopi = calloc( maxthr, sizeof ( long long ) );
Packit 577717
Packit 577717
	tests_quiet( argc, argv );	/* Set TESTS_QUIET variable */
Packit 577717
Packit 577717
	if ( maxthr < 2 )
Packit 577717
		test_skip( __FILE__, __LINE__, "omp_get_num_threads < 2", PAPI_EINVAL );
Packit 577717
Packit 577717
	if ( ( flops == NULL ) || ( flopi == NULL ) )
Packit 577717
		test_fail( __FILE__, __LINE__, "calloc", PAPI_ENOMEM );
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
	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
	retval =
Packit 577717
		PAPI_thread_init( ( unsigned
Packit 577717
							long ( * )( void ) ) ( omp_get_thread_num ) );
Packit 577717
	if ( retval != PAPI_OK )
Packit 577717
		if ( retval == PAPI_ECMP )
Packit 577717
			test_skip( __FILE__, __LINE__, "PAPI_thread_init", retval );
Packit 577717
		else
Packit 577717
			test_fail( __FILE__, __LINE__, "PAPI_thread_init", retval );
Packit 577717
Packit 577717
	flopper = Thread( 65536 ) / 65536;
Packit 577717
	printf( "flopper=%d\n", flopper );
Packit 577717
Packit 577717
	for ( int i = 0; i < 100000; i++ )
Packit 577717
#pragma omp parallel private(tid)
Packit 577717
	{
Packit 577717
		tid = omp_get_thread_num(  );
Packit 577717
		flopi[tid] = rand(  ) * 3;
Packit 577717
		flops[tid] = Thread( ( flopi[tid] / flopper ) % MAX_FLOPS );
Packit 577717
#pragma omp barrier
Packit 577717
#pragma omp master
Packit 577717
		if ( flops[tid] < flopi[tid] ) {
Packit 577717
			printf( "test iteration=%d\n", i );
Packit 577717
			for ( int j = 0; j < omp_get_num_threads(  ); j++ ) {
Packit 577717
				printf( "Thread %#x Value %6lld %c %6lld", j, flops[j],
Packit 577717
						( flops[j] < flopi[j] ) ? '<' : '=', flopi[j] );
Packit 577717
				for ( int k = 0; k < omp_get_num_threads(  ); k++ )
Packit 577717
					if ( ( k != j ) && ( flops[k] == flops[j] ) )
Packit 577717
						printf( " == Thread %#x!", k );
Packit 577717
				printf( "\n" );
Packit 577717
			}
Packit 577717
			test_fail( __FILE__, __LINE__, "value returned for thread",
Packit 577717
					   PAPI_EBUG );
Packit 577717
		}
Packit 577717
	}
Packit 577717
Packit 577717
	test_pass( __FILE__, NULL, 0 );
Packit 577717
	exit( 0 );
Packit 577717
}