PRAgMaTIc  master
DeferredOperations.h
Go to the documentation of this file.
1 /* Copyright (C) 2013 Imperial College London and others.
2  *
3  * Please see the AUTHORS file in the main source directory for a
4  * full list of copyright holders.
5  *
6  * Georgios Rokos
7  * Software Performance Optimisation Group
8  * Department of Computing
9  * Imperial College London
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  * notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above
17  * copyright notice, this list of conditions and the following
18  * disclaimer in the documentation and/or other materials provided
19  * with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
22  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
23  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
26  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
28  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
31  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
32  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #ifndef DEFERRED_OPERATIONS_H
37 #define DEFERRED_OPERATIONS_H
38 
39 #include <set>
40 #include <vector>
41 
42 #include "Mesh.h"
43 
44 template <typename real_t>
46 public:
47  DeferredOperations(Mesh<real_t>* mesh, const int num_threads, const int scaling_factor)
48  : nthreads(num_threads), defOp_scaling_factor(scaling_factor){
49  _mesh = mesh;
50  deferred_operations.resize(nthreads);
51  for(int i=0; i<nthreads; ++i)
52  deferred_operations[i].resize(nthreads*defOp_scaling_factor);
53  }
54 
56 
57  inline void addNN(const index_t i, const index_t n, const int tid){
58  deferred_operations[tid][hash(i) % (defOp_scaling_factor*nthreads)].addNN.push_back(i);
59  deferred_operations[tid][hash(i) % (defOp_scaling_factor*nthreads)].addNN.push_back(n);
60  }
61 
62  inline void remNN(const index_t i, const index_t n, const int tid){
63  deferred_operations[tid][hash(i) % (defOp_scaling_factor*nthreads)].remNN.push_back(i);
64  deferred_operations[tid][hash(i) % (defOp_scaling_factor*nthreads)].remNN.push_back(n);
65  }
66 
67  inline void addNE(const index_t i, const index_t n, const int tid){
68  deferred_operations[tid][hash(i) % (defOp_scaling_factor*nthreads)].addNE.push_back(i);
69  deferred_operations[tid][hash(i) % (defOp_scaling_factor*nthreads)].addNE.push_back(n);
70  }
71 
72  inline void addNE_fix(const index_t i, const index_t n, const int tid){
73  deferred_operations[tid][hash(i) % (defOp_scaling_factor*nthreads)].addNE_fix.push_back(i);
74  deferred_operations[tid][hash(i) % (defOp_scaling_factor*nthreads)].addNE_fix.push_back(n);
75  }
76 
77  inline void repEN(const size_t pos, const index_t n, const int tid){
78  deferred_operations[tid][(pos/16) % (defOp_scaling_factor*nthreads)].repEN.push_back(pos);
79  deferred_operations[tid][(pos/16) % (defOp_scaling_factor*nthreads)].repEN.push_back(n);
80  }
81 
82  inline void remNE(const index_t i, const index_t n, const int tid){
83  deferred_operations[tid][hash(i) % (defOp_scaling_factor*nthreads)].remNE.push_back(i);
84  deferred_operations[tid][hash(i) % (defOp_scaling_factor*nthreads)].remNE.push_back(n);
85  }
86 
87  inline void propagate_coarsening(const index_t i, const int tid){
88  deferred_operations[tid][hash(i) % (defOp_scaling_factor*nthreads)].coarsening_propagation.push_back(i);
89  }
90 
91  inline void propagate_refinement(const index_t i, const index_t n, const int tid){
92  deferred_operations[tid][hash(i) % (defOp_scaling_factor*nthreads)].refinement_propagation.push_back(i);
93  deferred_operations[tid][hash(i) % (defOp_scaling_factor*nthreads)].refinement_propagation.push_back(n);
94  }
95 
96  inline void propagate_swapping(const index_t i, const index_t n, const int tid){
97  deferred_operations[tid][hash(i) % (defOp_scaling_factor*nthreads)].swapping_propagation.push_back(i);
98  deferred_operations[tid][hash(i) % (defOp_scaling_factor*nthreads)].swapping_propagation.push_back(n);
99  }
100 
101  inline void reset_colour(const index_t i, const int tid){
102  deferred_operations[tid][hash(i) % (defOp_scaling_factor*nthreads)].reset_colour.push_back(i);
103  }
104 
105  inline void commit_addNN(const int tid, const int vtid){
106  for(typename std::vector<index_t>::const_iterator it=deferred_operations[tid][vtid].addNN.begin();
107  it!=deferred_operations[tid][vtid].addNN.end(); it+=2){
108  _mesh->NNList[*it].push_back(*(it+1));
109  }
110 
111  deferred_operations[tid][vtid].addNN.clear();
112  }
113 
114  inline void commit_remNN(const int tid, const int vtid){
115  for(typename std::vector<index_t>::const_iterator it=deferred_operations[tid][vtid].remNN.begin();
116  it!=deferred_operations[tid][vtid].remNN.end(); it+=2){
117  typename std::vector<index_t>::iterator position = std::find(_mesh->NNList[*it].begin(), _mesh->NNList[*it].end(), *(it+1));
118  assert(position != _mesh->NNList[*it].end());
119  _mesh->NNList[*it].erase(position);
120  }
121 
122  deferred_operations[tid][vtid].remNN.clear();
123  }
124 
125  inline void commit_addNE(const int tid, const int vtid){
126  for(typename std::vector<index_t>::const_iterator it=deferred_operations[tid][vtid].addNE.begin();
127  it!=deferred_operations[tid][vtid].addNE.end(); it+=2){
128  _mesh->NEList[*it].insert(*(it+1));
129  }
130 
131  deferred_operations[tid][vtid].addNE.clear();
132  }
133 
134  inline void commit_addNE_fix(std::vector<size_t>& threadIdx, const int tid, const int vtid){
135  for(typename std::vector<index_t>::const_iterator it=deferred_operations[tid][vtid].addNE_fix.begin();
136  it!=deferred_operations[tid][vtid].addNE_fix.end(); it+=2){
137  // Element was created by thread tid
138  index_t fixedId = *(it+1) + threadIdx[tid];
139  _mesh->NEList[*it].insert(fixedId);
140  }
141 
142  deferred_operations[tid][vtid].addNE_fix.clear();
143  }
144 
145  inline void commit_remNE(const int tid, const int vtid){
146  for(typename std::vector<index_t>::const_iterator it=deferred_operations[tid][vtid].remNE.begin();
147  it!=deferred_operations[tid][vtid].remNE.end(); it+=2){
148  assert(_mesh->NEList[*it].count(*(it+1)) != 0);
149  _mesh->NEList[*it].erase(*(it+1));
150  }
151 
152  deferred_operations[tid][vtid].remNE.clear();
153  }
154 
155  inline void commit_repEN(const int tid, const int vtid){
156  for(typename std::vector<index_t>::const_iterator it=deferred_operations[tid][vtid].repEN.begin();
157  it!=deferred_operations[tid][vtid].repEN.end(); it+=2){
158  _mesh->_ENList[*it] = *(it+1);
159  }
160 
161  deferred_operations[tid][vtid].repEN.clear();
162  }
163 
164  inline void commit_coarsening_propagation(index_t* dynamic_vertex, const int tid, const int vtid){
165  for(typename std::vector<index_t>::const_iterator it=deferred_operations[tid][vtid].coarsening_propagation.begin();
166  it!=deferred_operations[tid][vtid].coarsening_propagation.end(); ++it){
167  dynamic_vertex[*it] = -2;
168  }
169 
170  deferred_operations[tid][vtid].coarsening_propagation.clear();
171  }
172 
173  inline void commit_refinement_propagation(std::vector< std::set<index_t> >& marked_edges, const int tid, const int vtid){
174  for(typename std::vector<index_t>::const_iterator it=deferred_operations[tid][vtid].refinement_propagation.begin();
175  it!=deferred_operations[tid][vtid].refinement_propagation.end(); it+=2){
176  marked_edges[*it].insert(*(it+1));
177  }
178 
179  deferred_operations[tid][vtid].refinement_propagation.clear();
180  }
181 
182  inline void commit_swapping_propagation(std::vector< std::set<index_t> >& marked_edges, const int tid, const int vtid){
183  for(typename std::vector<index_t>::const_iterator it=deferred_operations[tid][vtid].swapping_propagation.begin();
184  it!=deferred_operations[tid][vtid].swapping_propagation.end(); it+=2){
185  marked_edges[*it].insert(*(it+1));
186  }
187 
188  deferred_operations[tid][vtid].swapping_propagation.clear();
189  }
190 
191  inline void commit_colour_reset(int* node_colour, const int tid, const int vtid){
192  for(typename std::vector<index_t>::const_iterator it=deferred_operations[tid][vtid].reset_colour.begin();
193  it!=deferred_operations[tid][vtid].reset_colour.end(); ++it){
194  node_colour[*it] = 0;
195  }
196 
197  deferred_operations[tid][vtid].reset_colour.clear();
198  }
199 
200 private:
201  /*
202  * Park & Miller (aka Lehmer) pseudo-random number generation. Possible bug if
203  * index_t is a datatype longer than 32 bits. However, in the context of a single
204  * MPI node, it is highly unlikely that index_t will ever need to be longer.
205  * A 64-bit datatype makes sense only for global node numbers, not local.
206  */
207  inline uint32_t hash(const uint32_t id) const{
208  return ((uint64_t)id * 279470273UL) % 4294967291UL;
209  }
210 
211  struct def_op_t{
212  // Mesh
213  std::vector<index_t> addNN; // addNN -> [i, n] : Add node n to NNList[i].
214  std::vector<index_t> remNN; // remNN -> [i, n] : Remove node n from NNList[i].
215  std::vector<index_t> addNE; // addNE -> [i, n] : Add element n to NEList[i].
216  std::vector<index_t> remNE; // remNE -> [i, n] : Remove element n from NEList[i].
217  std::vector<index_t> addNE_fix; // addNE_fix -> [i, n] : Fix ID of element n according to
218  // threadIdx[thread_which_created_n] and add it to NEList[i].
219  std::vector<index_t> repEN; // remEN -> [pos, n] : Set _ENList[pos] = n.
220  std::vector<index_t> coarsening_propagation; // [i] : Mark Coarseninig::dynamic_vertex[i]=-2.
221  std::vector<index_t> refinement_propagation; // [i, n]: Mark Edge(i,n) for refinement.
222  std::vector<index_t> swapping_propagation; // [i, n] : Mark Swapping::marked_edges[i].insert(n).
223  std::vector<index_t> reset_colour; // [i] : Set Colouring::node_colour[i]=-1.
224  };
225 
226  //Deferred operations main structure
227  std::vector< std::vector<def_op_t> > deferred_operations;
228  const int nthreads;
229  const int defOp_scaling_factor;
230 
231  Mesh<real_t>* _mesh;
232 };
233 
234 #endif
void remNE(const index_t i, const index_t n, const int tid)
void reset_colour(const index_t i, const int tid)
void commit_addNE_fix(std::vector< size_t > &threadIdx, const int tid, const int vtid)
void addNE(const index_t i, const index_t n, const int tid)
int index_t
void commit_remNE(const int tid, const int vtid)
void commit_colour_reset(int *node_colour, const int tid, const int vtid)
void commit_swapping_propagation(std::vector< std::set< index_t > > &marked_edges, const int tid, const int vtid)
void commit_addNE(const int tid, const int vtid)
Manages mesh data.
Definition: Mesh.h:70
void propagate_swapping(const index_t i, const index_t n, const int tid)
void commit_coarsening_propagation(index_t *dynamic_vertex, const int tid, const int vtid)
void remNN(const index_t i, const index_t n, const int tid)
void commit_remNN(const int tid, const int vtid)
void propagate_coarsening(const index_t i, const int tid)
void commit_refinement_propagation(std::vector< std::set< index_t > > &marked_edges, const int tid, const int vtid)
void propagate_refinement(const index_t i, const index_t n, const int tid)
void commit_repEN(const int tid, const int vtid)
void commit_addNN(const int tid, const int vtid)
void addNE_fix(const index_t i, const index_t n, const int tid)
DeferredOperations(Mesh< real_t > *mesh, const int num_threads, const int scaling_factor)
void addNN(const index_t i, const index_t n, const int tid)
void repEN(const size_t pos, const index_t n, const int tid)