QUDA  1.0.0
cpu_color_spinor_field.cpp
Go to the documentation of this file.
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <iostream>
5 #include <typeinfo>
6 #include <color_spinor_field.h>
7 #include <comm_quda.h> // for comm_drand()
8 
9 namespace quda {
10 
16 
18 
20  ColorSpinorField(param), init(false), reference(false) {
21 
22  // need to set this before create
23  if (param.create == QUDA_REFERENCE_FIELD_CREATE) {
24  v = param.v;
25  reference = true;
26  }
27 
28  create(param.create);
29 
31  // do nothing
32  } else if (param.create == QUDA_ZERO_FIELD_CREATE) {
33  zero();
34  } else {
35  errorQuda("Creation type %d not supported", param.create);
36  }
37  }
38 
40  ColorSpinorField(src), init(false), reference(false) {
42  memcpy(v,src.v,bytes);
43  }
44 
46  ColorSpinorField(src), init(false), reference(false) {
48  if (typeid(src) == typeid(cpuColorSpinorField)) {
49  memcpy(v, dynamic_cast<const cpuColorSpinorField&>(src).v, bytes);
50  } else if (typeid(src) == typeid(cudaColorSpinorField)) {
51  dynamic_cast<const cudaColorSpinorField&>(src).saveSpinorField(*this);
52  } else {
53  errorQuda("Unknown input ColorSpinorField %s", typeid(src).name());
54  }
55  }
56 
57  /*
58  This is special case constructor used to create parity subset references with in a full field
59  */
61  ColorSpinorField(src), init(false), reference(false) {
62 
63  // can only overide if we parity subset reference special case
64  if ( param.create == QUDA_REFERENCE_FIELD_CREATE &&
67  typeid(src) == typeid(cpuColorSpinorField) ) {
68  reset(param);
69  } else {
70  errorQuda("Undefined behaviour"); // else silent bug possible?
71  }
72 
73  // need to set this before create
74  if (param.create == QUDA_REFERENCE_FIELD_CREATE) {
75  v = (void*)src.V();
76  norm = (void*)src.Norm();
77  }
78 
79  create(param.create);
80  }
81 
83  destroy();
84  }
85 
87  if (typeid(src) == typeid(cudaColorSpinorField)) {
88  *this = (dynamic_cast<const cudaColorSpinorField&>(src));
89  } else if (typeid(src) == typeid(cpuColorSpinorField)) {
90  *this = (dynamic_cast<const cpuColorSpinorField&>(src));
91  } else {
92  errorQuda("Unknown input ColorSpinorField %s", typeid(src).name());
93  }
94  return *this;
95  }
96 
98  if (&src != this) {
99  if (!reference) {
100  destroy();
101  // keep current attributes unless unset
104  }
105  copy(src);
106  }
107  return *this;
108  }
109 
111  if (!reference) { // if the field is a reference, then we must maintain the current state
112  destroy();
113  // keep current attributes unless unset
116  }
117  src.saveSpinorField(*this);
118  return *this;
119  }
120 
122  // these need to be reset to ensure no ghost zones for the cpu
123  // fields since we can't determine during the parent's constructor
124  // whether the field is a cpu or cuda field
125 
126  // set this again here. this is a hack since we can determine we
127  // have a cpu or cuda field in ColorSpinorField::create(), which
128  // means a ghost zone is set. So we unset it here. This will be
129  // fixed when clean up the ghost code with the peer-2-peer branch
130  bytes = length * precision;
132 
133 
134  if (pad != 0) errorQuda("Non-zero pad not supported");
135  if (precision == QUDA_HALF_PRECISION) errorQuda("Half precision not supported");
136  if (precision == QUDA_QUARTER_PRECISION) errorQuda("Quarter precision not supported");
137 
143  errorQuda("Field order %d not supported", fieldOrder);
144  }
145 
146  if (create != QUDA_REFERENCE_FIELD_CREATE) {
147  // array of 4-d fields
149  int Ls = x[nDim-1];
150  v = (void**)safe_malloc(Ls * sizeof(void*));
151  for (int i=0; i<Ls; i++) ((void**)v)[i] = safe_malloc(bytes / Ls);
152  } else {
153  v = safe_malloc(bytes);
154  }
155  init = true;
156  }
157 
159  ColorSpinorParam param(*this);
161  param.nDim = nDim;
162  memcpy(param.x, x, nDim*sizeof(int));
163  param.x[0] /= 2;
165  param.v = v;
166  param.norm = norm;
167  param.is_composite = false;
168  param.composite_dim = 0;
171  even = new cpuColorSpinorField(*this, param);
172  odd = new cpuColorSpinorField(*this, param);
173 
174  // need this hackery for the moment (need to locate the odd pointers half way into the full field)
175  (dynamic_cast<cpuColorSpinorField*>(odd))->v = (void*)((char*)v + bytes/2);
176  if (precision == QUDA_HALF_PRECISION || precision == QUDA_QUARTER_PRECISION)
177  (dynamic_cast<cpuColorSpinorField*>(odd))->norm = (void*)((char*)norm + norm_bytes/2);
178 
179  if (bytes != 2*even->Bytes() || bytes != 2*odd->Bytes())
180  errorQuda("dual-parity fields should have double the size of a single-parity field (%lu,%lu,%lu)\n",
181  bytes, even->Bytes(), odd->Bytes());
182  }
183 
184  }
185 
187 
188  if (init) {
190  for (int i=0; i<x[nDim-1]; i++) host_free(((void**)v)[i]);
191  host_free(v);
192  init = false;
193  }
194 
196  if (even) delete even;
197  if (odd) delete odd;
198  }
199 
200  }
201 
203  checkField(*this, src);
204  if (fieldOrder == src.fieldOrder && bytes == src.Bytes()) {
206  for (int i=0; i<x[nDim-1]; i++) memcpy(((void**)v)[i], ((void**)src.v)[i], bytes/x[nDim-1]);
207  else
208  memcpy(v, src.v, bytes);
209  } else {
211  }
212  }
213 
215  if (backed_up) errorQuda("Field already backed up");
216 
217  backup_h = new char[bytes];
218  memcpy(backup_h, v, bytes);
219 
220  if (norm_bytes) {
221  backup_norm_h = new char[norm_bytes];
222  memcpy(backup_norm_h, norm, norm_bytes);
223  }
224 
225  backed_up = true;
226  }
227 
229  {
230  if (!backed_up) errorQuda("Cannot restore since not backed up");
231 
232  memcpy(v, backup_h, bytes);
233  delete []backup_h;
234  if (norm_bytes) {
235  memcpy(norm, backup_norm_h, norm_bytes);
236  delete []backup_norm_h;
237  }
238 
239  backed_up = false;
240  }
241 
244  else for (int i=0; i<x[nDim-1]; i++) memset(((void**)v)[i], '\0', bytes/x[nDim-1]);
245  }
246 
247  void cpuColorSpinorField::Source(QudaSourceType source_type, int x, int s, int c) {
248  genericSource(*this, source_type, x, s, c);
249  }
250 
252  const int tol) {
253  checkField(a,b);
254  return genericCompare(a, b, tol);
255  }
256 
257  // print out the vector at volume point x
258  void cpuColorSpinorField::PrintVector(unsigned int x) const { genericPrintVector(*this, x); }
259 
261  {
262  int spinor_size = 2*nSpin*nColor*precision;
263  bool resize = false;
264 
265  // resize face only if requested size is larger than previously allocated one
266  for (int i=0; i<nDimComms; i++) {
267  size_t nbytes = siteSubset*nFace*surfaceCB[i]*spinor_size;
268  resize = (nbytes > ghostFaceBytes[i]) ? true : resize;
269  ghostFaceBytes[i] = (nbytes > ghostFaceBytes[i]) ? nbytes : ghostFaceBytes[i];
270  }
271 
272  if (!initGhostFaceBuffer || resize) {
273  freeGhostBuffer();
274  for (int i=0; i<nDimComms; i++) {
279  }
281  }
282  }
283 
284 
286  {
287  if(!initGhostFaceBuffer) return;
288 
289  for(int i=0; i < 4; i++){ // make nDimComms static?
294  }
296  }
297 
298 
299  void cpuColorSpinorField::packGhost(void **ghost, const QudaParity parity, const int nFace, const int dagger) const
300  {
301  genericPackGhost(ghost, *this, parity, nFace, dagger);
302  return;
303  }
304 
305  void cpuColorSpinorField::unpackGhost(void* ghost_spinor, const int dim,
306  const QudaDirection dir, const int dagger)
307  {
308  if (this->siteSubset == QUDA_FULL_SITE_SUBSET){
309  errorQuda("Full spinor is not supported in unpackGhost for cpu");
310  }
311  }
312 
314  const MemoryLocation *dummy2, bool dummy3, bool dummy4, QudaPrecision dummy5) const
315  {
316  // allocate ghost buffer if not yet allocated
317  allocateGhostBuffer(nFace);
318 
319  void **sendbuf = static_cast<void**>(safe_malloc(nDimComms * 2 * sizeof(void*)));
320 
321  for (int i=0; i<nDimComms; i++) {
322  sendbuf[2*i + 0] = backGhostFaceSendBuffer[i];
323  sendbuf[2*i + 1] = fwdGhostFaceSendBuffer[i];
324  ghost_buf[2*i + 0] = backGhostFaceBuffer[i];
325  ghost_buf[2*i + 1] = fwdGhostFaceBuffer[i];
326  }
327 
328  packGhost(sendbuf, parity, nFace, dagger);
329 
330  exchange(ghost_buf, sendbuf, nFace);
331 
332  host_free(sendbuf);
333  }
334 
335 } // namespace quda
int genericCompare(const cpuColorSpinorField &a, const cpuColorSpinorField &b, int tol)
void genericPrintVector(const cpuColorSpinorField &a, unsigned int x)
void copy(const cpuColorSpinorField &)
void PrintVector(unsigned int x) const
void unpackGhost(void *ghost_spinor, const int dim, const QudaDirection dir, const int dagger)
enum QudaPrecision_s QudaPrecision
#define errorQuda(...)
Definition: util_quda.h:121
#define host_free(ptr)
Definition: malloc_quda.h:71
void create(const QudaFieldCreate)
CompositeColorSpinorFieldDescriptor composite_descr
used for deflation eigenvector sets etc.:
cpuColorSpinorField(const cpuColorSpinorField &)
void Source(const QudaSourceType sourceType, const int st=0, const int s=0, const int c=0)
void copyGenericColorSpinor(ColorSpinorField &dst, const ColorSpinorField &src, QudaFieldLocation location, void *Dst=0, void *Src=0, void *dstNorm=0, void *srcNorm=0)
void restore() const
Restores the cpuColorSpinorField.
QudaSiteSubset siteSubset
Definition: lattice_field.h:71
enum QudaSourceType_s QudaSourceType
int Ls
Definition: test_util.cpp:38
QudaGaugeParam param
Definition: pack_test.cpp:17
void packGhost(void **ghost, const QudaParity parity, const int nFace, const int dagger) const
int x[QUDA_MAX_DIM]
Definition: lattice_field.h:67
bool is_composite
for deflation solvers:
enum QudaDirection_s QudaDirection
static void * backGhostFaceSendBuffer[QUDA_MAX_DIM]
void genericPackGhost(void **ghost, const ColorSpinorField &a, QudaParity parity, int nFace, int dagger, MemoryLocation *destination=nullptr)
Generic ghost packing routine.
ColorSpinorField * odd
double tol
Definition: test_util.cpp:1656
static void checkField(const ColorSpinorField &, const ColorSpinorField &)
void exchange(void **ghost, void **sendbuf, int nFace=1) const
void reset(const ColorSpinorParam &)
#define ALIGNMENT_ADJUST(n)
Definition: quda_internal.h:22
QudaSiteSubset SiteSubset() const
void saveSpinorField(ColorSpinorField &src) const
void * ghost[2][QUDA_MAX_DIM]
static void * backGhostFaceBuffer[QUDA_MAX_DIM]
enum QudaParity_s QudaParity
void genericSource(cpuColorSpinorField &a, QudaSourceType sourceType, int x, int s, int c)
void exchangeGhost(QudaParity parity, int nFace, int dagger, const MemoryLocation *pack_destination=nullptr, const MemoryLocation *halo_location=nullptr, bool gdr_send=false, bool gdr_recv=false, QudaPrecision ghost_precision=QUDA_INVALID_PRECISION) const
This is a unified ghost exchange function for doing a complete halo exchange regardless of the type o...
void init()
Create the CUBLAS context.
Definition: blas_cublas.cu:31
static void * fwdGhostFaceSendBuffer[QUDA_MAX_DIM]
#define safe_malloc(size)
Definition: malloc_quda.h:66
static void * fwdGhostFaceBuffer[QUDA_MAX_DIM]
static int Compare(const cpuColorSpinorField &a, const cpuColorSpinorField &b, const int resolution=1)
Perform a component by component comparison of two color-spinor fields. In doing we normalize with re...
void * memset(void *s, int c, size_t n)
virtual ColorSpinorField & operator=(const ColorSpinorField &)
void backup() const
Backs up the cpuColorSpinorField.
__shared__ float s[]
void allocateGhostBuffer(int nFace) const
Allocate the ghost buffers.
int surfaceCB[QUDA_MAX_DIM]
enum QudaFieldCreate_s QudaFieldCreate
#define QUDA_MAX_DIM
Maximum number of dimensions supported by QUDA. In practice, no routines make use of more than 5...
void * ghost_buf[2 *QUDA_MAX_DIM]
QudaDagType dagger
Definition: test_util.cpp:1620
QudaParity parity
Definition: covdev_test.cpp:54
QudaPrecision precision
static size_t ghostFaceBytes[QUDA_MAX_DIM]
ColorSpinorField * even
ColorSpinorField & operator=(const ColorSpinorField &)