OPAL (Object Oriented Parallel Accelerator Library)  2024.1
OPAL
BrickIterator.hpp
Go to the documentation of this file.
1 // -*- C++ -*-
2 /***************************************************************************
3  *
4  * The IPPL Framework
5  *
6  * This program was prepared by PSI.
7  * All rights in the program are reserved by PSI.
8  * Neither PSI nor the author(s)
9  * makes any warranty, express or implied, or assumes any liability or
10  * responsibility for the use of this software
11  *
12  * Visit www.amas.web.psi for more details
13  *
14  ***************************************************************************/
15 
16 // -*- C++ -*-
17 /***************************************************************************
18  *
19  * The IPPL Framework
20  *
21  *
22  * Visit http://people.web.psi.ch/adelmann/ for more details
23  *
24  ***************************************************************************/
25 
26 // include files
27 #include "Field/AssignDefs.h"
28 #include "Index/NDIndex.h"
29 #include "Utility/PAssert.h"
30 
31 
33 // BrickCounter methods
34 
35 template<unsigned Dim>
37 {
38  for (unsigned d=0; d<Dim; ++d)
39  {
41  BrickCounter<Dim>::Counts[d] = counted[d].length();
42  }
43 }
44 
46 
47 template<unsigned Dim>
48 void
50 {
51  // Remove this profiling because this is too lightweight.
52  //
53  //
54  for (unsigned d=0; d<Dim; ++d) {
55  step(d);
57  return;
58  rewind(d);
59  }
60  // If we get to here we have looped over the whole thing.
61 }
62 
63 
65 // BrickIterator methods
66 
67 template<class T, unsigned Dim>
69  const NDIndex<Dim>& counted,
70  const NDIndex<Dim>& domalloc)
71 : BrickCounter<Dim>(counted), Current(p), Whole(true)
72 {
73  // Remove this profiling because this is too lightweight.
74  //
75  //
76 
77  // Calculate the strides,carriage returns and offset for the pointer.
78  int n=1;
79  for (unsigned d=0; d<Dim; ++d) {
80  Strides[d] = n*counted[d].stride();
81  Current += n*(counted[d].first() - domalloc[d].first());
82  n *= domalloc[d].length();
83  Whole = (Whole && counted[d] == domalloc[d]);
84  }
85 }
86 
88 
89 template< class T, unsigned Dim >
91 {
92  // Remove this profiling because this is too lightweight.
93  //
94  //
95 
96  int n = 1;
97  for (unsigned d=0; d<Dim; ++d) {
98  BrickCounter<Dim>::Counts[d] = sizes[d];
100  Strides[d] = n;
101  n *= sizes[d];
102  }
103  Current = p;
104  Whole = true;
105 }
106 
108 
109 template<class T, unsigned Dim>
110 void
112 {
113  // Remove this profiling because this is too lightweight.
114  //
115  //
116 
117  for (unsigned d=0; d<Dim; ++d) {
118  step(d);
120  return;
121  rewind(d);
122  }
123  // If we get to here we have looped over the whole thing.
124  Current = 0;
125 }
126 
127 
129 // put data into a message to send to another node
130 // ... for putMessage, the second argument
131 // is used for an optimization for when the entire brick is being
132 // sent. If that is so, do not copy data into a new buffer, just
133 // put the pointer into the message. USE WITH CARE. The default is
134 // tohave putMessage make a copy of the data in the brick before adding
135 // it to the message. In many situations, this is required since the
136 // data referred to by the iterator is not contiguous. getMessage
137 // has no such option, it always does the most efficient thing it can.
138 template<class T, unsigned Dim>
140 
141 
142 
143  int n, s[Dim];
144  unsigned int i;
145 
146  // put in the size of the data, and calculate total number of elements
147  for (n=1, i=0; i < Dim; ++i) {
148  s[i] = BrickCounter<Dim>::Counts[i];
150  }
151  m.put(s, s + Dim);
152 
153  // Only add in the actual data if there is something to add.
154  if (n > 0) {
155  // If we are not required to make a copy, check if we can just add in
156  // the pointer. We can do this ONLY if we are adding in the entire
157  // domain, and not a subset, of the original domain.
158  if (!makecopy && whole()) {
159  // We are iterating over the whole brick (not just a subset), and
160  // we are not required to make a copy, so, well, don't. Just put
161  // in the pointer to the brick and ask the message NOT to delete
162  // the data when the message is sent.
163  m.setCopy(false);
164  m.setDelete(false);
165  m.putmsg((void *)Current, sizeof(T), n);
166  } else {
167  // FIX THIS!! Better to give a BrickIterator begin/end pair to
168  // putMessage than to do this.
169  T* cpydata = (T*) malloc(sizeof(T)*n);
170  T* cpy = cpydata;
171  T* cpyend = cpydata + n;
172  BrickIterator<T, Dim> bi = *this;
173  for (; cpy != cpyend; ++cpy, ++bi)
174  new (cpy) T(*bi);
175 
176  // put data into this message
177  m.setCopy(false);
178  m.setDelete(true);
179  m.putmsg((void *)cpydata, sizeof(T), n);
180  }
181  }
182 
183  return m;
184 }
185 
186 
188 // get data out from a message
189 template<class T, unsigned Dim>
191 
192 
193  int n, s[Dim];
194  unsigned int i;
195  // this will only work if this iterator does not yet point
196  // at any data
197  PInsist(Current == 0,
198  "Iterator already has data in BrickIterator::getMessage!!");
199 
200  // retrieve size of data in message, and set counters, strides, etc.
201  m.get((int*) s);
202  for (n=1, i=0; i < Dim; ++i) {
203  BrickCounter<Dim>::Counts[i] = s[i];
205  Strides[i] = n;
206  n *= s[i];
207  }
208 
209  // retrieve actual data into an allocated buffer
210  // NOTE: This just stores a pointer to the data that is actually stored
211  // in the Message item. It does not make its own copy. So, if you use
212  // a BrickIterator to get data from a message, you must use the data in the
213  // BrickIterator BEFORE you delete the Message. Otherwise, you'll be
214  // pointing at deallocated memory.
215  /*
216  Current = new T[n];
217  ::getMessage_iter(m, Current);
218  */
219  Current = static_cast<T *>(m.item(0).data());
220  m.get();
221  return m;
222 }
223 
224 
225 
226 /***************************************************************************
227  * $RCSfile: BrickIterator.cpp,v $ $Author: adelmann $
228  * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:26 $
229  * IPPL_VERSION_ID: $Id: BrickIterator.cpp,v 1.1.1.1 2003/01/23 07:40:26 adelmann Exp $
230  ***************************************************************************/
Message & put(const T &val)
Definition: Message.h:406
and give any other recipients of the Program a copy of this License along with the Program You may charge a fee for the physical act of transferring a and you may at your option offer warranty protection in exchange for a fee You may modify your copy or copies of the Program or any portion of thus forming a work based on the and copy and distribute such modifications or work under the terms of Section provided that you also meet all of these that in whole or in part contains or is derived from the Program or any part to be licensed as a whole at no charge to all third parties under the terms of this License c If the modified program normally reads commands interactively when you must cause when started running for such interactive use in the most ordinary to print or display an announcement including an appropriate copyright notice and a notice that there is no and telling the user how to view a copy of this and can be reasonably considered independent and separate works in then this and its do not apply to those sections when you distribute them as separate works But when you distribute the same sections as part of a whole which is a work based on the the distribution of the whole must be on the terms of this whose permissions for other licensees extend to the entire whole
Definition: LICENSE:117
Message & getMessage(Message &)
Message & setDelete(const bool c)
Definition: Message.h:331
MsgItem & item(size_t n)
Definition: Message.h:308
Message & get(const T &cval)
Definition: Message.h:476
Message & putmsg(void *, int, int=0)
Message & setCopy(const bool c)
Definition: Message.h:319
Message & putMessage(Message &, bool makecopy=true)
const unsigned Dim
#define PInsist(c, m)
Definition: PAssert.h:120
T *__restrict__ Current
void * data()
Definition: Message.h:244
vec< int, Dim > Strides