00001 // -*- C++ -*- 00002 /*************************************************************************** 00003 * 00004 * The IPPL Framework 00005 * 00006 * This program was prepared by PSI. 00007 * All rights in the program are reserved by PSI. 00008 * Neither PSI nor the author(s) 00009 * makes any warranty, express or implied, or assumes any liability or 00010 * responsibility for the use of this software 00011 * 00012 * Visit http://www.acl.lanl.gov/POOMS for more details 00013 * 00014 ***************************************************************************/ 00015 00016 // -*- C++ -*- 00017 /*************************************************************************** 00018 * 00019 * The IPPL Framework 00020 * 00021 * 00022 * Visit http://people.web.psi.ch/adelmann/ for more details 00023 * 00024 ***************************************************************************/ 00025 00026 // include files 00027 #include "Field/AssignDefs.h" 00028 #include "Index/NDIndex.h" 00029 #include "Utility/PAssert.h" 00030 #include "Profile/Profiler.h" 00031 00033 // BrickCounter methods 00034 00035 template<unsigned Dim> 00036 BrickCounter<Dim>::BrickCounter(const NDIndex<Dim>& counted) 00037 { 00038 // Remove this profiling because this is too lightweight. 00039 // TAU_TYPE_STRING(taustr, "void (" + CT(counted) + " )" ); 00040 // TAU_PROFILE("BrickCounter::BrickCounter()", taustr, TAU_FIELD); 00041 for (unsigned d=0; d<Dim; ++d) 00042 { 00043 BrickCounter<Dim>::Counters[d] = 0; 00044 BrickCounter<Dim>::Counts[d] = counted[d].length(); 00045 } 00046 } 00047 00049 00050 template<unsigned Dim> 00051 void 00052 BrickCounter<Dim>::op_pp() 00053 { 00054 // Remove this profiling because this is too lightweight. 00055 // TAU_TYPE_STRING(taustr, CT(*this) + " void ()" ); 00056 // TAU_PROFILE("BrickCounter::op_pp()", taustr, TAU_FIELD); 00057 for (unsigned d=0; d<Dim; ++d) { 00058 step(d); 00059 if ( BrickCounter<Dim>::Counters[d] != BrickCounter<Dim>::Counts[d] ) 00060 return; 00061 rewind(d); 00062 } 00063 // If we get to here we have looped over the whole thing. 00064 } 00065 00066 00068 // BrickIterator methods 00069 00070 template<class T, unsigned Dim> 00071 BrickIterator<T,Dim>::BrickIterator(T* p, 00072 const NDIndex<Dim>& counted, 00073 const NDIndex<Dim>& domalloc) 00074 : BrickCounter<Dim>(counted), Current(p), Whole(true) 00075 { 00076 // Remove this profiling because this is too lightweight. 00077 // TAU_TYPE_STRING(taustr, "void (" + CT(p) + ", " + CT(counted) + ", " + CT(alloc) + " )" ); 00078 // TAU_PROFILE("BrickIterator::BrickIterator()", taustr, TAU_FIELD); 00079 00080 // Calculate the strides,carriage returns and offset for the pointer. 00081 int n=1; 00082 for (unsigned d=0; d<Dim; ++d) { 00083 Strides[d] = n*counted[d].stride(); 00084 Current += n*(counted[d].first() - domalloc[d].first()); 00085 n *= domalloc[d].length(); 00086 Whole = (Whole && counted[d] == domalloc[d]); 00087 } 00088 } 00089 00091 00092 template< class T, unsigned Dim > 00093 BrickIterator<T,Dim>::BrickIterator(T* p, const vec<int,Dim>& sizes) 00094 { 00095 // Remove this profiling because this is too lightweight. 00096 //TAU_TYPE_STRING(taustr, "void (" + CT(p) + ", " + CT(sizes) + " )" ); 00097 //TAU_PROFILE("BrickIterator::BrickIterator()", taustr, TAU_FIELD); 00098 00099 int n = 1; 00100 for (unsigned d=0; d<Dim; ++d) { 00101 BrickCounter<Dim>::Counts[d] = sizes[d]; 00102 BrickCounter<Dim>::Counters[d] = 0; 00103 Strides[d] = n; 00104 n *= sizes[d]; 00105 } 00106 Current = p; 00107 Whole = true; 00108 } 00109 00111 00112 template<class T, unsigned Dim> 00113 void 00114 BrickIterator<T,Dim>::op_pp() 00115 { 00116 // Remove this profiling because this is too lightweight. 00117 // TAU_TYPE_STRING(taustr, CT(*this) + " void ()" ); 00118 // TAU_PROFILE("BrickIterator::op_pp()", taustr, TAU_FIELD); 00119 00120 for (unsigned d=0; d<Dim; ++d) { 00121 step(d); 00122 if ( BrickCounter<Dim>::Counters[d] != BrickCounter<Dim>::Counts[d] ) 00123 return; 00124 rewind(d); 00125 } 00126 // If we get to here we have looped over the whole thing. 00127 Current = 0; 00128 } 00129 00130 00132 // put data into a message to send to another node 00133 // ... for putMessage, the second argument 00134 // is used for an optimization for when the entire brick is being 00135 // sent. If that is so, do not copy data into a new buffer, just 00136 // put the pointer into the message. USE WITH CARE. The default is 00137 // tohave putMessage make a copy of the data in the brick before adding 00138 // it to the message. In many situations, this is required since the 00139 // data referred to by the iterator is not contiguous. getMessage 00140 // has no such option, it always does the most efficient thing it can. 00141 template<class T, unsigned Dim> 00142 Message& BrickIterator<T,Dim>::putMessage(Message& m, bool makecopy) { 00143 TAU_TYPE_STRING(taustr, "Message& (" + CT(m) + ", bool)" ); 00144 TAU_PROFILE("BrickIterator::putMessage", taustr, TAU_FIELD|TAU_MESSAGE); 00145 00146 int i, n, s[Dim]; 00147 00148 // put in the size of the data, and calculate total number of elements 00149 for (n=1, i=0; i < Dim; ++i) { 00150 s[i] = BrickCounter<Dim>::Counts[i]; 00151 n *= BrickCounter<Dim>::Counts[i]; 00152 } 00153 m.put(s, s + Dim); 00154 00155 // Only add in the actual data if there is something to add. 00156 if (n > 0) { 00157 // If we are not required to make a copy, check if we can just add in 00158 // the pointer. We can do this ONLY if we are adding in the entire 00159 // domain, and not a subset, of the original domain. 00160 if (!makecopy && whole()) { 00161 // We are iterating over the whole brick (not just a subset), and 00162 // we are not required to make a copy, so, well, don't. Just put 00163 // in the pointer to the brick and ask the message NOT to delete 00164 // the data when the message is sent. 00165 m.setCopy(false); 00166 m.setDelete(false); 00167 m.putmsg((void *)Current, sizeof(T), n); 00168 } else { 00169 // FIX THIS!! Better to give a BrickIterator begin/end pair to 00170 // putMessage than to do this. 00171 T* cpydata = (T*) malloc(sizeof(T)*n); 00172 T* cpy = cpydata; 00173 T* cpyend = cpydata + n; 00174 BrickIterator<T, Dim> bi = *this; 00175 for (; cpy != cpyend; ++cpy, ++bi) 00176 new (cpy) T(*bi); 00177 00178 // put data into this message 00179 m.setCopy(false); 00180 m.setDelete(true); 00181 m.putmsg((void *)cpydata, sizeof(T), n); 00182 } 00183 } 00184 00185 return m; 00186 } 00187 00188 00190 // get data out from a message 00191 template<class T, unsigned Dim> 00192 Message& BrickIterator<T,Dim>::getMessage(Message& m) { 00193 TAU_TYPE_STRING(taustr, "Message& (" + CT(m) + " )" ); 00194 TAU_PROFILE("BrickIterator::getMessage", taustr, TAU_FIELD|TAU_MESSAGE); 00195 int i, n, s[Dim]; 00196 00197 // this will only work if this iterator does not yet point 00198 // at any data 00199 PInsist(Current == 0, 00200 "Iterator already has data in BrickIterator::getMessage!!"); 00201 00202 // retrieve size of data in message, and set counters, strides, etc. 00203 m.get((int*) s); 00204 for (n=1, i=0; i < Dim; ++i) { 00205 BrickCounter<Dim>::Counts[i] = s[i]; 00206 BrickCounter<Dim>::Counters[i] = 0; 00207 Strides[i] = n; 00208 n *= s[i]; 00209 } 00210 00211 // retrieve actual data into an allocated buffer 00212 // NOTE: This just stores a pointer to the data that is actually stored 00213 // in the Message item. It does not make its own copy. So, if you use 00214 // a BrickIterator to get data from a message, you must use the data in the 00215 // BrickIterator BEFORE you delete the Message. Otherwise, you'll be 00216 // pointing at deallocated memory. 00217 /* 00218 Current = new T[n]; 00219 ::getMessage_iter(m, Current); 00220 */ 00221 Current = static_cast<T *>(m.item(0).data()); 00222 m.get(); 00223 return m; 00224 } 00225 00226 00227 00228 /*************************************************************************** 00229 * $RCSfile: BrickIterator.cpp,v $ $Author: adelmann $ 00230 * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:26 $ 00231 * IPPL_VERSION_ID: $Id: BrickIterator.cpp,v 1.1.1.1 2003/01/23 07:40:26 adelmann Exp $ 00232 ***************************************************************************/