SCIRun  5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Reducer.h
Go to the documentation of this file.
1 /*
2  For more information, please see: http://software.sci.utah.edu
3 
4  The MIT License
5 
6  Copyright (c) 2009 Scientific Computing and Imaging Institute,
7  University of Utah.
8 
9 
10  Permission is hereby granted, free of charge, to any person obtaining a
11  copy of this software and associated documentation files (the "Software"),
12  to deal in the Software without restriction, including without limitation
13  the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  and/or sell copies of the Software, and to permit persons to whom the
15  Software is furnished to do so, subject to the following conditions:
16 
17  The above copyright notice and this permission notice shall be included
18  in all copies or substantial portions of the Software.
19 
20  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  DEALINGS IN THE SOFTWARE.
27 */
28 
29 
30 
31 ///
32 ///@file Reducer.h
33 ///@brief A barrier with reduction operations
34 ///
35 ///@author Steve Parker
36 /// Department of Computer Science
37 /// University of Utah
38 ///@date June 1997
39 ///
40 
41 #ifndef Core_Thread_Reducer_h
42 #define Core_Thread_Reducer_h
43 
45 
46 namespace SCIRun {
47 
48 /**************************************
49 
50 @class
51  Reducer
52 
53 KEYWORDS
54  Thread
55 
56 @details
57  Perform reduction operations over a set of threads. Reduction
58  operations include things like global sums, global min/max, etc.
59  In these operations, a local sum (operation) is performed on each
60  thread, and these sums are added together.
61 
62 ****************************************/
63  template<class T> class Reducer : public Barrier {
64  public:
65  //////////
66  /// The function that performs the reduction
67  typedef T (*ReductionOp)(const T&, const T&);
68 
69  //////////
70  /// Create a <b> Reducer</i>.
71  /// At each operation, a barrier wait is performed, and the
72  /// operation will be performed to compute the global balue.
73  /// <i>name</i> should be a static string which describes
74  /// the primitive for debugging purposes.
75  /// op is a function which will compute a reduced value from
76  /// a pair of values. op should be associative and commutative,
77  /// even up to floating point errors.
78  Reducer(const char* name, ReductionOp);
79 
80  //////////
81  /// Destroy the Reducer and free associated memory.
82  virtual ~Reducer();
83 
84  //////////
85  /// Performs a global reduction over all of the threads. As
86  /// soon as each thread has called reduce with their local value,
87  /// each thread will return the same global reduced value.
88  T reduce(int myrank, int numThreads, const T& value);
89 
90  private:
91  T (*f_op)(const T&, const T&);
92  struct DataArray {
93  // We want this on it's own cache line
94  T data_;
95  // Assumes 128 bytes in a cache line...
96  char filler_[128];
97  };
98  DataArray* join_[2];
99 
100  struct BufArray {
101  int which;
102  char filler_[128-sizeof(int)];
103  };
104  BufArray* p_;
105 
106  int array_size_;
107  void collectiveResize(int proc, int numThreads);
108  void allocate(int size);
109 
110  // Cannot copy them
111  Reducer(const Reducer<T>&);
112  Reducer<T>& operator=(const Reducer<T>&);
113  };
114  }
115 }
116 
117 template<class T>
118 Reducer<T>::Reducer(const char* name, ReductionOp op)
119  : Barrier(name), f_op(op)
120 {
121  array_size_=-1;
122  p_=0;
123 }
124 
125 template<class T>
126 void
127 Reducer<T>::allocate(int n)
128 {
129  join_[0]=new DataArray[2*numThreads+2]-1;
130  join_[1]=join_[0]+numThreads;
131  p_=new BufArray[num_threads_+2]+1;
132  for(int i=0;i<num_threads_;i++)
133  p_[i].whichBuffer_=0;
134  array_size_=n;
135 }
136 
137 template<class T>
139 {
140  if(p_){
141  delete[] (void*)(join_[0]-1);
142  delete[] (void*)(p_-1);
143  }
144 }
145 
146 template<class T>
147 void
148 Reducer<T>::collectiveResize(int proc, int n)
149 {
150  // Extra barrier here to change the array size...
151 
152  // We must wait until everybody has seen the array size change,
153  // or they will skip down too soon...
154  wait(n);
155  if(proc==0){
156  delete[] (void*)(join_[0]-1);
157  delete[] (void*)(p_-1);
158  allocate(n);
159  array_size_=n;
160  }
161  wait(n);
162 }
163 
164 template<class T>
165 T
166 Reducer<T>::reduce(int proc, int n, const T& myresult)
167 {
168  if(n != array_size_){
169  collectiveResize(proc, n);
170 } // End namespace SCIRun
171  if(n<=1)
172  return myresult;
173 
174  int buf=p_[proc].whichBuffer_;
175  p_[proc].whichBuffer_=1-buf;
176 
177  dataArray* j=join_[buf];
178  j[proc].data_=myresult;
179  wait(n);
180  T red=j[0].data_;
181  for(int i=1;i<n;i++)
182  red=(*f_op)(red, j[i].data_);
183  return red;
184 
185 #endif
186 
187 
Definition: Barrier.h:71
Definition: Reducer.h:63
const char * name[]
Definition: BoostGraphExampleTests.cc:87
T(* ReductionOp)(const T &, const T &)
The function that performs the reduction.
Definition: Reducer.h:67
virtual ~Reducer()
Destroy the Reducer and free associated memory.
Definition: Reducer.h:138
T reduce(int myrank, int numThreads, const T &value)
Definition: Reducer.h:166
int n
Definition: eab.py:9
Reducer(const char *name, ReductionOp)
int size
Definition: eabLatVolData.py:2