source: icXML/icXML-devel/PapiCounter.hpp @ 3566

Last change on this file since 3566 was 3566, checked in by cameron, 6 years ago

PapiCounter?

File size: 9.2 KB
Line 
1#ifndef PAPICOUNTER_HPP
2#define PAPICOUNTER_HPP
3
4#ifdef USE_PAPI
5
6#include <papi.h>
7#include <string.h>
8#include <iostream>
9
10#ifdef _MSC_VER
11#include <intrin.h>
12#pragma intrinsic(__rdtsc)
13#pragma intrinsic(_BitScanReverse)
14#endif
15
16#include <xercesc/util/XMLString.hpp>
17
18XERCES_CPP_NAMESPACE_BEGIN
19
20#ifdef PAPI_EVENT_SET1
21#define PAPI_EVENT_SET 1
22#endif
23#ifdef PAPI_EVENT_SET2
24#define PAPI_EVENT_SET 2
25#endif
26#ifdef PAPI_EVENT_SET3
27#define PAPI_EVENT_SET 3
28#endif
29#ifdef PAPI_EVENT_SET4
30#define PAPI_EVENT_SET 4
31#endif
32#ifdef PAPI_EVENT_SET5
33#define PAPI_EVENT_SET 5
34#endif
35
36#define PAPI_MEASURE_CSA_PMP 0
37#define PAPI_MEASURE_SP 1
38#define PAPI_MEASURE_EM 2
39#define PAPI_MEASURE_CSG 3
40#define PAPI_MEASURE_LCT 4
41#define PAPI_MEASURE_WF 5
42#define PAPI_MEASURE_NR 6
43#define PAPI_MEASURE_GV 7
44#define PAPI_MEASURE_DD 8
45#define PAPI_MEASURE_TOTAL 9
46
47#ifdef PAPI_EVENT_SET
48#define NEW_PAPI_COUNTER new PapiCounter<10>(PAPI_EVENT_SET)
49#define START_PAPI_COUNTER(papiCounter, groupIndex) papiCounter->start(groupIndex)
50#define STOP_PAPI_COUNTER(papiCounter, groupIndex) papiCounter->stop(groupIndex)
51#else
52#define NEW_PAPI_COUNTER ((IPapiCounter*)(0))
53#define START_PAPI_COUNTER(papiCounter, groupIndex)
54#define STOP_PAPI_COUNTER(papiCounter, groupIndex)
55#endif
56
57static const int PAPI_EVENTS[] =
58{
59    PAPI_L1_DCM, PAPI_L1_ICM, PAPI_L2_DCM, PAPI_L2_ICM,     // event set 1
60
61    PAPI_L3_TCM, PAPI_TLB_DM, PAPI_TOT_INS, PAPI_TOT_CYC,   // event set 2
62
63    PAPI_BR_INS, PAPI_BR_MSP, PAPI_TLB_IM, PAPI_STL_ICY,    // event set 3
64
65    PAPI_L2_DCA, PAPI_L2_ICA, PAPI_L3_DCA, PAPI_L3_ICA,     // event set 4
66
67    PAPI_L2_TCW, PAPI_L3_TCW, PAPI_SR_INS, PAPI_LD_INS      // event set 5
68
69};
70
71class IPapiCounter
72{
73    public:
74
75        enum { MAX_EVENT_SET = 5 };
76
77        virtual void start(const int groupIndex = 0) = 0;
78        virtual void stop(const int groupIndex = 0) = 0;
79        virtual void write(std::ostream & out) const = 0;
80};
81
82template <bool accumulate = false, int Groups = 1>
83class PapiCounter : public IPapiCounter
84{
85    typedef long_long papi_counter_t;
86
87public:
88
89    inline PapiCounter(const int eventSet);
90    inline ~PapiCounter();
91
92    virtual void start(const int groupIndex = 0);
93    virtual void stop(const int groupIndex = 0);
94    virtual void write(std::ostream & out) const;
95
96private:
97
98    int                    fEventSet;                                                                   // PAPI event set
99    papi_counter_t         fStartedAt[4 * (Groups ? Groups : 1)];
100    papi_counter_t         fIntervals[4 * (Groups ? Groups : 1)];
101    int                    fEvent[4];
102    int                    fEvents;
103};
104
105template <bool accumulate, int Groups>
106PapiCounter<accumulate, Groups>::PapiCounter(const int eventSet)
107{
108    // PAPI init
109    int rval = PAPI_library_init(PAPI_VER_CURRENT);
110    if (rval != PAPI_VER_CURRENT)
111    {
112        std::cerr << "Fatal Error: " << __FILE__ << ":" << __LINE__ << " PAPI code: " << PAPI_strerror(rval) << std::endl;
113        exit(1);
114    }
115
116    memcpy(fEvent, &PAPI_EVENTS[(eventSet - 1) * 4], sizeof(int) * 4);
117    memset(fStartedAt, 0, sizeof(papi_counter_t) * 4);
118    memset(fIntervals, 0, sizeof(papi_counter_t) * 4 * Groups);
119
120    // PAPI create event set
121    fEventSet = PAPI_NULL;
122    if ((rval = PAPI_create_eventset(&fEventSet)) != PAPI_OK)
123    {
124        std::cerr << "Fatal Error: " << __FILE__ << ":" << __LINE__ << " PAPI code: " << PAPI_strerror(rval) << std::endl;
125        exit(1);
126    }
127
128    fEvents = 4;
129
130    // PAPI fill event set
131    if ((rval = PAPI_add_events(fEventSet, fEvent, fEvents)) != PAPI_OK)
132    {
133        std::cerr << "Fatal Error: " << __FILE__ << ":" << __LINE__ << " PAPI code: " << PAPI_strerror(rval < PAPI_OK ? rval : PAPI_EINVAL) << ':' << rval << std::endl;
134        exit(1);
135    }
136
137    // Call PAPI start on construction, to force PAPI initialization
138    rval = PAPI_start(fEventSet);
139    if (rval != PAPI_OK)
140    {
141        std::cerr << "Fatal Error: " << __FILE__ << ":" << __LINE__ << " PAPI code: " << PAPI_strerror(rval) << std::endl;
142        exit(1);
143    }
144}
145
146template <bool accumulate, int Groups>
147PapiCounter<accumulate, Groups>::~PapiCounter()
148{
149    // Call PAPI stop on destruction
150    int rval = PAPI_stop(fEventSet, NULL);
151    if (rval != PAPI_OK)
152    {
153        std::cerr << "Fatal Error: " << __FILE__ << ":" << __LINE__ << " PAPI code: " << PAPI_strerror(rval) << std::endl;
154        exit(1);
155    }
156
157    if ((rval =  PAPI_cleanup_eventset(fEventSet) != PAPI_OK))
158    {
159        std::cerr << "Fatal Error: " << __FILE__ << ":" << __LINE__ << " PAPI code: " << PAPI_strerror(rval) << std::endl;
160        exit(1);
161    }
162
163    // PAPI free all events
164    if ((rval = PAPI_destroy_eventset(&fEventSet) != PAPI_OK))
165    {
166        std::cerr << "Fatal Error: " << __FILE__ << ":" << __LINE__ << " PAPI code: " << PAPI_strerror(rval) << std::endl;
167        exit(1);
168    }
169}
170
171template <bool accumulate, int Groups>
172void PapiCounter<accumulate, Groups>::start(const int groupIndex)
173{
174    int rval = PAPI_read(fEventSet, &fStartedAt[groupIndex * 4]);
175    if (rval != PAPI_OK)
176    {
177        std::cerr << "Fatal Error: " << __FILE__ << ":" << __LINE__ << " PAPI code: " << PAPI_strerror(rval) << std::endl;
178        exit(1);
179
180    }
181}
182
183// PAPI Low Level API Wrapper: Records the difference Events of the current start interval array values set into the values.
184template <bool accumulate, int Groups>
185void PapiCounter<accumulate, Groups>::stop(const int groupIndex)
186{
187    papi_counter_t endedAt[4];
188
189    int rval = PAPI_read(fEventSet, endedAt);
190    if (rval != PAPI_OK)
191    {
192        std::cerr << "Fatal Error: " << __FILE__ << ":" << __LINE__ << " PAPI code: " << PAPI_strerror(rval) << std::endl;
193        exit(1);
194
195    }
196
197    papi_counter_t * interval = &fIntervals[groupIndex * 4];
198    papi_counter_t * startedAt = &fStartedAt[groupIndex * 4];
199
200    for (int i = 0; i < fEvents; i++)
201    {
202        interval[i] = (accumulate ? interval[i] : 0) + (endedAt[i] - startedAt[i]);
203    }
204}
205
206template <bool accumulate, int Groups>
207void PapiCounter<accumulate, Groups>::write(std::ostream & out) const
208{
209    // Convert PAPI codes to names
210    char eventName[PAPI_MAX_STR_LEN + 1] = {','};
211
212
213    if (Groups == 1)
214    {
215        for (size_t j = 0; j < fEvents; j++)
216        {
217            int rval = PAPI_event_code_to_name(fEvent[j], eventName + 1);
218            if (rval != PAPI_OK)
219            {
220                memset(eventName + 1, '?', 16);
221                eventName[16 + 1] = 0;
222            }
223            out << eventName << ':' << fIntervals[j];
224        }
225    }
226    else
227    {       
228        for (size_t i = 0; i < Groups; i++)
229        {
230            out << ",GROUP:";
231
232            switch (i)
233            {
234                case PAPI_MEASURE_CSA_PMP: out << "CSA+PMP"; break;
235                case PAPI_MEASURE_SP: out << "SP"; break;
236                case PAPI_MEASURE_EM: out << "EM"; break;
237                case PAPI_MEASURE_CSG: out << "CSG"; break;
238                case PAPI_MEASURE_LCT: out << "LCT"; break;
239                case PAPI_MEASURE_WF: out << "WF"; break;
240                case PAPI_MEASURE_NR: out << "NR"; break;
241                case PAPI_MEASURE_GV: out << "GV"; break;
242                case PAPI_MEASURE_DD: out << "DD+API"; break;
243                case PAPI_MEASURE_TOTAL: out << "TOTAL"; break;
244            }
245
246            for (size_t j = 0; j < fEvents; j++)
247            {
248                int rval = PAPI_event_code_to_name(fEvent[j], eventName + 1);
249                if (rval != PAPI_OK)
250                {
251                    memset(eventName + 1, '?', 16);
252                    eventName[16 + 1] = 0;
253                }
254                out << eventName << ':' << fIntervals[i * 4 + j];
255            }
256        }
257    }
258}
259
260/** SPECAILIZED INSTANCE OF PAPICOUNTER<0> TO SIMPLY READ THE CYCLE COUNT! **/
261
262
263template <bool accumulate>
264class PapiCounter<accumulate, 0> : public IPapiCounter
265{
266    typedef uint64_t timestamp_t;
267
268public:
269
270    inline PapiCounter(int)
271    : fStartAt(0)
272    , fInterval(0)
273    {
274
275    }
276
277    inline ~PapiCounter()
278    {
279
280    }
281
282    virtual void start(const int groupIndex = 0)
283    {
284        fStartAt = read_cycle_counter();
285    }
286
287    virtual void stop(const int groupIndex = 0)
288    {
289        timestamp_t endAt = read_cycle_counter();
290        fInterval += endAt - fStartAt;
291    }
292
293    virtual void write(std::ostream & out) const
294    {
295        out << "CYCLES:" << fInterval;
296    }
297
298private:
299
300    static inline timestamp_t read_cycle_counter()
301    {
302        #ifdef __GNUC__
303            timestamp_t ts;
304            #ifdef __x86_64__
305                unsigned int eax, edx;
306                asm volatile("rdtsc" : "=a" (eax), "=d" (edx));
307                ts = ((timestamp_t) eax) | (((timestamp_t) edx) << 32);
308            #else
309                asm volatile("rdtsc\n" : "=A" (ts));
310            #endif
311            return (ts);
312        #elif defined(_MSC_VER)
313            return __rdtsc();
314        #endif
315    }
316
317private:
318
319    timestamp_t             fStartAt;
320    timestamp_t             fInterval;
321};
322
323/** FRIENDLY OSTREAM OVERRIDE **/
324
325inline static std::ostream & operator << (std::ostream & out, const IPapiCounter * papiCounter)
326{
327    papiCounter->write(out);
328    return out;
329}
330
331inline static std::ostream & operator << (std::ostream & out, const IPapiCounter & papiCounter)
332{
333    papiCounter.write(out);
334    return out;
335}
336
337XERCES_CPP_NAMESPACE_END
338
339#else
340
341#define START_PAPI_COUNTER(x,y)
342#define STOP_PAPI_COUNTER(x,y)
343
344#endif
345
346#endif // PAPICOUNTER_HPP
Note: See TracBrowser for help on using the repository browser.