OPAL (Object Oriented Parallel Accelerator Library) 2022.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
35template<unsigned Dim>
37{
38 for (unsigned d=0; d<Dim; ++d)
39 {
41 BrickCounter<Dim>::Counts[d] = counted[d].length();
42 }
43}
44
46
47template<unsigned Dim>
48void
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
67template<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
89template< 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
109template<class T, unsigned Dim>
110void
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.
138template<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) {
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
189template<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) {
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 ***************************************************************************/
const unsigned Dim
#define PInsist(c, m)
Definition: PAssert.h:120
T *__restrict__ Current
Message & getMessage(Message &)
vec< int, Dim > Strides
Message & putMessage(Message &, bool makecopy=true)
Message & putmsg(void *, int, int=0)
Message & setCopy(const bool c)
Definition: Message.h:319
Message & put(const T &val)
Definition: Message.h:406
MsgItem & item(size_t n)
Definition: Message.h:308
Message & setDelete(const bool c)
Definition: Message.h:331
Message & get(const T &cval)
Definition: Message.h:476
void * data()
Definition: Message.h:244