QUDA  v1.1.0
A library for QCD on GPUs
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) {
41  create(QUDA_COPY_FIELD_CREATE);
42  memcpy(v,src.v,bytes);
43  }
44 
46  ColorSpinorField(src), init(false), reference(false) {
47  create(QUDA_COPY_FIELD_CREATE);
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 &&
66  param.siteSubset == QUDA_PARITY_SITE_SUBSET &&
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
103  create(QUDA_COPY_FIELD_CREATE);
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
115  create(QUDA_COPY_FIELD_CREATE);
116  }
117  src.saveSpinorField(*this);
118  return *this;
119  }
120 
121  void cpuColorSpinorField::create(const QudaFieldCreate create) {
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  if (pad != 0) errorQuda("Non-zero pad not supported");
134  if (precision < QUDA_SINGLE_PRECISION) errorQuda("Fixed-point precision not supported");
135 
141  errorQuda("Field order %d not supported", fieldOrder);
142  }
143 
144  if (create != QUDA_REFERENCE_FIELD_CREATE) {
145  // array of 4-d fields
147  int Ls = x[nDim-1];
148  v = (void**)safe_malloc(Ls * sizeof(void*));
149  for (int i=0; i<Ls; i++) ((void**)v)[i] = safe_malloc(bytes / Ls);
150  } else {
151  v = safe_malloc(bytes);
152  }
153  init = true;
154  }
155 
157  ColorSpinorParam param(*this);
158  param.siteSubset = QUDA_PARITY_SITE_SUBSET;
159  param.nDim = nDim;
160  memcpy(param.x, x, nDim*sizeof(int));
161  param.x[0] /= 2;
163  param.v = v;
164  param.norm = norm;
165  param.is_composite = false;
166  param.composite_dim = 0;
167  param.is_component = composite_descr.is_component;
168  param.component_id = composite_descr.id;
169  even = new cpuColorSpinorField(*this, param);
170  odd = new cpuColorSpinorField(*this, param);
171 
172  // need this hackery for the moment (need to locate the odd pointers half way into the full field)
173  (dynamic_cast<cpuColorSpinorField*>(odd))->v = (void*)((char*)v + bytes/2);
175  (dynamic_cast<cpuColorSpinorField*>(odd))->norm = (void*)((char*)norm + norm_bytes/2);
176 
177  if (bytes != 2*even->Bytes() || bytes != 2*odd->Bytes())
178  errorQuda("dual-parity fields should have double the size of a single-parity field (%lu,%lu,%lu)\n",
179  bytes, even->Bytes(), odd->Bytes());
180  }
181 
182  }
183 
184  void cpuColorSpinorField::destroy() {
185 
186  if (init) {
188  for (int i=0; i<x[nDim-1]; i++) host_free(((void**)v)[i]);
189  host_free(v);
190  init = false;
191  }
192 
194  if (even) delete even;
195  if (odd) delete odd;
196  }
197 
198  }
199 
201  checkField(*this, src);
202  if (fieldOrder == src.fieldOrder && bytes == src.Bytes()) {
204  for (int i=0; i<x[nDim-1]; i++) memcpy(((void**)v)[i], ((void**)src.v)[i], bytes/x[nDim-1]);
205  else
206  memcpy(v, src.v, bytes);
207  } else {
209  }
210  }
211 
213  if (backed_up) errorQuda("Field already backed up");
214 
215  backup_h = new char[bytes];
216  memcpy(backup_h, v, bytes);
217 
218  if (norm_bytes) {
219  backup_norm_h = new char[norm_bytes];
220  memcpy(backup_norm_h, norm, norm_bytes);
221  }
222 
223  backed_up = true;
224  }
225 
227  {
228  if (!backed_up) errorQuda("Cannot restore since not backed up");
229 
230  memcpy(v, backup_h, bytes);
231  delete []backup_h;
232  if (norm_bytes) {
233  memcpy(norm, backup_norm_h, norm_bytes);
234  delete []backup_norm_h;
235  }
236 
237  backed_up = false;
238  }
239 
242  else for (int i=0; i<x[nDim-1]; i++) memset(((void**)v)[i], '\0', bytes/x[nDim-1]);
243  }
244 
245  void cpuColorSpinorField::Source(QudaSourceType source_type, int x, int s, int c) {
246  genericSource(*this, source_type, x, s, c);
247  }
248 
250  const int tol) {
251  checkField(a,b);
252  return genericCompare(a, b, tol);
253  }
254 
255  // print out the vector at volume point x
256  void cpuColorSpinorField::PrintVector(unsigned int x) const { genericPrintVector(*this, x); }
257 
259  {
260  int spinor_size = 2*nSpin*nColor*precision;
261  bool resize = false;
262 
263  // resize face only if requested size is larger than previously allocated one
264  for (int i=0; i<nDimComms; i++) {
265  size_t nbytes = siteSubset*nFace*surfaceCB[i]*spinor_size;
266  resize = (nbytes > ghostFaceBytes[i]) ? true : resize;
267  ghostFaceBytes[i] = (nbytes > ghostFaceBytes[i]) ? nbytes : ghostFaceBytes[i];
268  }
269 
270  if (!initGhostFaceBuffer || resize) {
271  freeGhostBuffer();
272  for (int i=0; i<nDimComms; i++) {
277  }
279  }
280  }
281 
282 
284  {
285  if(!initGhostFaceBuffer) return;
286 
287  for(int i=0; i < 4; i++){ // make nDimComms static?
292  }
294  }
295 
296 
297  void cpuColorSpinorField::packGhost(void **ghost, const QudaParity parity, const int nFace, const int dagger) const
298  {
299  genericPackGhost(ghost, *this, parity, nFace, dagger);
300  return;
301  }
302 
303  void cpuColorSpinorField::unpackGhost(void* ghost_spinor, const int dim,
304  const QudaDirection dir, const int dagger)
305  {
306  if (this->siteSubset == QUDA_FULL_SITE_SUBSET){
307  errorQuda("Full spinor is not supported in unpackGhost for cpu");
308  }
309  }
310 
312  const MemoryLocation *dummy2, bool dummy3, bool dummy4, QudaPrecision dummy5) const
313  {
314  // allocate ghost buffer if not yet allocated
315  allocateGhostBuffer(nFace);
316 
317  void **sendbuf = static_cast<void**>(safe_malloc(nDimComms * 2 * sizeof(void*)));
318 
319  for (int i=0; i<nDimComms; i++) {
320  sendbuf[2*i + 0] = backGhostFaceSendBuffer[i];
321  sendbuf[2*i + 1] = fwdGhostFaceSendBuffer[i];
322  ghost_buf[2*i + 0] = backGhostFaceBuffer[i];
323  ghost_buf[2*i + 1] = fwdGhostFaceBuffer[i];
324  }
325 
326  packGhost(sendbuf, parity, nFace, dagger);
327 
328  exchange(ghost_buf, sendbuf, nFace);
329 
330  host_free(sendbuf);
331  }
332 
333  void cpuColorSpinorField::copy_to_buffer(void *buffer) const
334  {
335  std::memcpy(buffer, v, bytes);
336  if (precision < QUDA_SINGLE_PRECISION) { std::memcpy(static_cast<char *>(buffer) + bytes, norm, norm_bytes); }
337  }
338 
340  {
341  std::memcpy(v, buffer, bytes);
342  if (precision < QUDA_SINGLE_PRECISION) { std::memcpy(norm, static_cast<char *>(buffer) + bytes, norm_bytes); }
343  }
344 
345 } // namespace quda
void exchange(void **ghost, void **sendbuf, int nFace=1) const
virtual ColorSpinorField & operator=(const ColorSpinorField &)
void * ghost_buf[2 *QUDA_MAX_DIM]
ColorSpinorField * even
CompositeColorSpinorFieldDescriptor composite_descr
used for deflation eigenvector sets etc.:
QudaSiteSubset SiteSubset() const
void * ghost[2][QUDA_MAX_DIM]
void reset(const ColorSpinorParam &)
static void checkField(const ColorSpinorField &, const ColorSpinorField &)
ColorSpinorField * odd
QudaPrecision precision
int surfaceCB[QUDA_MAX_DIM]
virtual void copy_from_buffer(void *buffer)
Copy all contents of the field from a host buffer to this field.
void unpackGhost(void *ghost_spinor, const int dim, const QudaDirection dir, const int dagger)
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...
static size_t ghostFaceBytes[QUDA_MAX_DIM]
static void * fwdGhostFaceSendBuffer[QUDA_MAX_DIM]
virtual void copy_to_buffer(void *buffer) const
Copy all contents of the field to a host buffer.
void backup() const
Backs up the cpuColorSpinorField.
static void * fwdGhostFaceBuffer[QUDA_MAX_DIM]
void packGhost(void **ghost, const QudaParity parity, const int nFace, const int dagger) const
void restore() const
Restores the cpuColorSpinorField.
static void * backGhostFaceSendBuffer[QUDA_MAX_DIM]
void copy(const cpuColorSpinorField &)
ColorSpinorField & operator=(const ColorSpinorField &)
void Source(const QudaSourceType sourceType, const int st=0, const int s=0, const int c=0)
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...
cpuColorSpinorField(const cpuColorSpinorField &)
static void * backGhostFaceBuffer[QUDA_MAX_DIM]
void PrintVector(unsigned int x) const
void allocateGhostBuffer(int nFace) const
Allocate the ghost buffers.
double tol
std::array< int, 4 > dim
bool dagger
void * memset(void *s, int c, size_t n)
QudaParity parity
Definition: covdev_test.cpp:40
enum QudaPrecision_s QudaPrecision
@ QUDA_CPU_FIELD_LOCATION
Definition: enum_quda.h:325
enum QudaDirection_s QudaDirection
@ QUDA_FULL_SITE_SUBSET
Definition: enum_quda.h:333
@ QUDA_PARITY_SITE_SUBSET
Definition: enum_quda.h:332
enum QudaFieldCreate_s QudaFieldCreate
@ QUDA_SINGLE_PRECISION
Definition: enum_quda.h:64
@ QUDA_QUARTER_PRECISION
Definition: enum_quda.h:62
@ QUDA_HALF_PRECISION
Definition: enum_quda.h:63
enum QudaSourceType_s QudaSourceType
@ QUDA_SPACE_COLOR_SPIN_FIELD_ORDER
Definition: enum_quda.h:352
@ QUDA_QOP_DOMAIN_WALL_FIELD_ORDER
Definition: enum_quda.h:354
@ QUDA_QDPJIT_FIELD_ORDER
Definition: enum_quda.h:353
@ QUDA_PADDED_SPACE_SPIN_COLOR_FIELD_ORDER
Definition: enum_quda.h:355
@ QUDA_SPACE_SPIN_COLOR_FIELD_ORDER
Definition: enum_quda.h:351
@ QUDA_ZERO_FIELD_CREATE
Definition: enum_quda.h:361
@ QUDA_COPY_FIELD_CREATE
Definition: enum_quda.h:362
@ QUDA_REFERENCE_FIELD_CREATE
Definition: enum_quda.h:363
@ QUDA_NULL_FIELD_CREATE
Definition: enum_quda.h:360
enum QudaParity_s QudaParity
int Ls
Definition: host_utils.cpp:48
#define safe_malloc(size)
Definition: malloc_quda.h:106
#define host_free(ptr)
Definition: malloc_quda.h:115
void init()
Create the BLAS context.
void genericPackGhost(void **ghost, const ColorSpinorField &a, QudaParity parity, int nFace, int dagger, MemoryLocation *destination=nullptr)
Generic ghost packing routine.
void copyGenericColorSpinor(ColorSpinorField &dst, const ColorSpinorField &src, QudaFieldLocation location, void *Dst=0, void *Src=0, void *dstNorm=0, void *srcNorm=0)
void genericPrintVector(const cpuColorSpinorField &a, unsigned int x)
void genericSource(cpuColorSpinorField &a, QudaSourceType sourceType, int x, int s, int c)
int genericCompare(const cpuColorSpinorField &a, const cpuColorSpinorField &b, int tol)
QudaGaugeParam param
Definition: pack_test.cpp:18
#define QUDA_MAX_DIM
Maximum number of dimensions supported by QUDA. In practice, no routines make use of more than 5.
#define ALIGNMENT_ADJUST(n)
Definition: quda_internal.h:42
#define errorQuda(...)
Definition: util_quda.h:120