MorphoGraphX  2.0-1-227
DistObject.hpp
Go to the documentation of this file.
1 //
2 // This file is part of MorphoGraphX - http://www.MorphoGraphX.org
3 // Copyright (C) 2012-2016 Richard S. Smith and collaborators.
4 //
5 // If you use MorphoGraphX in your work, please cite:
6 // http://dx.doi.org/10.7554/eLife.05864
7 //
8 // MorphoGraphX is free software, and is licensed under under the terms of the
9 // GNU General (GPL) Public License version 2.0, http://www.gnu.org/licenses.
10 //
11 #ifndef DIST_OBJECT_HPP
12 #define DIST_OBJECT_HPP
13 
22 #include <QString>
23 #include <Attributes.hpp>
24 #include <ThrustTypes.hpp>
25 
26 namespace mgx
27 {
28  template<typename T1, typename T2>
29  int copyGPU(T1 *src, T2 *dst);
30 
31  template<typename T>
32  int allocGPU(T **vec, size_t n);
33 
39  template <typename vvGraphT>
40  class DistNhbd
41  {
42  public:
43  // Type of the graph
44  typedef vvGraphT vvGraph;
45  // Type of a vertex
46  typedef typename vvGraphT::vertex_t Vertex;
47  // Type of vertex content
48  typedef typename Vertex::content_t VertexContent;
49  // Type of an edge
50  typedef typename vvGraphT::edge_t Edge;
51  // Type of vertex content
52  typedef typename Edge::content_t EdgeContent;
53 
54  private:
55  uint _n;
56  uint _nbs;
57  vvGraphT &_S;
58  thrust::device_vector<uint> *_data; // Neighborhood information
59  std::unordered_map<Vertex, uint> _vNum;
60 
61  public:
62  // Set offset of data item in vertex
63  DistNhbd(vvGraphT &S) : _n(S.size()), _S(S), _data(0) {}
64 
65  // Clean up
66  virtual ~DistNhbd() { allocGPU(&_data, 0); }
67 
68  // Return # of vertices
69  uint n() { return _n; };
70 
71  // Return max # of neighbors
72  uint nbs() { return _nbs; };
73 
74  // Return pointer to device buffer
75  thrust::device_vector<uint> *data()
76  {
77  return _data;
78  };
79 
80  // Return graph
81  vvGraphT &graph() { return _S; };
82 
83  // Return vertex number from our ordering map
84  uint vNum(const Vertex &v) { return _vNum[v]; };
85 
86  // Allocate and send to GPU
87  void write()
88  {
89  // Record vertex numbers and find max # of neighbors
90  _vNum.clear();
91  _n = _nbs = 0;
92  forall(const Vertex &v, _S) {
93  _vNum[v] = _n++;
94  if(_S.valence(v) > _nbs)
95  _nbs = _S.valence(v);
96  }
97  if(_n * _nbs == 0)
98  return;
99  thrust::host_vector<uint> hData(_n * _nbs);
100  uint d = 0;
101  // Grab the neighborhood information
102  forall(const Vertex &v, _S) {
103  // Put in edge data,
104  forall(const Vertex &w, _S.neighbors(v))
105  hData[d++] = _vNum[w];
106 
107  // Use current index to indicate empty
108  for(uint k = _S.valence(v); k < _nbs; k++)
109  hData[d++] = _vNum[v];
110  }
111  // Write to device
112  try {
113  allocGPU(&_data, _n * _nbs) ;
114  } catch (const std::exception &e) {
115  throw(QString("Unable to allocate distributed neighborhood object of sizes %1 %2 %3, err:%4")
116  .arg(_n).arg(_nbs).arg(sizeof(uint)).arg(e.what()));
117  } catch(...) {
118  throw(QString("Unable to allocate distributed neighborhood object of sizes %1 %2 %3")
119  .arg(_n).arg(_nbs).arg(sizeof(uint)));
120  }
121  copyGPU(&hData, _data);
122  }
123  };
124 
132  template <typename DistNhbdT, typename DataT>
134  {
135  DistNhbdT &_nhbd; // Distributed neighborhood object
136  thrust::device_vector<DataT> *_data; // Distributed data
137  bool _hasHostData;// Is there host-side storage? or is it GPU only?
138 
139  protected:
140  // Constructor for object with host data, only from derived classes
141  DistVertex(DistNhbdT &nhbd, bool hasData) : _nhbd(nhbd), _data(0), _hasHostData(hasData) {}
142 
143  public:
144  // Constructor for object with no host data (GPU only)
145  DistVertex(DistNhbdT &nhbd) : _nhbd(nhbd), _data(0), _hasHostData(false) {}
146 
147  // Clean up
148  virtual ~DistVertex() { allocGPU(&_data, 0); }
149 
150  // Get a data entry
151  virtual DataT *vData(const typename DistNhbdT::Vertex &) { return 0; }
152 
153  // Return neighborhood object
154  DistNhbdT &nhbd() { return _nhbd; };
155 
156  // Return pointer to device buffer
157  thrust::device_vector<DataT> *data()
158  {
159  alloc();
160  return _data;
161  };
162 
163  // Allocate space on GPU
164  void alloc()
165  {
166  try {
167  allocGPU(&_data, _nhbd.n());
168  } catch (const std::exception &e) {
169  throw(QString("Unable to allocate distributed vertex object of sizes %1 %2, err:%3")
170  .arg(_nhbd.n()).arg(sizeof(DataT)).arg(e.what()));
171  } catch(...) {
172  throw(QString("Unable to allocate distributed vertex object of sizes %1 %2")
173  .arg(_nhbd.n()).arg(sizeof(DataT)));
174  }
175  }
176 
177  // Copy vertex data to GPU
178  void write()
179  {
180  if(!_hasHostData)
181  throw(QString("Error: Distributed vector has no host storage"));
182  if(_nhbd.n() <= 0)
183  return;
184 
185  thrust::host_vector<DataT> hData(_nhbd.n());
186  forall(const typename DistNhbdT::Vertex &v, _nhbd.graph())
187  hData[_nhbd.vNum(v)] = *vData(v);
188 
189  // Write to device
190  alloc();
191  copyGPU(&hData, _data);
192  }
193 
194  // Copy vertex data to Host
195  void read()
196  {
197  if(!_hasHostData)
198  throw(QString("Error: Distributed vector has no host storage"));
199  if(_nhbd.n() <= 0)
200  return;
201  if(_data->size() != _nhbd.n())
202  throw(QString("Error: Distributed vector size mismatch on device buffer"));
203 
204  // Read data from device
205  thrust::host_vector<DataT> hData(_nhbd.n());
206  copyGPU(_data, &hData);
207  forall(const typename DistNhbdT::Vertex &v, _nhbd.graph())
208  *vData(v) = hData[_nhbd.vNum(v)];
209  }
210  };
211 
217  template <typename DistNhbdT, typename DataT>
218  class DistVertexGraph : public DistVertex<DistNhbdT, DataT>
219  {
220  DataT DistNhbdT::VertexContent::*_off;
221 
222  public:
223  // Constructor for object with memory in vertices of the graph
224  DistVertexGraph(DistNhbdT &nhbd, DataT DistNhbdT::VertexContent::*off)
225  : DistVertex<DistNhbdT, DataT>(nhbd, true), _off(off) {}
226 
227  // Get data
228  DataT *vData(const typename DistNhbdT::Vertex &v)
229  {
230  return &((*v).*_off);
231  }
232  };
233 
239  template <typename DistNhbdT, typename ContentT, typename DataT>
240  class DistVertexAttr : public DistVertex<DistNhbdT, DataT>
241  {
242  private:
244  DataT ContentT::*_off;
245 
246  public:
247  // Constructor for object with memory in vertices of the graph
249  DataT ContentT::*off)
250  : DistVertex<DistNhbdT, DataT>(nhbd, true), _map(map), _off(off) {}
251 
252  // Get data
253  DataT *vData(const typename DistNhbdT::Vertex &v)
254  {
255  return &((v->*_map).*_off);
256  }
257 
258  // Set (or reset) attribute map. I may change when mesh is reset.
260  {
261  _map = map;
262  }
263  };
264 
272  template <typename DistNhbdT, typename DataT>
273  class DistEdge
274  {
275  public:
276  DistNhbdT &_nhbd; // Distributed neighborhood object
277  bool _hasHostData;// Is there host-side storage? (or is it GPU only)
278  thrust::device_vector<DataT> *_data; // Distributed data
279 
280  public:
281  // Constructor for object with no host data (only GPU)
283 
284  protected:
285  // Constructor for object with host data, only from derived classes
286  DistEdge(DistNhbdT &nhbd, bool hasData) : _nhbd(nhbd), _hasHostData(hasData), _data(0) {}
287 
288  public:
289  // Clean up
290  virtual ~DistEdge() { allocGPU(&_data, 0); }
291 
292  // Return neighborhood object
293  DistNhbdT &nhbd() { return _nhbd; };
294 
295  // Get edge data
296  virtual DataT *eData(const typename DistNhbdT::Vertex &v1, const typename DistNhbdT::Vertex &v2) { return 0; }
297 
298  // Return pointer to device buffer
299  thrust::device_vector<DataT> *data()
300  {
301  alloc();
302  return _data;
303  };
304 
305  // Allocate space on GPU
306  void alloc()
307  {
308  try {
309  allocGPU(&_data, _nhbd.n() * _nhbd.nbs());
310  } catch (const std::exception &e) {
311  throw(QString("Unable to allocate distributed neighborhood object of sizes %1 %2 %3, err:%4")
312  .arg(_nhbd.n()).arg(_nhbd.nbs()).arg(sizeof(DataT)).arg(e.what()));
313  } catch(...) {
314  throw(QString("Unable to allocate distributed edge object of sizes %1 %2 %3")
315  .arg(_nhbd.n()).arg(_nhbd.nbs()).arg(sizeof(DataT)));
316  }
317  }
318 
319  // Send edge data to GPU
320  void write()
321  {
322  if(!_hasHostData)
323  throw(QString("Error: DistEdge is temp (no graph storage)"));
324  // No data, just return
325  if(_nhbd.n() * _nhbd.nbs() <= 0)
326  return;
327 
328  thrust::host_vector<DataT> hData(_nhbd.n() * _nhbd.nbs());
329  // Grab data
330  uint d = 0;
331  forall(const typename DistNhbdT::Vertex &v, _nhbd.graph()) {
332  forall(const typename DistNhbdT::Vertex &w, _nhbd.graph().neighbors(v))
333  hData[d++] = *eData(v,w);
334 
335  // Pad rest of nhbd with 0s
336  for(uint k = _nhbd.graph().valence(v); k < _nhbd.nbs(); k++)
337  hData[d++] = DataT();
338  }
339  // Write to GPU
340  alloc();
341  copyGPU(&hData, _data);
342  }
343 
344  // Copy edge data to host
345  void read()
346  {
347  if(!_hasHostData)
348  throw(QString("Warning DistEdge is temp (no graph storage)"));
349  // Return if no data
350  if(_nhbd.n() * _nhbd.nbs() <= 0)
351  return;
352 
353  // Read from GPU
354  thrust::host_vector<DataT> hData(_nhbd.n() * _nhbd.nbs());
355  copyGPU(_data, &hData);
356 
357  // Grab data
358  uint s = 0;
359  forall(const typename DistNhbdT::Vertex &v, _nhbd.graph()) {
360  forall(const typename DistNhbdT::Vertex &w, _nhbd.graph().neighbors(v))
361  *eData(v,w) = hData[s++];
362 
363  // Skip 0s
364  for(uint k = _nhbd.graph().valence(v); k < _nhbd.nbs(); k++)
365  s++;
366  }
367  }
368  };
369 
375  template <typename DistNhbdT, typename DataT>
376  class DistEdgeGraph : public DistEdge<DistNhbdT, DataT>
377  {
378  DataT DistNhbdT::EdgeContent::*_off;
379 
380  public:
381  // Constructor for object with memory in edges of the graph
382  DistEdgeGraph(DistNhbdT &nhbd, DataT DistNhbdT::EdgeContent::*off)
383  : DistEdge<DistNhbdT, DataT>(nhbd, true), _off(off) {}
384 
385  // Get data
386  DataT *eData(const typename DistNhbdT::Vertex &v1, const typename DistNhbdT::Vertex &v2)
387  {
388  return &((*DistEdge<DistNhbdT, DataT>::nhbd().graph().edge(v1, v2)).*_off);
389  }
390  };
391 
397  template <typename DistNhbdT, typename ContentT, typename DataT>
398  class DistEdgeAttr : public DistEdge<DistNhbdT, DataT>
399  {
400  public:
401  typedef std::pair<typename DistNhbdT::Vertex, typename DistNhbdT::Vertex> EdgePair;
403  DataT ContentT::*_off;
404 
405  public:
406  // Constructor for object with memory in the attributes system
408  : DistEdge<DistNhbdT, DataT>(nhbd, true), _map(map), _off(off) {}
409 
410  // Get data
411  DataT *eData(const typename DistNhbdT::Vertex &v1, const typename DistNhbdT::Vertex &v2)
412  {
413  return &((EdgePair(v1, v2)->*_map).*_off);
414  }
415 
416  // Set (or reset) attribute map. I may change when mesh is reset.
418  {
419  _map = map;
420  }
421  };
422 }
423 #endif
mgx::DistNhbd::~DistNhbd
virtual ~DistNhbd()
Definition: DistObject.hpp:66
Attributes.hpp
mgx::DistEdge::write
void write()
Definition: DistObject.hpp:320
mgx::uint
unsigned int uint
Definition: Geometry.hpp:41
mgx::DistNhbd::VertexContent
Vertex::content_t VertexContent
Definition: DistObject.hpp:48
mgx::DistNhbd::Edge
vvGraphT::edge_t Edge
Definition: DistObject.hpp:50
mgx::DistEdge::_nhbd
DistNhbdT & _nhbd
Definition: DistObject.hpp:276
mgx::Vertex::content_t
VertexContent content_t
Type of the content of the vertex.
Definition: Vertex.hpp:98
mgx::Edge::content_t
EdgeContent content_t
Type of the content of the edge.
Definition: Edge.hpp:52
DistNhbdT
mgx::DistNhbd::nbs
uint nbs()
Definition: DistObject.hpp:72
mgx::DistNhbd::n
uint n()
Definition: DistObject.hpp:69
mgx::copyGPU
int mgx_EXPORT copyGPU(T1 *src, T2 *dst)
Definition: DistObjectCuda.hpp:21
forall
#define forall
Definition: Forall.hpp:22
mgx::DistNhbd::DistNhbd
DistNhbd(vvGraphT &S)
Definition: DistObject.hpp:63
n
#define n
Definition: Eigenvalues.hpp:36
mgx::DistNhbd::EdgeContent
Edge::content_t EdgeContent
Definition: DistObject.hpp:52
mgx::DistVertexAttr
Definition: DistObject.hpp:240
mgx::DistEdgeAttr::DistEdgeAttr
DistEdgeAttr(DistNhbdT &nhbd, AttrMap< EdgePair, ContentT > *map, DataT ContentT::*off)
Definition: DistObject.hpp:407
mgx::DistEdge
Definition: DistObject.hpp:273
mgx::DistVertex::read
void read()
Definition: DistObject.hpp:195
mgx::DistVertexGraph
Definition: DistObject.hpp:218
mgx::DistEdge::~DistEdge
virtual ~DistEdge()
Definition: DistObject.hpp:290
mgx::DistVertex::nhbd
DistNhbdT & nhbd()
Definition: DistObject.hpp:154
mgx::DistEdgeAttr
Definition: DistObject.hpp:398
ThrustTypes.hpp
mgx::DistEdge::read
void read()
Definition: DistObject.hpp:345
mgx
Distributed matrix library.
Definition: Assert.hpp:26
mgx::DistEdgeAttr::eData
DataT * eData(const typename DistNhbdT::Vertex &v1, const typename DistNhbdT::Vertex &v2)
Definition: DistObject.hpp:411
mgx::DistVertex::DistVertex
DistVertex(DistNhbdT &nhbd, bool hasData)
Definition: DistObject.hpp:141
mgx::allocGPU
int mgx_EXPORT allocGPU(T **vec, size_t n)
Definition: DistObjectCuda.hpp:31
mgx::DistNhbd::data
thrust::device_vector< uint > * data()
Definition: DistObject.hpp:75
mgx::DistVertex::~DistVertex
virtual ~DistVertex()
Definition: DistObject.hpp:148
mgx::DistNhbd::vvGraph
vvGraphT vvGraph
Definition: DistObject.hpp:44
mgx::DistVertex::vData
virtual DataT * vData(const typename DistNhbdT::Vertex &)
Definition: DistObject.hpp:151
mgx::DistVertex::write
void write()
Definition: DistObject.hpp:178
mgx::DistEdge::_data
thrust::device_vector< DataT > * _data
Definition: DistObject.hpp:278
mgx::DistVertex
Definition: DistObject.hpp:133
mgx::DistEdge::DistEdge
DistEdge(DistNhbdT &nhbd)
Definition: DistObject.hpp:282
mgx::DistVertexAttr::setAttrMap
void setAttrMap(AttrMap< typename DistNhbdT::Vertex, ContentT > *map)
Definition: DistObject.hpp:259
mgx::DistEdgeGraph
Definition: DistObject.hpp:376
mgx::DistEdgeAttr::_map
AttrMap< EdgePair, ContentT > * _map
Definition: DistObject.hpp:402
mgx::DistEdge::DistEdge
DistEdge(DistNhbdT &nhbd, bool hasData)
Definition: DistObject.hpp:286
mgx::DistNhbd
Definition: DistObject.hpp:40
mgx::DistNhbd::graph
vvGraphT & graph()
Definition: DistObject.hpp:81
mgx::DistNhbd::Vertex
vvGraphT::vertex_t Vertex
Definition: DistObject.hpp:46
mgx::DistVertex::alloc
void alloc()
Definition: DistObject.hpp:164
mgx::DistEdge::_hasHostData
bool _hasHostData
Definition: DistObject.hpp:277
mgx::DistEdgeAttr::setAttrMap
void setAttrMap(AttrMap< EdgePair, ContentT > *map)
Definition: DistObject.hpp:417
mgx::DistNhbd::vNum
uint vNum(const Vertex &v)
Definition: DistObject.hpp:84
mgx::DistEdgeAttr::_off
DataT ContentT::* _off
Definition: DistObject.hpp:403
mgx::DistVertexAttr::DistVertexAttr
DistVertexAttr(DistNhbdT &nhbd, AttrMap< typename DistNhbdT::Vertex, ContentT > *map, DataT ContentT::*off)
Definition: DistObject.hpp:248
mgx::DistEdge::data
thrust::device_vector< DataT > * data()
Definition: DistObject.hpp:299
mgx::DistEdge::eData
virtual DataT * eData(const typename DistNhbdT::Vertex &v1, const typename DistNhbdT::Vertex &v2)
Definition: DistObject.hpp:296
mgx::DistVertex::DistVertex
DistVertex(DistNhbdT &nhbd)
Definition: DistObject.hpp:145
mgx::DistEdgeAttr::EdgePair
std::pair< typename DistNhbdT::Vertex, typename DistNhbdT::Vertex > EdgePair
Definition: DistObject.hpp:401
mgx::DistEdgeGraph::eData
DataT * eData(const typename DistNhbdT::Vertex &v1, const typename DistNhbdT::Vertex &v2)
Definition: DistObject.hpp:386
mgx::DistVertexAttr::vData
DataT * vData(const typename DistNhbdT::Vertex &v)
Definition: DistObject.hpp:253
mgx::DistEdge::nhbd
DistNhbdT & nhbd()
Definition: DistObject.hpp:293
mgx::DistVertexGraph::DistVertexGraph
DistVertexGraph(DistNhbdT &nhbd, DataT DistNhbdT::VertexContent::*off)
Definition: DistObject.hpp:224
mgx::DistVertex::data
thrust::device_vector< DataT > * data()
Definition: DistObject.hpp:157
mgx::DistEdge::alloc
void alloc()
Definition: DistObject.hpp:306
mgx::DistVertexGraph::vData
DataT * vData(const typename DistNhbdT::Vertex &v)
Definition: DistObject.hpp:228
mgx::DistEdgeGraph::DistEdgeGraph
DistEdgeGraph(DistNhbdT &nhbd, DataT DistNhbdT::EdgeContent::*off)
Definition: DistObject.hpp:382
mgx::AttrMap< typename DistNhbdT::Vertex, ContentT >
mgx::DistNhbd::write
void write()
Definition: DistObject.hpp:87
mgx::map
CU_HOST_DEVICE Vector< dim, T > map(const T &(*fct)(const T1 &), const Vector< dim, T1 > &v)
Definition: Vector.hpp:1380