|
Packit |
577717 |
/* This test exercises the PAPI_TOT_CYC and PAPI_REF_CYC counters.
|
|
Packit |
577717 |
|
|
Packit |
577717 |
PAPI_TOT_CYC should measure the number of cycles required to do
|
|
Packit |
577717 |
a fixed amount of work.
|
|
Packit |
577717 |
It should be roughly constant for constant work, regardless of the
|
|
Packit |
577717 |
speed state a core is in.
|
|
Packit |
577717 |
|
|
Packit |
577717 |
PAPI_REF_CYC should measure the number of cycles at a constant
|
|
Packit |
577717 |
reference clock rate, independent of the actual clock rate of the core.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
PAPI_REF_CYC has various issues on Intel chips:
|
|
Packit |
577717 |
|
|
Packit |
577717 |
On older machines PAPI uses UNHALTED_REFERENCE_CYCLES but this
|
|
Packit |
577717 |
means different things on different architectures
|
|
Packit |
577717 |
|
|
Packit |
577717 |
+ On Core2/Atom this maps to the special Fixed Counter 2
|
|
Packit |
577717 |
CPU_CLK_UNHALTED.REF
|
|
Packit |
577717 |
This counts at the same rate as the TSC (PAPI_get_real_cyc())
|
|
Packit |
577717 |
And also seems to match PAPI_TOT_CYC
|
|
Packit |
577717 |
It is documented as having a fixed ratio to the
|
|
Packit |
577717 |
CPU_CLK_UNHALTED.BUS (3c/1) event.
|
|
Packit |
577717 |
|
|
Packit |
577717 |
+ On Nehalem/Westemere this also maps to Fixed Counter 2.
|
|
Packit |
577717 |
Again, counts same rate as the TSC and returns
|
|
Packit |
577717 |
CPU_CLK_UNHALTED.REF_P (3c/1)
|
|
Packit |
577717 |
times the "Maximum Non-Turbo Ratio"
|
|
Packit |
577717 |
|
|
Packit |
577717 |
+ Same for Sandybridge/Ivybridge
|
|
Packit |
577717 |
|
|
Packit |
577717 |
On newer HSW,BDW,SKL machines PAPI uses a different type of event
|
|
Packit |
577717 |
CPU_CLK_THREAD_UNHALTED:REF_XCLK
|
|
Packit |
577717 |
|
|
Packit |
577717 |
+ On Haswell machines this is just the reference clock
|
|
Packit |
577717 |
(100MHz?)
|
|
Packit |
577717 |
+ On Sandybridge this is off by a factor of 8x?
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* NOTE:
|
|
Packit |
577717 |
PAPI_get_virt_cyc() returns a lie!
|
|
Packit |
577717 |
It's just virt_time() * max_theoretical_MHz
|
|
Packit |
577717 |
so no point in checking that */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#include <stdio.h>
|
|
Packit |
577717 |
#include <stdlib.h>
|
|
Packit |
577717 |
#include <unistd.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#include "papi.h"
|
|
Packit |
577717 |
#include "papi_test.h"
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#include "testcode.h"
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define NUM_FLOPS 20000000
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void work (int EventSet, int sleep_test, int quiet)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int retval;
|
|
Packit |
577717 |
long long values[2];
|
|
Packit |
577717 |
long long elapsed_us, elapsed_cyc, elapsed_virt_us, elapsed_virt_cyc;
|
|
Packit |
577717 |
double cycles_error;
|
|
Packit |
577717 |
int numflops = NUM_FLOPS;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Gather before stats */
|
|
Packit |
577717 |
elapsed_us = PAPI_get_real_usec( );
|
|
Packit |
577717 |
elapsed_cyc = PAPI_get_real_cyc( );
|
|
Packit |
577717 |
elapsed_virt_us = PAPI_get_virt_usec( );
|
|
Packit |
577717 |
elapsed_virt_cyc = PAPI_get_virt_cyc( );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Start PAPI */
|
|
Packit |
577717 |
retval = PAPI_start( EventSet );
|
|
Packit |
577717 |
if ( retval != PAPI_OK ) {
|
|
Packit |
577717 |
test_fail( __FILE__, __LINE__, "PAPI_start", retval );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* our test code */
|
|
Packit |
577717 |
if (sleep_test) {
|
|
Packit |
577717 |
sleep(2);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
else {
|
|
Packit |
577717 |
do_flops( numflops, 1 );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Stop PAPI */
|
|
Packit |
577717 |
retval = PAPI_stop( EventSet, values );
|
|
Packit |
577717 |
if ( retval != PAPI_OK ) {
|
|
Packit |
577717 |
test_fail( __FILE__, __LINE__, "PAPI_stop", retval );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Calculate total values */
|
|
Packit |
577717 |
elapsed_virt_us = PAPI_get_virt_usec( ) - elapsed_virt_us;
|
|
Packit |
577717 |
elapsed_virt_cyc = PAPI_get_virt_cyc( ) - elapsed_virt_cyc;
|
|
Packit |
577717 |
elapsed_us = PAPI_get_real_usec( ) - elapsed_us;
|
|
Packit |
577717 |
elapsed_cyc = PAPI_get_real_cyc( ) - elapsed_cyc;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!quiet) {
|
|
Packit |
577717 |
printf( "-------------------------------------------------------------------------\n" );
|
|
Packit |
577717 |
if (sleep_test) printf("Sleeping for 2s\n");
|
|
Packit |
577717 |
else printf( "Using %d iterations of c += a*b\n", numflops );
|
|
Packit |
577717 |
printf( "-------------------------------------------------------------------------\n" );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
printf( "PAPI_TOT_CYC : \t%10lld\n", values[0] );
|
|
Packit |
577717 |
printf( "PAPI_REF_CYC : \t%10lld\n", values[1] );
|
|
Packit |
577717 |
printf( "Real usec : \t%10lld\n", elapsed_us );
|
|
Packit |
577717 |
printf( "Real cycles : \t%10lld\n", elapsed_cyc );
|
|
Packit |
577717 |
printf( "Virt usec : \t%10lld\n", elapsed_virt_us );
|
|
Packit |
577717 |
printf( "Virt cycles (estimate) : \t%10lld\n", elapsed_virt_cyc );
|
|
Packit |
577717 |
printf( "Estimated GHz : \t%10.3lf\n", (double) elapsed_cyc/(double)elapsed_us/1000.0);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
printf( "-------------------------------------------------------------------------\n" );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (sleep_test) {
|
|
Packit |
577717 |
if (!quiet) {
|
|
Packit |
577717 |
printf( "Verification: PAPI_REF_CYC should be much lower than real_usec\n");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (values[1]>elapsed_us) {
|
|
Packit |
577717 |
if (!quiet) printf("PAPI_REF_CYC too high!\n");
|
|
Packit |
577717 |
test_fail( __FILE__, __LINE__, "PAPI_REF_CYC too high", 0 );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
else {
|
|
Packit |
577717 |
/* PAPI_REF_CYC should be roughly the same as TSC when busy */
|
|
Packit |
577717 |
/* on Intel chips */
|
|
Packit |
577717 |
if (!quiet) {
|
|
Packit |
577717 |
printf( "Verification: real_cyc should be roughly PAPI_REF_CYC\n");
|
|
Packit |
577717 |
printf( " real_usec should be roughly virt_usec (on otherwise idle system)\n");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
cycles_error=100.0*
|
|
Packit |
577717 |
((double)values[1]-((double)elapsed_cyc))
|
|
Packit |
577717 |
/values[1];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ((cycles_error>10.0) || (cycles_error<-10.0)) {
|
|
Packit |
577717 |
if (!quiet) printf("Error of %.2f%%\n",cycles_error);
|
|
Packit |
577717 |
test_fail( __FILE__, __LINE__, "PAPI_REF_CYC validation", 0 );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
cycles_error=100.0*
|
|
Packit |
577717 |
((double)elapsed_us-(double)elapsed_virt_us)
|
|
Packit |
577717 |
/(double)elapsed_us;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ((cycles_error>10.0) || (cycles_error<-10.0)) {
|
|
Packit |
577717 |
if (!quiet) printf("Error of %.2f%%\n",cycles_error);
|
|
Packit |
577717 |
test_warn( __FILE__, __LINE__, "real_us validation", 0 );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
main( int argc, char **argv )
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int retval;
|
|
Packit |
577717 |
int EventSet = PAPI_NULL;
|
|
Packit |
577717 |
int quiet;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Set TESTS_QUIET variable */
|
|
Packit |
577717 |
quiet = tests_quiet( argc, argv );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Init the PAPI library */
|
|
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 |
/* Check the ref cycles event */
|
|
Packit |
577717 |
retval = PAPI_query_named_event("PAPI_REF_CYC");
|
|
Packit |
577717 |
if (PAPI_OK!=retval) {
|
|
Packit |
577717 |
if (!quiet) printf("No PAPI_REF_CYC available\n");
|
|
Packit |
577717 |
test_skip( __FILE__, __LINE__,
|
|
Packit |
577717 |
"PAPI_REF_CYC is not defined on this platform.", 0);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* create an eventset */
|
|
Packit |
577717 |
retval = PAPI_create_eventset( &EventSet );
|
|
Packit |
577717 |
if ( retval != PAPI_OK ) {
|
|
Packit |
577717 |
test_fail( __FILE__, __LINE__, "PAPI_create_eventset", retval );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* add core cycle event */
|
|
Packit |
577717 |
retval = PAPI_add_named_event( EventSet, "PAPI_TOT_CYC");
|
|
Packit |
577717 |
if ( retval != PAPI_OK ) {
|
|
Packit |
577717 |
test_fail( __FILE__, __LINE__,
|
|
Packit |
577717 |
"PAPI_add_named_event: PAPI_TOT_CYC", retval );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* add ref cycle event */
|
|
Packit |
577717 |
retval = PAPI_add_named_event( EventSet, "PAPI_REF_CYC");
|
|
Packit |
577717 |
if ( retval != PAPI_OK ) {
|
|
Packit |
577717 |
test_fail( __FILE__, __LINE__,
|
|
Packit |
577717 |
"PAPI_add_events: PAPI_REF_CYC", retval );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!quiet) {
|
|
Packit |
577717 |
printf("Test case sleeping: "
|
|
Packit |
577717 |
"Look at TOT and REF cycles.\n");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
work(EventSet, 1, quiet);
|
|
Packit |
577717 |
// do_flops(10*numflops);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!quiet) {
|
|
Packit |
577717 |
printf( "\nTest case busy:\n" );
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
work(EventSet, 0, quiet);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
test_pass( __FILE__ );
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|