File: Timer.h

package info (click to toggle)
r-cran-rcppparallel 5.1.7%2Bdfsg-6
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 544 kB
  • sloc: cpp: 1,852; sh: 19; makefile: 11
file content (208 lines) | stat: -rw-r--r-- 6,038 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#ifndef __RCPP_PARALLEL_TIMER__
#define __RCPP_PARALLEL_TIMER__

namespace RcppParallel {
    typedef uint64_t nanotime_t;

    template <typename Timer>
    class ProportionTimer {
    public:
        ProportionTimer() : 
            timer(), n(0), id(0)
        {}
        
        ProportionTimer( nanotime_t origin, int id_ ) : 
            timer(origin), n(0), id(id_)
        {}
        
        inline operator SEXP() const {
            Rcpp::NumericVector out = (SEXP)timer ;
            out.attr("n") = n ;
            return out ;
        }
        
        inline nanotime_t origin() const{
            return timer.origin() ;
        }
        
        inline int get_n() const {
            return n ;    
        }
        
        inline void step( const std::string& name) {
            timer.step(name) ;    
        }
        
        Timer timer ;
        int n ;
        int id ;
        
    } ;
    
    template <typename Timer>
    class SingleTimer {
    public:
        SingleTimer() : timer(){}
        
        inline operator SEXP(){
            Rcpp::List out = Rcpp::List::create(timer) ;
            out.attr("class") = Rcpp::CharacterVector::create( "SingleTimer", "Timer" );
            return out ;
        }
        
        inline void step( const char* name ){
            timer.step(name) ;    
        }
        
    private:
        Timer timer ;
    } ;
    
    template <typename Timer>
    class FixedSizeTimers {
    public:
        FixedSizeTimers( int n, int ndata_ ) : 
            timers(n), ndata(ndata_)
        {}
        
        inline ProportionTimer<Timer>& get(int i) {
            return timers[i] ;
        }
        
        inline ProportionTimer<Timer>& operator[](int i){ 
            return timers[i]; 
        }
        
        inline operator SEXP(){
            Rcpp::List out = wrap(timers) ;
            out.attr("class") = Rcpp::CharacterVector::create("FixedSizeTimers", "Timer") ;
            out.attr("n") = ndata ;
            return out ;
        }
        
    private:
        std::vector< ProportionTimer<Timer> > timers ;
        int ndata ;
    } ;
    
    template <typename Timer, typename Mutex, typename Locker>
    class TimersList {
    public:
        
        TimersList(int n_): 
            timers(), origin(Rcpp::get_nanotime()), n(n_)
        {
            timers.push_back( ProportionTimer<Timer>( origin, 0 ) ) ;
            childs.push_back( std::vector<int>() );
        }
        
        ProportionTimer<Timer>& front(){
            return timers.front() ;
        }
        
        ProportionTimer<Timer>& get_new_timer(int parent_id){
            Locker lock(mutex) ;
            int id = timers.size() ;
            timers.push_back( ProportionTimer<Timer>( origin, id ) ) ;
            childs.push_back( std::vector<int>() );
            std::list< std::vector<int> >::iterator it = childs.begin() ;
            for(int i=0; i<parent_id; i++) ++it ;
            it->push_back(id) ;
            return timers.back() ;
        }
        
        inline operator SEXP(){
            int nt = timers.size() ;
            Rcpp::List data(nt) ;
            typename std::list<ProportionTimer<Timer> >::const_iterator timers_it = timers.begin() ;
            std::list<std::vector<int> >::const_iterator childs_it = childs.begin() ;
            for( int i=0; i<nt; i++, ++timers_it, ++childs_it ){
                Rcpp::NumericVector x = (SEXP)*timers_it ;
                Rcpp::IntegerVector kids = Rcpp::wrap(*childs_it) ;
                x.attr("childs") = kids + 1 ;
                data[i] = x ;
            }
            data.attr("class") = Rcpp::CharacterVector::create( "TimersList" , "Timer" ) ;
            data.attr("n") = n ;
            return data ;
        }
        
        std::list< ProportionTimer<Timer> > timers ;
        std::list< std::vector<int> > childs ;
        Mutex mutex ;
        nanotime_t origin ;
        int n ;
        
    private:
        TimersList( const TimersList& ) ;
    
    } ;
    
    template <typename Reducer, typename Timer, typename Mutex, typename Locker, typename OUT = Rcpp::List>
    class TimedReducer : public Worker {
    public:
        typedef TimersList<Timer,Mutex,Locker> Timers ; 
        
        Reducer* reducer ;
        Timers& timers ;
        ProportionTimer<Timer>& timer ;
        bool owner ;
        
        TimedReducer( Reducer& reducer_, Timers& timers_) : 
            reducer(&reducer_), 
            timers(timers_), 
            timer(timers.get_new_timer(0)), 
            owner(false)
        {
            timer.step("init");
        }
        
        TimedReducer( const TimedReducer& other, Split s) : 
            reducer( new Reducer(*other.reducer, s) ), 
            timers( other.timers ), 
            timer( timers.get_new_timer(other.timer.id) ),
            owner(true)
        {
            timer.step("init") ;
        }
        
        ~TimedReducer(){
            if(owner && reducer) {
                delete reducer ;
            }
            reducer = 0 ;
        }
        
        inline void operator()( size_t begin, size_t end){
            timer.n += (end-begin) ;
            timer.step("start") ;
            reducer->operator()(begin, end) ;
            timer.step("work") ;
        }
        
        inline void join(const TimedReducer& rhs){
            rhs.timer.step("start") ;
            reducer->join(*rhs.reducer) ;
            rhs.timer.step("join") ;
        }
        
        inline Rcpp::List get() const {
            timers.front().step("start") ;
            OUT out = reducer->get() ;
            timers.front().step("structure") ;
            
            Rcpp::List res = Rcpp::List::create( (SEXP)timers, out );
            return res ;
        }
        
    private:
        // just to be on the safe side, making sure these are not called
        TimedReducer() ;
        TimedReducer( const TimedReducer& ) ;
    } ;
    
    
} // namespace RcppParallel


#endif // __RCPP_PARALLEL_COMMON__