source: icGREP/icgrep-devel/icgrep/util/papi_helper.hpp @ 5733

Last change on this file since 5733 was 4983, checked in by cameron, 3 years ago

Move items to util directory

File size: 3.8 KB
Line 
1#ifndef PAPICOUNTER_HPP
2#define PAPICOUNTER_HPP
3
4#include <papi.h>
5#include <string>
6#include <iostream>
7#include <stdexcept>
8
9namespace papi {
10
11class IPapiCounter {
12    public:
13        virtual void start() = 0;
14        virtual void stop() = 0;
15        virtual void write(std::ostream & out) const = 0;
16};
17
18template <unsigned N>
19class PapiCounter : public IPapiCounter
20{
21    typedef long_long papi_counter_t;
22
23public:
24
25    inline PapiCounter(std::initializer_list<int> events);
26    inline ~PapiCounter();
27
28    virtual void start();
29    virtual void stop();
30    virtual void write(std::ostream & out) const;
31
32private:
33
34    int                    fEventSet;                                                                   // PAPI event set
35    papi_counter_t         fStartedAt[N];
36    papi_counter_t         fIntervals[N];
37    int                    fEvent[N];
38};
39
40template <unsigned N>
41PapiCounter<N>::PapiCounter(std::initializer_list<int> events) {
42
43    // PAPI init
44    int rval = PAPI_library_init(PAPI_VER_CURRENT);
45    if (rval != PAPI_VER_CURRENT) {
46        throw std::runtime_error("PAPI Library Init Error: " + std::string(PAPI_strerror(rval)));
47    }
48    std::copy(events.begin(), events.end(), fEvent);
49    memset(fStartedAt, 0, sizeof(papi_counter_t) * N);
50    memset(fIntervals, 0, sizeof(papi_counter_t) * N);
51
52    // PAPI create event set
53    fEventSet = PAPI_NULL;
54    if ((rval = PAPI_create_eventset(&fEventSet)) != PAPI_OK) {
55        throw std::runtime_error("PAPI Create Event Set Error: " + std::string(PAPI_strerror(rval)));
56    }
57
58    // PAPI fill event set
59    if ((rval = PAPI_add_events(fEventSet, fEvent, N)) != PAPI_OK) {
60        throw std::runtime_error("PAPI Add Events Error: " + std::string(PAPI_strerror(rval < PAPI_OK ? rval : PAPI_EINVAL)));
61    }
62
63    // Call PAPI start on construction, to force PAPI initialization
64    rval = PAPI_start(fEventSet);
65    if (rval != PAPI_OK) {
66        throw std::runtime_error("PAPI Start Error: " + std::string(PAPI_strerror(rval)));
67    }
68}
69
70template <unsigned N>
71PapiCounter<N>::~PapiCounter() {
72    // Call PAPI stop on destruction
73    int rval = PAPI_stop(fEventSet, nullptr);
74    if (rval != PAPI_OK) {
75        throw std::runtime_error(" PAPI code: " + std::string(PAPI_strerror(rval)));
76    }
77    if ((rval =  PAPI_cleanup_eventset(fEventSet) != PAPI_OK)) {
78        throw std::runtime_error("PAPI code: " + std::string(PAPI_strerror(rval)));
79    }
80    // PAPI free all events
81    if ((rval = PAPI_destroy_eventset(&fEventSet) != PAPI_OK)) {
82        throw std::runtime_error("PAPI code: " + std::string(PAPI_strerror(rval)));
83    }
84}
85
86template <unsigned N>
87void PapiCounter<N>::start() {
88    int rval = PAPI_read(fEventSet, fStartedAt);
89    if (rval != PAPI_OK) {
90        throw std::runtime_error("PAPI code: " + std::string(PAPI_strerror(rval)));
91    }
92}
93
94// PAPI Low Level API Wrapper: Records the difference Events of the current start interval array values set into the values.
95template <unsigned N>
96void PapiCounter<N>::stop() {
97    papi_counter_t endedAt[N];
98    int rval = PAPI_read(fEventSet, endedAt);
99    if (rval != PAPI_OK) {
100        throw std::runtime_error("PAPI code: " + std::string(PAPI_strerror(rval)));
101    }
102    for (unsigned i = 0; i != N; i++) {
103        fIntervals[i] = (endedAt[i] - fStartedAt[i]);
104    }
105}
106
107template <unsigned N>
108void PapiCounter<N>::write(std::ostream & out) const {
109    // Convert PAPI codes to names
110    char eventName[PAPI_MAX_STR_LEN + 1];
111    for (unsigned i = 0; i != N; i++) {
112        int rval = PAPI_event_code_to_name(fEvent[i], eventName);
113        if (rval != PAPI_OK) {
114            memset(eventName + 1, '?', 16);
115            eventName[16 + 1] = 0;
116        }
117        out << ';' << eventName << '|' << fIntervals[i];
118    }
119}
120
121inline static std::ostream & operator << (std::ostream & out, const IPapiCounter & papiCounter) {
122    papiCounter.write(out);
123    return out;
124}
125
126}
127
128#endif // PAPICOUNTER_HPP
Note: See TracBrowser for help on using the repository browser.