Zoltan2
Loading...
Searching...
No Matches
Zoltan2_Directory.hpp
Go to the documentation of this file.
1/*
2 * @HEADER
3 *
4 * ***********************************************************************
5 *
6 * Zoltan2 Directory for Load-balancing, Partitioning, Ordering and Coloring
7 * Copyright 2012 Sandia Corporation
8 *
9 * Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
10 * the U.S. Government retains certain rights in this software.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are
14 * met:
15 *
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 *
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 *
23 * 3. Neither the name of the Corporation nor the names of the
24 * contributors may be used to endorse or promote products derived from
25 * this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
28 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
31 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 *
39 * Questions? Contact Karen Devine kddevin@sandia.gov
40 * Erik Boman egboman@sandia.gov
41 *
42 * ***********************************************************************
43 *
44 * @HEADER
45 */
46
47#ifndef ZOLTAN2_DIRECTORY_H_
48#define ZOLTAN2_DIRECTORY_H_
49
50#include <Teuchos_DefaultComm.hpp> // currently using Teuchos comm throughout
51#include <Teuchos_CommHelpers.hpp>
52
53#ifndef HAVE_MPI
54// support mpi serial - directory currently has a mix of Teuchos mpi commands
55// and original MPI commands so as this gets better organized the serial support
56// can be handled more naturally. Currently the tests call an MPI_Init for serial
57// so this can all work. I've mostly added the serial support just to make
58// debugging easier.
59#include <mpi.h>
60#endif
61
62#include <Kokkos_UnorderedMap.hpp> // unordered map stores the local nodes
63
64namespace Zoltan2 {
65
66// The new Kokkos mode maps over the gid using unordered map
67// Originally was thinking we don't want ptrs here and want the user data
68// to be a natural type so it can cleanly support std::vector. However as this
69// evolved I am not sure this is the best decision and can be more costly for
70// memory. Now that all the unit testing is in place it would be easier to
71// refactor this back to the original packed ptr style if necessary.
72template <typename gid_t, typename lid_t, typename user_t>
74 public:
75 // TODO: This free is an outstanding issue - follows original format and
76 // allows me to search the Kokkos::UnorderedMap by index and distinguish
77 // between empty slots and filled. But I am not quite understanding this
78 // and is there a way to search the filled slots without referring to the
79 // keys.
81 int owner; /* processor hosting global ID object */
82 int partition; /* Optional data */
83 int errcheck; /* Error checking(inconsistent updates) */
84 lid_t lid; /* lid value */
85 user_t userData; /* user data */
86 int free; /* flag whether node is free or used */
87};
88
89// TODO: These message structures should become MPI datatypes(KDD)
90// Currently these are implemented as they were in the original zoltan code.
91template <typename gid_t, typename lid_t>
92class Zoltan2_DD_Update_Msg { /* Only used by Zoltan_DD_Update() */
93 public:
94 char lid_flag; /* indicates if LID data are present */
95 char user_flag; /* indicates if USER data are present */
96 char partition_flag; /* indicates if optional partition data */
97 int owner; /* range [0, nproc-1] or -1 */
99 gid_t adjData[1]; /* TODO: refactor - includes gid & lid & user */
100};
101
102template <typename gid_t, typename lid_t>
103class Zoltan2_DD_Find_Msg { /* Only used by Zoltan_DD_Find() */
104 public:
105 int proc; /* destination or location */
107 int index; /* to put things back in order afterward */
108 gid_t adjData[1]; /* TODO: refactor - includes gid and user */
109};
110
111template <typename gid_t, typename lid_t>
112class Zoltan2_DD_Remove_Msg { /* Only used by Zoltan_DD_Remove() */
113 public:
114 int owner; /* range [0, nproc-1] or -1 */
115 gid_t adjData[1]; /* TODO: refactor - includes gid */
116};
117
124template <typename gid_t, typename lid_t, typename user_t>
126 public:
141
144 Teuchos::RCP<const Teuchos::Comm<int> > comm_,
146 bool use_lid_,
147 int debug_level_)
148 : comm(comm_), use_lid(use_lid_),
149 debug_level(debug_level_)
150 {
151 }
152
155 }
156
158 int update(
159 size_t length, /* number of gids */
160 const gid_t * gid,
161 const lid_t * lid,
162 const user_t * user,
163 const int * partition,
164 Update_Mode update_mode);
167 int find(
168 size_t length, /* number of gids */
169 const gid_t * gid,
170 lid_t * lid,
171 user_t * user,
172 int * partition,
173 int * owner,
174 bool throw_if_missing = true);
179 int remove(
180 size_t length, /* number of gids */
181 const gid_t * gid);
184 int print() const;
185
187 void stats() const;
188
190 bool is_use_lid() const { return use_lid; }
191
192 void get_locally_managed_gids(std::vector<gid_t> & local_gids) const {
193 // resize
194 local_gids.resize(node_map.size());
195
196 // fill
197 size_t cnt = 0;
198 for(size_t n = 0; n < node_map.capacity(); ++n) {
199 if(node_map.value_at(n).free == 0) {
200 local_gids[cnt++] = node_map.key_at(n);
201 }
202 }
203
204 if(cnt != node_map.size()) {
205 throw std::logic_error("Unexpected counts. Internal error with the"
206 " node_map behavior.");
207 }
208 }
209
211 // This process follows the pattern of the original unique ids setup
212 // It assumes we have updated the directory with keys (as the gid_t) and
213 // also created empty user data. Each key is converted to a unique integer
214 // and written into the user data.
215 typedef long long mpi_t;
216 mpi_t nDDEntries = static_cast<mpi_t>(node_map.size());
217 mpi_t firstIdx;
218 Teuchos::scan(*comm, Teuchos::REDUCE_SUM,
219 1, &nDDEntries, &firstIdx);
220 firstIdx -= nDDEntries; // do not include this rank's entries in prefix sum
221 size_t cnt = 0;
222 for(size_t n = 0; n < node_map.capacity(); ++n) {
223 if(node_map.value_at(n).free == 0) {
224 Zoltan2_Directory_Node<gid_t,lid_t,user_t> & node =
225 node_map.value_at(n);
226 node.userData = firstIdx + cnt;
227 cnt++;
228 }
229 }
230 }
231
232 size_t node_map_size() const {
233 return node_map.size();
234 }
235
236 protected:
237 // handled updating the local node information when the proc receives
238 // a new gid to store or updated data for a preexisting node
239 int update_local(gid_t* gid, lid_t* lid, user_t *user,
240 int partition, int owner);
241
242 // collect data on the local proc which has been requested by the directory.
243 int find_local(gid_t* gid, lid_t* lid, user_t *user,
244 int *partition, int *owner, bool throw_if_missing = true) const;
245
246 // remove the locally stored node for this gid
247 int remove_local(gid_t* gid);
248
249 size_t find_msg_size; /* Total allocation for Zoltan2_DD_FindMsg */
250 size_t update_msg_size; /* Total allocation for Zoltan2_DD_Update_Msg */
251 size_t remove_msg_size; /* Total allocation for Zoltan2_DD_Remove_Msg */
252
253 // originally the nodes are stored in a hash but in the new Kokkos mode
254 // they are stored using Kokkos::UnorderedMap
255 typedef Kokkos::UnorderedMap<gid_t,
256 Zoltan2_Directory_Node<gid_t,lid_t,user_t>, Kokkos::HostSpace> node_map_t;
258
259 // this method exists so constructor and copy constructor don't duplicate
260 void allocate();
261
262 // this method exists so operator= and copy constructor don't duplicate
263 int copy(const Zoltan2_Directory<gid_t,lid_t,user_t> &dd);
264
265 // TODO: Decide if this stays and how to incorporate with variable length
266 // data. See comments in Zoltan2_Directory_Impl.hpp
267 // size_t align_size_t(size_t a) const;
268
269 // take a gid and hash to proc - determines which proc wil own the gid data
270 unsigned int hash_proc(const gid_t & gid) const;
271
272 // stores the comm provided by the user
273 Teuchos::RCP<const Teuchos::Comm<int> > comm;
274
275 bool use_lid; /* If false not using lid */
276 int debug_level; /* Determines actions to multiple updates */
277
278 size_t max_id_size; /* Stores: max(sizeof(gid_t),sizeof(lid_t)) */
279 Update_Mode mode; /* Last mode sent using update */
280
281 // abstract methods are implemented below by Zoltan2_Directory_Simple
282 // or Zoltan2_Directory_Vector. These methods contain all the places where
283 // the code had to be specialized for normal user type (int, long, etc) or
284 // std::vector user type of variable length. Possibly we could consider
285 // making this all work by templating but exactly how to do that cleanly
286 // I am not sure. The class inheritance approach may be easier to understand
287 // but it does mean the user has to pick the right class to use.
288 virtual bool is_Zoltan2_Directory_Vector() const { return false; };
289 virtual void update_local_user(const user_t * pRaw, user_t & dst) {};
290 virtual void user_to_raw(const user_t & src, user_t * pRaw) const {};
291 virtual void raw_to_user(const user_t * pRaw, user_t & dst) const {};
292 virtual size_t size_of_value_type() const { return 0; };
293 virtual size_t get_update_msg_size(const user_t & data) const { return 0; };
294 virtual size_t get_update_msg_size(const user_t * pRaw) const { return 0; };
295 virtual size_t get_local_find_msg_size(gid_t *gid,
296 bool throw_if_missing = true) const { return 0; };
298 Zoltan2_DD_Find_Msg<gid_t,lid_t>* msg) const { return 0; };
299
300 private:
301 void rehash_node_map(size_t new_hash_size) {
302 node_map.rehash(new_hash_size);
303 }
304};
305
306template <typename gid_t, typename lid_t, typename user_t>
307class Zoltan2_Directory_Simple : public Zoltan2_Directory<gid_t, lid_t, user_t> {
308 public:
310
312 Zoltan2_Directory_Simple(Teuchos::RCP<const Teuchos::Comm<int> > comm_, bool use_lid_,
313 int debug_level_) :
314 Zoltan2_Directory<gid_t, lid_t, user_t>(comm_, use_lid_,
315 debug_level_) {
316 // Note that allocate() must be called in the derived class, not the
317 // base class or inheritance of the methods will break
318 this->allocate();
319 }
320
323 const Zoltan2_Directory_Simple<gid_t,lid_t,user_t> &src) :
324 Zoltan2_Directory<gid_t, lid_t, user_t>(src.comm, src.use_lid,
325 src.debug_level) {
326 this->allocate();
327 this->copy(src);
328 }
329
331 Zoltan2_Directory_Simple<gid_t,lid_t,user_t> & operator=
332 (const Zoltan2_Directory_Simple<gid_t,lid_t,user_t> &src) {
333 this->comm = src.comm;
334 this->use_lid = src.use_lid;
335 this->debug_level = src.debug_level;
336 this->allocate(); // operator= was setup in derived class so this inherits
337 this->copy(src);
338 return *this;
339 }
340
341 protected:
342 // awkward to have this at all - so maybe to refactor out with future progress
343 virtual bool is_Zoltan2_Directory_Vector() const { return false; }
344
345 // given raw data from the MPI stream we update user data based on mode
346 virtual void update_local_user(const user_t * pRaw, user_t & dst) {
347 switch(this->mode) {
349 dst = *pRaw;
350 break;
352 dst += *pRaw;
353 break;
355 throw std::logic_error("Aggregate doesn't mean anything for single "
356 "types. Must use Zoltan2_Directory_Vector class.");
358 throw std::logic_error("AggregateAdd doesn't mean anything for single "
359 "types. Must use Zoltan2_Directory_Vector class.");
360 }
361 }
362
363 // convert user data to raw data - simple conversion for this class
364 virtual void user_to_raw(const user_t & src, user_t * pRaw) const {
365 *pRaw = src;
366 }
367
368 // convert raw data to user data - simple conversion for this class
369 virtual void raw_to_user(const user_t * pRaw, user_t & dst) const {
370 dst = *pRaw;
371 }
372
373 // get size of the user type which is simply sizeof(user_t) for this class
374 virtual size_t size_of_value_type() const { return sizeof(user_t); }
375
376 // for this class, update_msg_size is simple (not variable length)
377 virtual size_t get_update_msg_size(const user_t & data) const {
378 return this->update_msg_size;
379 }
380
381 // for this class, update_msg_size is simple (not variable length)
382 virtual size_t get_update_msg_size(const user_t * pRaw) const {
383 return this->update_msg_size;
384 }
385
386 // for this class, find_msg_size is simple (not variable length)
387 virtual size_t get_local_find_msg_size(gid_t *gid,
388 bool throw_if_missing = true) const {
389 return this->find_msg_size;
390 }
391
392 // for this class, find_msg_size is simple (not variable length)
394 Zoltan2_DD_Find_Msg<gid_t,lid_t>* msg) const {
395 return this->find_msg_size;
396 }
397};
398
399template <typename gid_t, typename lid_t, typename user_t>
400class Zoltan2_Directory_Vector : public Zoltan2_Directory<gid_t, lid_t, user_t> {
401 public:
402 typedef typename user_t::value_type user_val_t;
403
405 Zoltan2_Directory_Vector(Teuchos::RCP<const Teuchos::Comm<int> > comm_, bool use_lid_,
406 int debug_level_) :
407 Zoltan2_Directory<gid_t, lid_t, user_t>(comm_, use_lid_,
408 debug_level_) {
409 // Note that allocate() must be called in the derived class, not the
410 // base class or inheritance of the methods will break
411 this->allocate();
412 }
413
416 const Zoltan2_Directory_Vector<gid_t,lid_t,user_t> &src) :
417 Zoltan2_Directory<gid_t, lid_t, user_t>(src.comm, src.use_lid,
418 src.debug_level) {
419 this->allocate(); // operator= was setup in derived class so this inherits
420 this->copy(src);
421 }
422
424 Zoltan2_Directory_Vector<gid_t,lid_t,user_t> & operator=
425 (const Zoltan2_Directory_Vector<gid_t,lid_t,user_t> &src) {
426 this->comm = src.comm;
427 this->use_lid = src.use_lid;
428 this->debug_level = src.debug_level;
429 this->allocate(); // operator= was setup in derived class so this inherits
430 this->copy(src);
431 return *this;
432 }
433
434 protected:
435 // awkward to have this at all - so maybe to refactor out with future progress
436 virtual bool is_Zoltan2_Directory_Vector() const { return true; }
437
438 // given raw data from the MPI stream we update user data based on mode
439 virtual void update_local_user(const user_t * pRaw, user_t & dst) {
440 // we're reading raw data of form: size_t, val, val, val ...
441 size_t * pLength = (size_t*)(pRaw);
442 size_t read_array_length = *pLength;
443 ++pLength; // move up to first element
444 user_val_t * pRead = (user_val_t*)(pLength);
445 switch(this->mode) {
447 // Note this is the raw_to_user method and we could just call it
448 // but Add and Aggregate don't have the equivalent so I've done it
449 // this way to keep the pattern.
450 dst.resize(read_array_length); // change to new
451 for(size_t i = 0; i < read_array_length; ++i) {
452 dst[i] = *pRead;
453 ++pRead;
454 }
455 }
456 break;
458 // ADD currently requires equal length vectors to add each element
459 if(dst.size() != static_cast<size_t>(read_array_length)) {
460 throw std::logic_error("The data lengths are not the same size");
461 }
462 // loop through and do the addition
463 for(size_t i = 0; i < dst.size(); ++i) {
464 dst[i] += *pRead;
465 ++pRead;
466 }
467 }
468 break;
470 // Add only unique elements
471 // Preserve ordering
472 // First scan the new incoming data
473 //
474 // For example we can have data of:
475 // [1,4,5,7]
476 // Then new incoming data is:
477 // [4,5,6,10]
478 // Then result would be:
479 // [1,4,5,6,7,10]
480 for(size_t i = 0; i < read_array_length; ++i) {
481 // handle the cases of dst no size or adding past last element
482 if(dst.size() == 0 || (*pRead) > dst[dst.size()-1]) {
483 dst.push_back(*pRead); // add first element or at end
484 }
485 else {
486 // otherwise we are going to insert unless it's not unique
487 for(auto itr = dst.begin(); itr != dst.end(); ++itr) {
488 if((*itr) == (*pRead)) { // do they match
489 if(this->mode == Zoltan2_Directory<gid_t,lid_t,user_t>::
491 (*itr) += (*pRead); // do the AggregateAdd action using +=
492 }
493 break; // break because it's already in there - do nothing
494 }
495 else if((*itr) > (*pRead)) { // is scanned element larger?
496 dst.insert(itr, (*pRead)); // preserve ordering
497 break; // break because once we add it we are done
498 }
499 }
500 }
501 ++pRead; // get the next incoming array element (*pRead)
502 }
503 }
504 break;
506 // AggregateAdd is similar to Aggregate except that when two items
507 // match through the operator==, they are combined using operator+=
508 // instead of excluding the duplicate. This reliance on operator==
509 // and operator+= allows the user to define the behavior for the
510 // struct but needs design discussion. This example struct was taken
511 // from Zoltan2_GraphMetricsUtility.hpp which was the origina reason
512 // for adding this mode.
513 /*
514 struct part_info {
515 part_info() : sum_weights(0) {
516 }
517 const part_info & operator+=(const part_info & src) {
518 sum_weights += src.sum_weights;
519 return *this; // return old value
520 }
521 bool operator>(const part_info & src) {
522 return (target_part > src.target_part);
523 }
524 bool operator==(const part_info & src) {
525 return (target_part == src.target_part);
526 }
527 part_t target_part; // the part this part_info refers to
528 t_scalar_t sum_weights; // the sum of weights
529 };
530 */
531 // Then if we use AggregateAdd the following example shows how the
532 // struct with part_t 1 will have sum_weights combined:
533 //
534 // Proc 1 Proc 2 Result
535 // part_t 0 1 1 3 0 1 3
536 // sum_weights 1.0 1.0 2.0 2.0 1.0 3.0 2.0
537 //
538 // TODO: We could make this almost identical to above Aggregate and
539 // preserve ordering. Then the only difference is that Aggregate just
540 // does nothing when two elements are the same while AggregateAdd will
541 // combine them with += operator. Did not implement yet since
542 // Zoltan2_GraphMetricsUtility.hpp didn't have parts ordered and I
543 // wasn't sure yet if we'd want to make that a requirement.
544 for(size_t i = 0; i < read_array_length; ++i) {
545 bool bMatch = false;
546 for(auto itr = dst.begin(); itr != dst.end(); ++itr) {
547 if((*itr) == (*pRead)) { // determine if they go together using ==
548 (*itr) += (*pRead); // do the AggregateAdd action using +=
549 bMatch = true;
550 break;
551 }
552 }
553 if(!bMatch) {
554 dst.push_back(*pRead); // add first element or at end
555 }
556 ++pRead; // get the next incoming array element (*pRead)
557 }
558 }
559 break;
560
561 }
562 }
563
564 // write the std::vector as length, x1, x2, x3 ...
565 virtual void user_to_raw(const user_t & src, user_t * pRaw) const {
566 // we're writing raw data of form: size_t, val, val, val ...
567 size_t *pLength = (size_t*)(pRaw);
568 *pLength = src.size(); // first write the length
569 ++pLength; // move up to first element
570 user_val_t *pWrite = (user_val_t*)(pLength);
571 for(size_t n = 0; n < src.size(); ++n) {
572 *pWrite = src[n]; // now write each element
573 ++pWrite;
574 }
575 }
576
577 // raw comes in as length, x1, x2, x3 ...
578 virtual void raw_to_user(const user_t * pRaw, user_t & dst) const {
579 // we're reading raw of form: size_t, val, val, val ...
580 size_t* pLength = (size_t*) pRaw;
581 dst.resize(static_cast<size_t>(*pLength)); // first read the length
582 ++pLength; // move up to first element
583 user_val_t* pRead = (user_val_t*) pLength;
584 for(size_t n = 0; n < dst.size(); ++n) {
585 dst[n] = *pRead; // now read each element
586 ++pRead;
587 }
588 }
589
590 // for the std::vector directory, value type is the size of the std::vector
591 // template parameter, so for std::vector<int> we want sizeof(int)(
592 virtual size_t size_of_value_type() const {
593 return sizeof(typename user_t::value_type);
594 }
595
596 // the update msg is the base size (includes vector length) plus the size
597 // of all the elements.
598 virtual size_t get_update_msg_size(const user_t & data) const {
599 return this->update_msg_size + data.size() * size_of_value_type();
600 }
601
602 // the update msg is the base size (includes vector length) plus the size
603 // of all the elements. This is same idea as above method but here we are
604 // intepreting raw data (which comes in as length, x1, x2, x3...) so we
605 // read the size as the first element. That's all we need to determine the
606 // total update_msg_size.
607 virtual size_t get_update_msg_size(const user_t * pRaw) const {
608 // the first element is size_t (length of the vector)
609 size_t * pLength = (size_t*) (pRaw);
610 return this->update_msg_size +
611 (pRaw ? ((*pLength) * size_of_value_type()) : 0);
612 }
613
614 // to get the local find msg size we need to verify the node exists and then
615 // read the std::vector size (which is added to base length find_msg_size.
616 virtual size_t get_local_find_msg_size(gid_t * gid,
617 bool throw_if_missing = true) const {
618 if(this->node_map.exists(*gid)) {
619 const Zoltan2_Directory_Node<gid_t,lid_t,user_t> & node =
620 this->node_map.value_at(this->node_map.find(*gid));
621 return this->find_msg_size + node.userData.size() * sizeof(user_val_t);
622 }
623 else if(throw_if_missing) {
624 throw std::logic_error( "Could not find gid in map." );
625 }
626 else {
627 // not clear yet if we ever want to handle this case or always err out
628 // I'm using this right now for the unit testing to validate that the
629 // remove command actually works.
630 return this->find_msg_size; // will not have any data content
631 }
632 }
633
634 // here we have a find msg coming in and we need to extract the vector length
635 // which is always at the same place in the message.
637 Zoltan2_DD_Find_Msg<gid_t,lid_t>* msg) const {
638 if(msg->proc == -1) {
639 // this happens if we called find for an element which was removed
640 // eventually we might just throw on find_local but for the testing,
641 // this is allowed, the data is left untouched, and the test validates
642 // that the results are as expected based on remove events
643 return this->find_msg_size; // no extra data for unfound node
644 }
645 // the first element of the user data is size_t (length of the vector)
646 size_t * pVectorLength =
647 (size_t*)(reinterpret_cast<char*>(msg->adjData) + this->max_id_size);
648 return this->find_msg_size + (*pVectorLength) * sizeof(user_val_t);
649 }
650};
651
652} // end namespace Zoltan2
653
654#endif
Zoltan2::BasicUserTypes< zscalar_t, zlno_t, zgno_t > user_t
Definition Metric.cpp:74
Zoltan2_Directory_Simple(const Zoltan2_Directory_Simple< gid_t, lid_t, user_t > &src)
Copy constructor.
virtual size_t get_update_msg_size(const user_t *pRaw) const
virtual void update_local_user(const user_t *pRaw, user_t &dst)
Zoltan2_Directory_Simple(Teuchos::RCP< const Teuchos::Comm< int > > comm_, bool use_lid_, int debug_level_)
Constructo directory which handles simple user data types.
virtual void raw_to_user(const user_t *pRaw, user_t &dst) const
virtual size_t get_local_find_msg_size(gid_t *gid, bool throw_if_missing=true) const
virtual bool is_Zoltan2_Directory_Vector() const
virtual size_t size_of_value_type() const
virtual size_t get_update_msg_size(const user_t &data) const
virtual void user_to_raw(const user_t &src, user_t *pRaw) const
virtual size_t get_incoming_find_msg_size(Zoltan2_DD_Find_Msg< gid_t, lid_t > *msg) const
Zoltan2_Directory_Vector(const Zoltan2_Directory_Vector< gid_t, lid_t, user_t > &src)
Copy constructor.
virtual void update_local_user(const user_t *pRaw, user_t &dst)
virtual size_t get_incoming_find_msg_size(Zoltan2_DD_Find_Msg< gid_t, lid_t > *msg) const
Zoltan2_Directory_Vector(Teuchos::RCP< const Teuchos::Comm< int > > comm_, bool use_lid_, int debug_level_)
Constructo directory which handles std::vector user data types.
virtual size_t get_update_msg_size(const user_t &data) const
virtual void raw_to_user(const user_t *pRaw, user_t &dst) const
virtual size_t get_local_find_msg_size(gid_t *gid, bool throw_if_missing=true) const
virtual size_t size_of_value_type() const
virtual void user_to_raw(const user_t &src, user_t *pRaw) const
virtual size_t get_update_msg_size(const user_t *pRaw) const
virtual bool is_Zoltan2_Directory_Vector() const
Zoltan2_Directory is an abstract base class.
Update_Mode
Update_Mode determines how update executes.
@ Aggregate
For std::vector user data, aggregates all data so for example [1,2,5] and [3,5] becomes [1,...
@ AggregateAdd
In progress and needs discussion. Currently this mode will use operator== to determine if two items m...
@ Add
All values from different procs are summed.
@ Replace
The new value replaces the original value.
virtual size_t get_local_find_msg_size(gid_t *gid, bool throw_if_missing=true) const
Zoltan2_Directory(Teuchos::RCP< const Teuchos::Comm< int > > comm_, bool use_lid_, int debug_level_)
Construct Zoltan2_Directory (abstract class).
virtual bool is_Zoltan2_Directory_Vector() const
Kokkos::UnorderedMap< gid_t, Zoltan2_Directory_Node< gid_t, lid_t, user_t >, Kokkos::HostSpace > node_map_t
virtual size_t size_of_value_type() const
virtual void update_local_user(const user_t *pRaw, user_t &dst)
virtual size_t get_update_msg_size(const user_t &data) const
virtual void user_to_raw(const user_t &src, user_t *pRaw) const
int update_local(gid_t *gid, lid_t *lid, user_t *user, int partition, int owner)
virtual size_t get_incoming_find_msg_size(Zoltan2_DD_Find_Msg< gid_t, lid_t > *msg) const
Teuchos::RCP< const Teuchos::Comm< int > > comm
virtual ~Zoltan2_Directory()
Destructor currently does nothing.
bool is_use_lid() const
returns true if the directory is handling local ids.
virtual size_t get_update_msg_size(const user_t *pRaw) const
int print() const
gids to remove.
int remove(size_t length, const gid_t *gid)
if true will throw if a gid is not found. This is used by the unit tests to properly assess if remove...
int update(size_t length, const gid_t *gid, const lid_t *lid, const user_t *user, const int *partition, Update_Mode update_mode)
update is called by user to submit new data.
virtual void raw_to_user(const user_t *pRaw, user_t &dst) const
int copy(const Zoltan2_Directory< gid_t, lid_t, user_t > &dd)
int find_local(gid_t *gid, lid_t *lid, user_t *user, int *partition, int *owner, bool throw_if_missing=true) const
void get_locally_managed_gids(std::vector< gid_t > &local_gids) const
void stats() const
stats. New Kokkos mode needs further development.
unsigned int hash_proc(const gid_t &gid) const
int find(size_t length, const gid_t *gid, lid_t *lid, user_t *user, int *partition, int *owner, bool throw_if_missing=true)
Can be Replace, Add, or Aggregate.
Created by mbenlioglu on Aug 31, 2020.