OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
LField.h
Go to the documentation of this file.
1 //
2 // Class LField
3 // Local Field class
4 //
5 // Copyright (c) 2003 - 2020, Paul Scherrer Institut, Villigen PSI, Switzerland
6 // All rights reserved
7 //
8 // This file is part of OPAL.
9 //
10 // OPAL is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
17 //
18 #ifndef LFIELD_H
19 #define LFIELD_H
20 
21 // include files
23 
24 #include <iostream>
25 
26 // forward declarations
27 template <class T, unsigned Dim> class LField;
28 template <class T, unsigned Dim>
29 std::ostream& operator<<(std::ostream&, const LField<T,Dim>&);
30 
31 // Template metaprogram to calculate Dim**N. Used to
32 // reserve space in the overlap cache below.
33 
34 template <int Dim>
35 struct ToTheDim
36 {
37  inline static int calc(int n)
38  {
39  return ToTheDim<Dim-1>::calc(n) * n;
40  }
41 };
42 
43 template<>
44 struct ToTheDim<1>
45 {
46  inline static int calc(int n)
47  {
48  return n;
49  }
50 };
51 
52 
54 
55 // This stores the local data for a Field.
56 template<class T, unsigned Dim>
57 class LField
58 {
59 
60 public:
61  // An iterator for the contents of this LField.
63 
64  // The type of domain stored here
66 
67  //
68  // Constructors and destructor
69  //
70 
71  // Ctors for an LField. Arguments:
72  // owned = domain of "owned" region of LField (without guards)
73  // allocated = domain of "allocated" region, which includes guards
74  // vnode = global vnode ID number (see below)
75  LField(const NDIndex<Dim>& owned,
76  const NDIndex<Dim>& allocated,
77  int vnode = -1);
78 
79  //UL: for pinned memory allocation
80  LField(const NDIndex<Dim>& owned,
81  const NDIndex<Dim>& allocated,
82  int vnode,
83  bool p);
84 
85  // Copy constructor.
86  LField(const LField<T,Dim>&);
87 
88  // Destructor: just free the memory, if it's there.
89 
90  ~LField();
91 
92  //
93  // General information accessors
94  //
95 
96  // Return information about the LField.
97  int size(unsigned d) const { return Owned[d].length(); }
98  const NDIndex<Dim>& getAllocated() const { return Allocated; }
99  const NDIndex<Dim>& getOwned() const { return Owned; }
100  T* getP() { return P; }
101 
102  // Return global vnode ID number (between 0 and nvnodes - 1)
103  int getVnode() const { return vnode_m; }
104 
105  //
106  // iterator interface
107  //
108 
109  // Return begin/end iterators for the LField data
110  const iterator& begin() const { return Begin; }
111  const iterator& end() const { return End; }
112 
113  // get an iterator over a subrange.
114  iterator begin(const NDIndex<Dim>& domain);
115 
116  // Get an iterator over a subrange, when we might want to try to
117  // compress the data in the subrange without affecting the rest of
118  // the LField data.
119  // The LField iterator here must be told about a specific
120  // location into which to store a compressed value, since this
121  // iterator is used only to create a message. Since the intersect
122  // region may not be the whole LField, we cannot use the LField's
123  // storage, we need to provide our own (otherwise, when compressing
124  // the Field, we'll write the compressed value for ALL current
125  // iterators on the LField which use the LField's compression
126  // storage).
127  iterator begin(const NDIndex<Dim>& domain, T&);
128 
129  //
130  // Compression handling.
131  //
132 
133  // Let the user ask if we are already compressed.
134  inline bool IsCompressed() const
135  {
136  return P==0;
137  }
138 
139  // Let the user tell us to try to compress.
140  // Return quickly if we already are compressed.
141  // If the argument is true, then only examine the owned domain to determine
142  // if all the values are the same.
143  bool TryCompress(bool baseOnPhysicalCells = false);
144 
145  // Look through the data and figure out if it can be compressed.
146  inline bool CanCompress() const
147  {
148  if (!IsCompressed())
149  return CanCompress(*Begin);
150  return true;
151  }
152 
153  // Look through the data and figure out if it can be compressed
154  // to the given value. Return true if it can be compressed down to the
155  // given value. If this returns false, then the data is currently not
156  // compressed and contains different values.
157  bool CanCompress(T x) const;
158 
159  // Force a compress. Delete the memory and make Begin compressed.
160  // First is a version that uses the first value.
161  inline void Compress()
162  {
163  if (!IsCompressed())
164  Compress(*P);
165  }
166 
167  // Here is version that lets the user specify a new value.
168  void Compress(const T &val);
169 
170  // Let the user tell us to uncompress.
171  // Return quickly if we are already uncompressed.
172  inline void Uncompress(bool fill_domain = true)
173  {
174  if (IsCompressed())
175  ReallyUncompress(fill_domain);
176  }
177 
178  // Return a reference to the compressed data for debugging.
180  const T &getCompressedData() const { return CompressedData; }
181 
182  //
183  // Overlap cache interface
184  //
185 
187 
188  void AddToOverlapCache(LField<T, Dim> *newCacheItem)
189  {
190  if (overlap.size() == 0)
191  overlap.reserve(ToTheDim<Dim>::calc(3)-1);
192  overlap.push_back(newCacheItem);
193  overlapCacheInited = true;
194  }
195 
196  typedef typename std::vector< LField<T, Dim> *>::iterator OverlapIterator;
197 
198  OverlapIterator BeginOverlap() { return overlap.begin(); }
199  OverlapIterator EndOverlap() { return overlap.end(); }
200 
201  //
202  // Swap the pointers between two LFields.
203  //
204 
205  void swapData( LField<T,Dim>& a );
206 
207  //
208  // I/O
209  //
210 
211  // print an LField out
212  void write(std::ostream&) const;
213 
214 private:
215  // Global vnode ID number for the associated Vnode (useful with more recent
216  // FieldLayouts which store a logical "array" of vnodes; user specifies
217  // numbers of vnodes along each direction). Classes or user codes that use
218  // LField are responsible for setting and managing the values of this index;
219  // if unset, it has the value -1. Generally, this parameter value is set on
220  // construction of the vnode:
221 
222  int vnode_m;
223 
224  // The actual pointer to the LField data.
225 
226  T* P;
227 
228  // UL: for pinned memory allocation
229 
230  bool Pinned;
231 
232  // What domain in the data is owned by this LField.
233 
235 
236  // How total domain is actually allocated for thie LField (including guards)
237 
239 
240  // An iterator pointing to the first element in the owned domain.
241 
243 
244  // An iterator pointing one past the last element in the owned domain.
245 
247 
248  // If compressed, put the data here. If not compressed, this is not used.
249 
251 
252  // The overlap cache, an whether it has been initialized.
253 
254  std::vector< LField<T, Dim> * > overlap;
256 
257  // The index of the element to start comparing to the first element
258  // in a "CanCompress" check. This is generally set to the index of the
259  // first element that failed a compression check last time. There are
260  // two versions, one for when we're checking using the entire allocated
261  // domain, and another when we're checking using just the owned domain.
262 
263  mutable int allocCompressIndex;
264  mutable int ownedCompressIndex;
265 
266  // A counter for an offset that is used to keep data from always aligning
267  // at the same point in a memory page.
268 
270 
271  // Private methods used to implement compression
272 
273  bool CanCompressBasedOnPhysicalCells() const;
274  void ReallyUncompress(bool fill_domain);
276 
277  // Actualy allocate storage for the LField data, doing any special
278  // memory tricks needed for performance. Sets P pointer to new memory.
279  void allocateStorage(int newsize);
280 
281  // Actually free the storage used in the LField, if any. Resets P to zero.
282  void deallocateStorage();
283 
284 
285  // Disable default constructor and operator=
286 
289 };
290 
291 
292 template<class T, unsigned Dim>
293 inline
294 std::ostream& operator<<(std::ostream& out, const LField<T,Dim>& a)
295 {
296 
297 
298  a.write(out);
299  return out;
300 }
301 
303 
304 #include "Field/LField.hpp"
305 
306 #endif // LFIELD_H
std::ostream & operator<<(std::ostream &, const LField< T, Dim > &)
Definition: LField.h:294
std::complex< double > a
Definition: LField.h:58
void Compress()
Definition: LField.h:161
void deallocateStorage()
Definition: LField.hpp:723
void ReallyUncompress(bool fill_domain)
Definition: LField.hpp:558
int size(unsigned d) const
Definition: LField.h:97
bool overlapCacheInited
Definition: LField.h:255
NDIndex< Dim > Allocated
Definition: LField.h:238
T * getP()
Definition: LField.h:100
void swapData(LField< T, Dim > &a)
Definition: LField.hpp:637
void AddToOverlapCache(LField< T, Dim > *newCacheItem)
Definition: LField.h:188
iterator Begin
Definition: LField.h:242
bool Pinned
Definition: LField.h:230
CompressedBrickIterator< T, Dim > iterator
Definition: LField.h:62
const T & getCompressedData() const
Definition: LField.h:180
long offsetBlocks
Definition: LField.h:269
void allocateStorage(int newsize)
Definition: LField.hpp:694
bool IsCompressed() const
Definition: LField.h:134
const LField< T, Dim > & operator=(const LField< T, Dim > &)
const NDIndex< Dim > & getOwned() const
Definition: LField.h:99
int vnode_m
Definition: LField.h:222
bool CanCompress() const
Definition: LField.h:146
int getVnode() const
Definition: LField.h:103
T & getCompressedData()
Definition: LField.h:179
std::vector< LField< T, Dim > * >::iterator OverlapIterator
Definition: LField.h:196
int allocCompressIndex
Definition: LField.h:263
const iterator & end() const
Definition: LField.h:111
std::vector< LField< T, Dim > * > overlap
Definition: LField.h:254
bool CanCompressBasedOnPhysicalCells() const
Definition: LField.hpp:389
int ownedCompressIndex
Definition: LField.h:264
bool TryCompress(bool baseOnPhysicalCells=false)
Definition: LField.hpp:214
void write(std::ostream &) const
Definition: LField.hpp:746
void CompressBasedOnPhysicalCells()
Definition: LField.hpp:527
const NDIndex< Dim > & getAllocated() const
Definition: LField.h:98
~LField()
Definition: LField.hpp:199
const iterator & begin() const
Definition: LField.h:110
NDIndex< Dim > Domain_t
Definition: LField.h:65
void Uncompress(bool fill_domain=true)
Definition: LField.h:172
OverlapIterator BeginOverlap()
Definition: LField.h:198
NDIndex< Dim > Owned
Definition: LField.h:234
T CompressedData
Definition: LField.h:250
OverlapIterator EndOverlap()
Definition: LField.h:199
bool OverlapCacheInitialized()
Definition: LField.h:186
iterator End
Definition: LField.h:246
T * P
Definition: LField.h:226
static int calc(int n)
Definition: LField.h:37
static int calc(int n)
Definition: LField.h:46