Page 1 of 1

Is PAPI_atttach and inherit supported?

PostPosted: Fri May 29, 2015 12:52 am
by MrDalek
I am attempting to monitor a long running multi-threaded application (C++11, std::threads) from a separate application.

Using ctest/inherit.c as a starting point, I modified the code to include all call to attach before the call to PAPI_start
Code: Select all
if ( ( retval = PAPI_attach(EventSet, MACRO_PID) ) != PAPI_OK)
    test_fail_exit( __FILE__, __LINE__, "PAPI_attach", retval );


For now I compile it with the current PID of the running application.
If I specify a single-thread application, then valid values are reported.
If I specify a multi-thread application, then it reports 0 values.
If I specify an application that has a sequential stage followed by a parallel stage, followed by another sequential stage, then in the example below I see the counter increase run during the sequential stage, stop during the parallel stage, and resume again in the sequential stage.

Am I using these two options incorrectly?
Is there a way to externally track all events created by a multi-threaded application?

Working Example Code:
Code: Select all
#include <stdio.h>
#include <unistd.h>
#if defined(_AIX) || defined (__FreeBSD__) || defined (__APPLE__)
#include <sys/wait.h>       /* ARGH! */
#else
#include <wait.h>
#endif
#include "papi_test.h"

/*
Build Instructions:
   - place in src/ctest/ directory
   - run make -C ../
Testing Instructions:
   run the command below from the src/ctest/ directory

<launch application command> 2>&1 > /dev/null & gcc -I.. -I../testlib -I.. -g -DSTATIC_PAPI_EVENTS_TABLE -DPEINCLUDE="libpfm4/include/perfmon/perf_event.h" -D_REENTRANT -D_GNU_SOURCE -DUSE_COMPILER_TLS  -Wall -Ilibpfm4/include -Wextra -DPAPI_NO_MEMORY_MANAGEMENT -O0 inherit_attach.c ../testlib/libtestlib.a ../libpapi.a -DPID_VALUE=$!  -o inherit_attach && ./inherit_attach

#sequential test:
yes 2>&1 > /dev/null & gcc -I.. -I../testlib -I.. -g -DSTATIC_PAPI_EVENTS_TABLE -DPEINCLUDE="libpfm4/include/perfmon/perf_event.h" -D_REENTRANT -D_GNU_SOURCE -DUSE_COMPILER_TLS  -Wall -Ilibpfm4/include -Wextra -DPAPI_NO_MEMORY_MANAGEMENT -O0 inherit_attach.c ../testlib/libtestlib.a ../libpapi.a -DPID_VALUE=$!  -o inherit_attach && ./inherit_attach

Note: If the build command does not work for you, construct a new one by the following:
1) Log the output of the make command
2) Copy the line that compiles inherit.c
3) change references to inherit to inherity_attach
4) Add  -DPID_VALUE=$!   before the -o flag
 */
int
main( int argc, char **argv )
{
   int retval, pid, EventSet = PAPI_NULL;
   long long int values[] = {0};
   PAPI_option_t opt;

  tests_quiet( argc, argv );

  pid = PID_VALUE ;

   if ( ( retval = PAPI_library_init( PAPI_VER_CURRENT ) ) != PAPI_VER_CURRENT )
      test_fail_exit( __FILE__, __LINE__, "PAPI_library_init", retval );

   if ( ( retval = PAPI_create_eventset( &EventSet ) ) != PAPI_OK )
      test_fail_exit( __FILE__, __LINE__, "PAPI_create_eventset", retval );

   if ( ( retval = PAPI_assign_eventset_component( EventSet, 0 ) ) != PAPI_OK )
      test_fail_exit( __FILE__, __LINE__, "PAPI_assign_eventset_component", retval );

   memset( &opt, 0x0, sizeof ( PAPI_option_t ) );
   opt.inherit.inherit = PAPI_INHERIT_ALL;
   opt.inherit.eventset = EventSet;
   if ( ( retval = PAPI_set_opt( PAPI_INHERIT, &opt ) ) != PAPI_OK ) {
      if ( retval == PAPI_ECMP) {
         test_skip( __FILE__, __LINE__, "Inherit not supported by current component.\n", retval );
      } else {
         test_fail_exit( __FILE__, __LINE__, "PAPI_set_opt", retval );
      }
   }

   if ( ( retval = PAPI_query_event( PAPI_TOT_CYC ) ) != PAPI_OK )
      test_fail_exit( __FILE__, __LINE__, "PAPI_query_event", retval );

   if ( ( retval = PAPI_add_event( EventSet, PAPI_TOT_CYC ) ) != PAPI_OK )
      test_fail_exit( __FILE__, __LINE__, "PAPI_add_event", retval );


  if ( ( retval = PAPI_attach(EventSet, pid) ) != PAPI_OK)
    test_fail_exit( __FILE__, __LINE__, "PAPI_attach", retval );


   if ( ( retval = PAPI_start( EventSet ) ) != PAPI_OK )
      test_fail_exit( __FILE__, __LINE__, "PAPI_start", retval );


   long long int lastValue = -1;
   while (1) {
      if ( ( retval = PAPI_read( EventSet, values ) ) != PAPI_OK ) {
         printf("PAPI_Read Error %d\n", retval);
      } else if (lastValue != values[0]) {
         lastValue = values[0];
       printf( "PAPI_TOT_CYC: \t%lld\n", values[0] );
     }
   }

   return 1;
}

Re: Is PAPI_atttach and inherit supported?

PostPosted: Tue Jun 30, 2015 12:03 pm
by s_ragate
As far as I know the way you have used PAPI_INHERIT and PAPI_ATTACH combination is not exactly right. PAPI_INHERIT allows to collect all the counts from parent and children processes,altogether, i.e for an entire application. In your application, PAPI_INHERIT is in the profiling process and PAPI_ATTACH is done to an entirely unrelated process. I am curious to know what happens if you do the following:

main(){
:
:
:
Initialize PAPI here;
set the PAPI inherit option;
pid=fork();
in child process{
exec(your long running multithreaded application);
}
In parent process{
PAPI_start();
delay()
PAPI_stop();
}
}
Since there is no real computation happening in parent process, you can ignore those counts. Please let me if you try this