14#include "arcane/std/PapiPerformanceService.h"
16#include "arcane/utils/ValueConvert.h"
17#include "arcane/utils/PlatformUtils.h"
18#include "arcane/utils/FatalErrorException.h"
19#include "arcane/utils/CriticalSection.h"
20#include "arcane/utils/IPerformanceCounterService.h"
22#include "arcane/FactoryService.h"
23#include "arcane/IParallelSuperMng.h"
25#include "arcane/std/ProfilingInfo.h"
26#include "arcane/impl/TimerMng.h"
48 if (PAPI_is_initialized()==PAPI_NOT_INITED){
49 int retval = PAPI_library_init(PAPI_VER_CURRENT);
50 if (retval!=PAPI_VER_CURRENT && retval>0)
51 ARCANE_FATAL(
"PAPI version mismatch r={0} current={1}",retval,PAPI_VER_CURRENT);
53 ARCANE_FATAL(
"Error in PAPI_library_init r={0} msg={1}",retval,PAPI_strerror(retval));
77PapiPerformanceService::
78PapiPerformanceService(
const ServiceBuildInfo& sbi)
81, m_event_set(PAPI_NULL)
82, m_application(sbi.application())
89PapiPerformanceService::
90~PapiPerformanceService()
100ProfInfos* global_infos =
nullptr;
101int global_nb_total_call = 0;
107void PapiPerformanceService::
108arcane_papi_handler(
int EventSet,
void *address, long_long overflow_vector,
void *context)
110 ARCANE_UNUSED(context);
111 static bool is_in_handler =
false;
117 if (Exception::hasPendingException()){
118 cout <<
"** WARNING: PapiHandler in pending exception\n";
124 is_in_handler =
true;
125 ++global_nb_total_call;
127 int overflow_event[MAX_COUNTER];
128 int nb_overflow_event = MAX_COUNTER;
129 PAPI_get_overflow_event_index(EventSet,overflow_vector,overflow_event,&nb_overflow_event);
130 global_infos->addEvent(address,overflow_event,nb_overflow_event);
131 is_in_handler =
false;
137bool PapiPerformanceService::
138_addEvent(
int event_code,
int event_index)
140 char event_name[PAPI_MAX_STR_LEN];
142 int retval = PAPI_add_event(m_event_set,event_code);
143 PAPI_event_code_to_name(event_code,event_name);
144 info() <<
"Adding Papi event name=" << event_name;
145 if (retval!=PAPI_OK){
146 pwarning() <<
"** ERROR in add_event (index=" << event_index <<
") r=" << retval
147 <<
" msg=" << PAPI_strerror(retval);
156void PapiPerformanceService::
160 if (m_is_initialized)
165 m_is_initialized =
true;
170 info() <<
"PROFILING: start profiling using 'PAPI' version="
191 start =
reinterpret_cast<caddr_t>(
prginfo->address_info.text_start);
194 info() <<
"** PROGRAM INFOS: start=" << (
long)start <<
" end=" << (
long)end <<
" length=" << (end-start);
216 for( Integer i=0; i<
nb_str; ++i ){
218 info() <<
"USER_EVENT name=" <<
ename;
222 pwarning() <<
"Can not set event from name=" <<
ename <<
" r=" <<
retval;
236 String period_str = platform::getEnvironmentVariable(
"ARCANE_PROFILING_PERIOD");
240 pwarning() <<
"Can not convert '" <<
period_str <<
"' to int";
243 String only_str = platform::getEnvironmentVariable(
"ARCANE_PROFILING_ONLYFLOPS");
255 for( Integer i=0; i<
nb_event; ++i ){
261 fatal() <<
"** ERROR in papi_overflow i=" << i <<
" r=" <<
retval
265 pwarning() <<
"** ERROR in papi_overflow i=" << i <<
" r=" <<
retval
271 info() <<
"Période de sampling: (en évènements) " << m_period;
279void PapiPerformanceService::
298void PapiPerformanceService::
306void PapiPerformanceService::
309 float real_time = 0.0f;
310 float proc_time = 0.0f;
311 long long flpins = 0.0;
317#if PAPI_VERSION >= PAPI_VERSION_NUMBER(6,0,0,0)
318 int retval = PAPI_flops_rate(PAPI_DP_OPS, &real_time, &proc_time, &flpins, &mflops);
320 int retval = PAPI_flops(&real_time, &proc_time, &flpins, &mflops);
323 error() <<
"** ERROR in PAPI_flops r=" << retval;
325 info() <<
"PAPI_Flops: real_time=" << real_time
326 <<
" proc_time=" << proc_time
327 <<
" flpins=" << flpins
328 <<
" mflips=" << mflops;
335void PapiPerformanceService::
353 m_is_running =
false;
361void PapiPerformanceService::
371void PapiPerformanceService::
381void PapiPerformanceService::
391void PapiPerformanceService::
410 m_is_init(
false), m_elapsed_us(0), m_elapsed_cycle()
419 void _addEvent(
int event);
421 Real stop(
const char*
msg);
458 int retval = PAPI_thread_init((
unsigned long (*)(
void)) (pthread_self));
459 if (retval != PAPI_OK)
462 retval = PAPI_create_eventset(&m_event_set);
466 _addEvent(PAPI_TOT_CYC);
467 _addEvent(PAPI_DP_OPS);
468 m_values.resize(m_nb_event);
470 m_start_values.resize(m_nb_event);
471 m_start_values.fill(0);
473 retval = PAPI_start(m_event_set);
474 if (retval != PAPI_OK)
485 int retval = PAPI_add_event(m_event_set,event);
486 if (retval!=PAPI_OK){
487 cerr <<
"** CAN NOT FIND EVENT " <<
event <<
'\n';
499 int retval = PAPI_read(m_event_set,m_start_values.data());
500 if (retval!=PAPI_OK){
501 cerr <<
"** CAN NOT START EVENT\n";
503 m_elapsed_us = PAPI_get_real_usec();
504 m_elapsed_cycle = PAPI_get_real_cyc();
513 int retval = PAPI_read(m_event_set,m_values.data());
514 if (retval!=PAPI_OK){
515 cerr <<
"** CAN NOT STOP EVENT\n";
517 long_long elapsed_us = PAPI_get_real_usec() - m_elapsed_us;
520 double sec_time = ((double)elapsed_us) / 1.0e6;
522 std::cout <<
" -- -- Time: ";
524 std::cout << msg <<
" = ";
526 std::cout << sec_time <<
" ";
530 long_long nb_cycle = m_values[0]-m_start_values[0];
531 long_long nb_flop = m_values[1]-m_start_values[1];
534 std::cout << nb_cycle <<
" ";
536 std::cout << nb_flop;
540 std::cout << nb_flop/elapsed_us;
579 m_event_set(
PAPI_NULL), m_is_started(
false)
613 void _addEvent(
int event)
617 error() <<
"** CAN NOT FIND EVENT " <<
event <<
'\n';
638 m_is_started =
false;
650 error() <<
"Error in 'PAPI_read' during getCounters() r=" <<
retval;
652 Integer n = m_nb_event;
654 for(
int i=0; i<n; ++i )
655 counters[i] = (Int64)values[i] - counters[i];
658 for(
int i=0; i<n; ++i )
659 counters[i] = values[i];
665 std::array<Int64,MIN_COUNTER_SIZE> values;
667 getCounters(view,
false);
675 bool m_is_started =
false;
682 ServiceProperty(
"PapiPerformanceCounterService",ST_Application),
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro pour déclarer une interface lors de l'enregistrement d'un service.
Tableau d'items de types quelconques.
Section critique en multi-thread.
Interface d'un gestionnaire de timer.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Real _getRealTime() override
Retourne le temps réel.
void _setRealTime() override
Positionne un timer réel.
Structure contenant les informations pour créer un service.
Vue modifiable d'un tableau d'un type T.
Interface du gestionnaire de traces.
Chaîne de caractères unicode.
Classe d'accès aux traces.
ITraceMng * traceMng() const
Gestionnaire de trace.
Vecteur 1D de données avec sémantique par valeur (style STL).
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro pour enregistrer un service.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
@ ST_Application
Le service s'utilise au niveau de l'application.