source: trunk/lib/perflib/BOM_Profiler.h @ 462

Last change on this file since 462 was 462, checked in by cameron, 9 years ago

perflib and block_carry.h

File size: 5.2 KB
Line 
1/*
2    BOM_Profiler.h - Binary Order of Magnitude Execution Time Profiler
3    Copyright (C) 2010  Robert D. Cameron and Dan Lin
4    Version 0.4
5    Licensed to the general public under Academic Free License version 3.0
6
7BOM_Profiler provides a lightweight multiplatform execution time profiling
8utility based on processor cycle counters.  It uses a binary logarithmic
9histogram technique that is useful in both highlighting patterns of
10cycle time distributions as well as identifing outliers in timing events
11due to interruptions for operating system services.
12
13In essence, BOM profiler is designed to collect statistics over a number
14of repetitions of particular timed events.  Statistics are gathered in the
15form of a logarithmic histogram of cycle times for processing a fixed number
16of elements between calls to start_BOM_interval and end_BOM_interval. 
17For example, an interval may correspond to processing 1024 single-byte
18elements by a particular routine.
19
20A timer t is created and initialized by a call to t = init_BOM_timer(). 
21Given a timer t, start_BOM_interval(t) initiates an interval measurement
22which completes with end_BOM_interval(t, n), where n is the number of
23elements processed. 
24
25dump_BOM_table(t) prints out a rudimentary histogram of the recorded
26intervals for a particular timer. 
27
28Although the basic concept of BOM_Profiler is architecture independent,
29processor-dependent routines for accessing time-stamp counters and
30determining the binary order of magnitude are included through external
31files.
32
33
34*/
35
36#ifndef BOM_Profiler_H
37#define BOM_Profiler_H
38
39#include <iostream>
40
41using namespace std;
42
43#include "i386_timer.h"
44
45#define BIT_COUNT 64
46#define MAX_TIMER_ENTRIES (1<<18)
47#define TIMER_SCALE_FACTOR 1000
48
49struct BOM_Table {
50  // current timing interval information
51  int timer_on;
52  int full;
53  timestamp_t interval_start[MAX_TIMER_ENTRIES];
54  timestamp_t interval_end[MAX_TIMER_ENTRIES];
55  unsigned int interval_elems[MAX_TIMER_ENTRIES]; 
56  unsigned int current_entry;
57};
58
59typedef struct BOM_Table BOM_Table;
60
61BOM_Table * init_BOM_timer () {
62  BOM_Table * timer_table = (BOM_Table *) malloc(sizeof(BOM_Table));
63  if (!timer_table) {
64    printf("Couldn't initialize BOM timer.\n");
65    exit(-1);
66  }
67  timer_table -> current_entry = 0;
68  timer_table -> full = 0;
69  timer_table -> timer_on = 0;
70  return timer_table;
71}
72
73
74static inline void start_BOM_interval(BOM_Table * timer_table) {
75  timer_table->timer_on = 1;
76  timer_table->interval_start[timer_table->current_entry] = read_cycle_counter();
77}
78
79static inline void end_BOM_interval(BOM_Table * timer_table, unsigned int elems) {
80  if (timer_table->timer_on) {
81    timer_table->interval_end[timer_table->current_entry] = read_cycle_counter();
82    timer_table->interval_elems[timer_table->current_entry] = elems;
83    timer_table->current_entry++;
84    if(timer_table->current_entry >= MAX_TIMER_ENTRIES) {
85      timer_table->full=1;
86      timer_table->current_entry=0;
87    }
88    timer_table->timer_on = 0;
89  }
90  else
91        fprintf(stderr,"Time interval end without a start!\n"); 
92}
93
94void dump_BOM_table(BOM_Table * timer_table) {
95  // an array of counts and timings per binary order of magnitude
96  int BOM_count[BIT_COUNT];
97  unsigned int BOM_elems[BIT_COUNT]; 
98  timestamp_t BOM_total_time[BIT_COUNT];
99
100  int BOM, b;
101  int this_count;
102  int cum_count = 0;
103  unsigned int entry = 0;
104  unsigned int total_entries;
105  unsigned int this_elems = 0;
106  unsigned int cum_elems = 0;
107  timestamp_t this_time;
108  timestamp_t cum_time = 0ULL;
109  timestamp_t this_avg;
110  timestamp_t cum_avg;
111  timestamp_t accumulated_cycles; 
112
113  for (b = 0; b < BIT_COUNT; b++) {
114        BOM_count[b] = 0;
115        BOM_elems[b] = 0;
116        BOM_total_time[b] = 0;
117  }
118
119
120  total_entries = timer_table->full ? MAX_TIMER_ENTRIES : timer_table->current_entry;
121  for(entry = 0; entry < total_entries; entry++){
122        accumulated_cycles = timer_table->interval_end[entry] - timer_table->interval_start[entry];
123        if (accumulated_cycles > 0ULL) {
124//        cout << "accumulated_cycles =" << accumulated_cycles << "; elems = " << timer_table->interval_elems[entry] << endl;
125            BOM = binary_order_of_magnitude(accumulated_cycles*TIMER_SCALE_FACTOR/timer_table->interval_elems[entry]);
126            BOM_count[BOM]++;
127            BOM_elems[BOM] += timer_table->interval_elems[entry];
128            BOM_total_time[BOM] += accumulated_cycles;
129        }
130  }
131 
132  printf("Binary Order of Magnitude Profile\n");
133  for (b = 0; b < BIT_COUNT; b++) {
134    this_count = BOM_count[b];
135    cum_count += this_count;
136    this_time = BOM_total_time[b];
137    cum_time += this_time;
138    this_elems = BOM_elems[b];
139    cum_elems += this_elems;
140    if (this_count == 0) this_avg = 0ULL;
141    else this_avg = (TIMER_SCALE_FACTOR*this_time)/(this_elems);
142    if (cum_count == 0) cum_avg = 0ULL;
143    else cum_avg = (TIMER_SCALE_FACTOR*cum_time)/(cum_elems);
144    if (this_count > 0) {  // Only report intervals with nonzero counts.
145      printf("BOM %i: %i ", b, this_count);
146      printf("(avg time: %i %s/kElem) ", (int) this_avg, cycle_counter_units);
147      printf("Cumulative: %i ", cum_count);
148      printf("(avg: %i %s/kElem)\n", (int) cum_avg, cycle_counter_units);
149    }
150  }           
151}
152#endif
Note: See TracBrowser for help on using the repository browser.