10 #ifndef ZOLTAN2_DIRECTORY_IMPL_H_
11 #define ZOLTAN2_DIRECTORY_IMPL_H_
22 #define ZOLTAN2_PRINT_INFO(proc,yo,str) \
23 printf("ZOLTAN2 (Processor %d) %s: %s\n", (proc), (yo), \
24 ((str) != NULL ? (char *)(str) : " "));
26 #define ZOLTAN2_TRACE(proc,where,yo,str) \
27 printf("ZOLTAN (Processor %d) %s %s %s\n", (proc), (where), (yo), \
28 ((str) != NULL ? (char *)(str) : " "));
30 #define ZOLTAN2_TRACE_IN(proc,yo,str) \
31 ZOLTAN2_TRACE((proc),"Entering",(yo),(str));
33 #define ZOLTAN2_TRACE_OUT(proc,yo,str) \
34 ZOLTAN2_TRACE((proc),"Exiting",(yo),(str));
38 #define ZOLTAN2_DD_FIND_MSG_TAG 29137
39 #define ZOLTAN2_DD_UPDATE_MSG_TAG 29140
40 #define ZOLTAN2_DD_REMOVE_MSG_TAG 29142
41 #define ZOLTAN2_DD_RESIZE_MSG_TAG 29150
43 template <
typename g
id_t,
typename l
id_t,
typename user_t>
46 const char * yo =
"Zoltan2_Directory::allocate";
48 if (debug_level > 4) {
53 size_t array[3], max_array[3], min_array[3];
54 array[0] =
sizeof(lid_t);
55 array[1] =
sizeof(gid_t);
57 Teuchos::reduceAll<int,size_t>(
58 *comm, Teuchos::REDUCE_MAX, 3, array, max_array);
59 Teuchos::reduceAll<int,size_t>(
60 *comm, Teuchos::REDUCE_MIN, 3, array, min_array);
61 if (max_array[0] != min_array[0] || max_array[1] != min_array[1]
62 || max_array[2] != min_array[2]) {
63 throw std::invalid_argument(
64 "Zoltan2_Directory() LID, GID, USER data lengths differ globally");
71 size_t user_base_size = is_Zoltan2_Directory_Vector() ?
sizeof(size_t) :
75 size_t size =
sizeof(gid_t) + (use_lid?
sizeof(lid_t):0) + user_base_size;
98 max_id_size = std::max(
sizeof(gid_t),
sizeof(lid_t));
100 size = max_id_size + user_base_size;
112 if (debug_level > 4) {
118 template <
typename g
id_t,
typename l
id_t,
typename user_t>
125 template <
typename g
id_t,
typename l
id_t,
typename user_t>
127 size_t count,
const gid_t * gid,
const lid_t * lid,
128 const user_t * user,
const int * partition,
133 this->mode = update_mode;
135 const char * yo =
"Zoltan2_Directory::update";
137 if (debug_level > 4) {
144 for(
size_t n = 0; n < node_map.size(); ++n) {
145 node_map.value_at(n).errcheck = -1;
149 if (debug_level > 6) {
156 Teuchos::ArrayRCP<int> procs;
158 procs = Teuchos::arcp(
new int[count], 0, count,
true);
162 Teuchos::ArrayRCP<int> msg_sizes;
163 int sum_msg_size = 0;
164 if(is_Zoltan2_Directory_Vector() && count > 0) {
165 msg_sizes = Teuchos::arcp(
new int[count], 0, count,
true);
166 for (
size_t i = 0; i < count; i++) {
167 size_t msg_size = get_update_msg_size(user[i]);
168 sum_msg_size += msg_size;
169 msg_sizes[i] = msg_size;
173 sum_msg_size = update_msg_size * count;
176 Teuchos::ArrayRCP<char> sbuff;
178 sbuff = Teuchos::arcp(
new char[sum_msg_size], 0, sum_msg_size,
true);
184 int track_offset = 0;
185 char * trackptr = sbuff.getRawPtr();
186 for (
size_t i = 0; i < count; i++) {
188 procs[i] = hash_proc(gid[i]);
192 msg_t *ptr =
reinterpret_cast<msg_t*
>(trackptr);
195 ptr->lid_flag = lid ? 1 : 0;
196 ptr->user_flag = user ? 1 : 0;
197 ptr->partition_flag = partition ? 1 : 0;
198 ptr->partition = partition ? partition[i] : -1;
199 ptr->owner = comm->getRank();
202 gid_t * pgid = ptr->adjData;
208 throw std::logic_error(
209 "Did not pass lid values but directory was created to use them!");
211 lid_t * plid =
reinterpret_cast<lid_t*
>(ptr->adjData + 1);
216 throw std::logic_error(
217 "Passed lid values but directory was created not to use them!");
223 reinterpret_cast<char*
>(ptr->adjData) +
sizeof(gid_t) +
224 (use_lid?
sizeof(lid_t):0));
230 user_to_raw(user[i], puser);
240 size_t new_update_msg_size =
241 is_Zoltan2_Directory_Vector() ? msg_sizes[i] : update_msg_size;
242 track_offset += new_update_msg_size;
243 trackptr += new_update_msg_size;
248 if(track_offset != sum_msg_size) {
249 throw std::logic_error(
"Bad summing!");
252 if (debug_level > 6) {
261 int nrec = directoryComm.
getNRec();
264 throw std::logic_error(
"Zoltan2_Directory::update() Comm_Create error");
267 if (debug_level > 6) {
271 int sum_recv_sizes = 0;
272 if(is_Zoltan2_Directory_Vector()) {
274 err = directoryComm.
resize(msg_sizes,
278 sum_recv_sizes = update_msg_size * nrec;
282 throw std::logic_error(
"directoryComm.execute_resize error");
289 if(nrec && static_cast<int>(node_map.size()) < nrec) {
295 rehash_node_map(nrec);
299 Teuchos::ArrayRCP<char> rbuff;
300 if(sum_recv_sizes > 0) {
301 rbuff = Teuchos::arcp(
302 new char[sum_recv_sizes], 0, sum_recv_sizes,
true);
307 const int nbytes = is_Zoltan2_Directory_Vector() ? 1 : update_msg_size;
310 sbuff, nbytes, rbuff);
313 throw std::logic_error(
"Zoltan2_Directory::update() Comm_Do error");
316 if (debug_level > 6) {
324 trackptr = rbuff.getRawPtr();
325 for (
int i = 0; i < nrec; i++) {
326 msg_t *ptr =
reinterpret_cast<msg_t*
>(trackptr);
328 user_t * puser = (ptr->user_flag) ?
329 (
user_t*)(
reinterpret_cast<char*
>(ptr->adjData) +
330 sizeof(gid_t) + (use_lid?
sizeof(lid_t):0)) : NULL;
332 err = update_local(ptr->adjData,
333 (ptr->lid_flag) ? reinterpret_cast<lid_t*>(ptr->adjData + 1) : NULL,
335 (ptr->partition_flag) ? (ptr->partition) : -1,
344 size_t delta_msg_size = get_update_msg_size(puser);
345 trackptr += delta_msg_size;
346 track_offset += delta_msg_size;
351 if(track_offset != sum_recv_sizes) {
352 throw std::logic_error(
"Did not sum!");
355 if (debug_level > 6) {
362 err = (errcount) ? 1 : 0;
367 sprintf (str,
"Processed %lu GIDs (%d local), %d GID errors", count,
373 if (debug_level > 4) {
380 template <
typename g
id_t,
typename l
id_t,
typename user_t>
388 const char * yo =
"Zoltan2_Directory::update_local";
392 throw std::logic_error(
393 "Zoltan2_Directory::update_local() owner < 0");
395 if (owner >= comm->getSize()) {
396 throw std::logic_error(
397 "Zoltan2_Directory::update_local() owner >= comm->getSize()");
400 throw std::logic_error(
401 "Zoltan2_Directory::update_local() gid == NULL");
404 if (debug_level > 5) {
409 size_t node_index = node_map.find(*gid);
410 if(node_map.valid_at(node_index)) {
412 node_map.value_at(node_index);
419 update_local_user(user, node.
userData);
423 if (partition != -1) {
476 if (debug_level > 5) {
488 node.
lid = lid ? (*lid) : lid_t();
504 if(node_map.insert(*gid, node).failed()) {
511 size_t new_guess_size = (node_map.size() < 10) ? 10 :
512 ( node_map.size() + node_map.size()/10);
513 rehash_node_map(new_guess_size);
514 if(node_map.insert(*gid, node).failed()) {
515 throw std::logic_error(
"Hash insert failed. Mem sufficient?....");
519 if (debug_level > 6) {
523 if (debug_level > 5) {
530 template <
typename g
id_t,
typename l
id_t,
typename user_t>
538 bool throw_if_missing)
540 const char * yo =
"Zoltan2_Directory::find";
542 if (debug_level > 4) {
549 Teuchos::ArrayRCP<int> procs;
551 procs = Teuchos::arcp(
552 new int[count], 0, count,
true);
556 for (
size_t i = 0; i < count; i++) {
557 procs[i] = hash_proc(gid[i]);
563 int nrec = directoryComm.
getNRec();
565 if (debug_level > 6) {
570 throw std::logic_error(
"Zoltan2_Directory::find() error");
573 Teuchos::ArrayRCP<char> sbuff;
575 sbuff = Teuchos::arcp(
new char[find_msg_size*count],
576 0, find_msg_size*count,
true);
582 char *trackptr = sbuff.getRawPtr();
583 for (
size_t i = 0; i < count; i++) {
584 msg_t *ptr =
reinterpret_cast<msg_t*
>(trackptr);
586 ptr->proc = procs[i];
587 *(ptr->adjData) = gid[i];
588 trackptr += find_msg_size;
591 if (debug_level > 6) {
596 throw std::logic_error(
"directoryComm.execute_resize error");
600 Teuchos::ArrayRCP<char> rbuff;
602 rbuff = Teuchos::arcp(
new char[nrec * find_msg_size],
603 0, nrec * find_msg_size,
true);
606 const int nbytes = find_msg_size;
612 throw std::logic_error(
"Zoltan2_Directory::find() error");
615 if (debug_level > 6) {
621 Teuchos::ArrayRCP<int> rmsg_sizes_resized;
623 rmsg_sizes_resized = Teuchos::arcp(
new int[nrec], 0, nrec,
true);
625 Teuchos::ArrayRCP<int>::size_type sum_rmsg_sizes_resized = 0;
627 char *track_ptr = rbuff.getRawPtr();
628 for (
int i = 0; i < nrec; i++) {
629 msg_t *msg =
reinterpret_cast<msg_t*
>(track_ptr);
630 track_ptr += find_msg_size;
631 size_t find_rmsg_size_resized = get_local_find_msg_size(msg->adjData,
633 rmsg_sizes_resized[i] = find_rmsg_size_resized;
634 sum_rmsg_sizes_resized += find_rmsg_size_resized;
637 Teuchos::ArrayRCP<char>::size_type track_offset_resized = 0;
639 Teuchos::ArrayRCP<char> rbuff_resized_build;
641 if(is_Zoltan2_Directory_Vector()) {
643 if(sum_rmsg_sizes_resized > 0) {
644 rbuff_resized_build = Teuchos::arcp(
new char[sum_rmsg_sizes_resized],
645 0, sum_rmsg_sizes_resized,
true);
648 track_ptr = rbuff.getRawPtr();
649 char * track_ptr_resized = rbuff_resized_build.getRawPtr();
650 for (
int i = 0; i < nrec; i++) {
651 memcpy(track_ptr_resized, track_ptr, find_msg_size);
652 track_ptr += find_msg_size;
653 track_ptr_resized += rmsg_sizes_resized[i];
659 Teuchos::ArrayRCP<char> rbuff_resized = is_Zoltan2_Directory_Vector() ?
660 rbuff_resized_build : rbuff;
663 track_offset_resized = 0;
664 track_ptr = rbuff_resized.getRawPtr();
665 for (
int i = 0; i < nrec; i++) {
667 find_msg_t *ptr =
reinterpret_cast<find_msg_t*
>(track_ptr);
669 reinterpret_cast<char*
>(ptr->adjData) + max_id_size);
675 err = find_local(ptr->adjData, (lid_t*)ptr->adjData,
676 puser, &ptr->partition, &ptr->proc, throw_if_missing);
678 const size_t & size_shift = rmsg_sizes_resized[i];
679 track_offset_resized += size_shift;
680 track_ptr += size_shift;
683 if(track_offset_resized != sum_rmsg_sizes_resized) {
684 throw std::logic_error(
"Bad sum!");
688 size_t size_scale = is_Zoltan2_Directory_Vector() ? 1 : find_msg_size;
690 Teuchos::ArrayRCP<char> sbuff_resized;
691 if(!is_Zoltan2_Directory_Vector()) {
692 sbuff_resized = sbuff;
695 if(is_Zoltan2_Directory_Vector()) {
697 rbuff_resized, size_scale, rmsg_sizes_resized, sbuff_resized);
701 rbuff_resized, size_scale, Teuchos::null, sbuff_resized);
705 throw std::logic_error(
"Zoltan2_Directory::find() do reverse failed");
708 if (debug_level > 6) {
713 track_offset_resized = 0;
716 char * trackptr_resized = sbuff_resized.getRawPtr();
717 for (
size_t i = 0; i < count; i++) {
719 if(track_offset_resized >= sbuff_resized.size()) {
721 "%d has gid.size() %d track_offset_resized: %d sbuff_resized: %d\n",
723 (int) count, (
int) track_offset_resized, (int) sbuff_resized.size());
724 throw std::logic_error(
"Bad buffer overflow! Internal error.");
727 msg_t *ptr =
reinterpret_cast<msg_t*
>(trackptr_resized);
730 owner[ptr->index] = ptr->proc;
732 partition[ptr->index] = ptr->partition ;
734 memcpy (&lid[ptr->index], ptr->adjData,
sizeof(lid_t));
738 reinterpret_cast<char*
>(ptr->adjData) + max_id_size);
746 if(ptr->proc != -1 && user) {
747 raw_to_user(pRead, user[ptr->index]);
752 size_t incoming_size = get_incoming_find_msg_size(ptr);
753 trackptr_resized += incoming_size;
754 track_offset_resized += incoming_size;
757 if(track_offset_resized != sbuff_resized.size()) {
758 throw std::logic_error(
"Bad buffer sum!");
761 if (debug_level > 6) {
766 Teuchos::reduceAll<int>(*comm, Teuchos::REDUCE_SUM, 1, &errcount, &err);
770 if (debug_level > 0) {
772 sprintf(str,
"Processed %lu GIDs, GIDs not found: %d", count, errcount);
776 if (debug_level > 4) {
783 template <
typename g
id_t,
typename l
id_t,
typename user_t>
790 bool throw_if_missing)
const
792 const char * yo =
"Zoltan2_Directory::find_local";
795 if (owner == NULL || gid == NULL) {
796 throw std::logic_error(
"Zoltan2_Directory::find_local() Invalid input");
799 if (debug_level > 5) {
808 size_t node_index = node_map.find(*gid);
809 if(node_map.valid_at(node_index))
812 node_map.value_at(node_index);
822 if (owner) *owner = node.
owner;
823 if (partition) *partition = node.
partition;
825 if (debug_level > 5) {
835 if (debug_level > 5) {
839 if(throw_if_missing) {
842 throw std::logic_error(
"find_local did not succeed");
849 template <
typename g
id_t,
typename l
id_t,
typename user_t>
852 const char * yo =
"Zoltan2_Directory::print";
854 if (debug_level > 4) {
858 for (
size_t i = 0; i < node_map.size(); i++) {
860 node_map.value_at(i);
861 printf (
"ZOLTAN DD Print(%d): \tList, \tGID ", comm->getRank());
874 printf(
"TODO: Decide how to print gid of arbitrary type.");
879 printf(
"TODO: Decide how to print lid of arbitrary type.");
883 printf (
"\tOwner %d\n", node.
owner);
886 if (debug_level > 4) {
893 template <
typename g
id_t,
typename l
id_t,
typename user_t>
896 const char *yo =
"Zoltan2_Directory::stats";
898 if (debug_level > 4) {
905 sprintf(str,
"Kokkos unordered map %d nodes.", node_map.size());
907 if (debug_level > 4) {
912 template <
typename g
id_t,
typename l
id_t,
typename user_t>
917 const char * yo =
"Zoltan2_Directory::remove";
919 if (debug_level > 4) {
926 Teuchos::ArrayRCP<int> procs;
927 Teuchos::ArrayRCP<char> sbuff;
929 procs = Teuchos::arcp(
930 new int[count], 0, count,
true);
931 sbuff = Teuchos::arcp(
932 new char[count*remove_msg_size], 0, count*remove_msg_size,
true);
938 char * trackptr = sbuff.getRawPtr();
939 for (
size_t i = 0; i < count; i++) {
940 procs[i] = hash_proc(gid[i]);
941 msg_t *ptr =
reinterpret_cast<msg_t*
>(trackptr);
942 ptr->owner = comm->getRank();
943 *(ptr->adjData) = gid[i];
944 trackptr += remove_msg_size;
950 int nrec = directoryComm.
getNRec();
953 throw std::logic_error(
"Zoltan_Comm_Create failed");
956 if (debug_level > 6) {
961 Teuchos::ArrayRCP<char> rbuff;
963 rbuff = Teuchos::arcp(
new char[nrec*remove_msg_size],
964 0, nrec*remove_msg_size,
true);
969 sbuff, remove_msg_size, rbuff);
972 throw std::logic_error(
"Comm_Do error");
975 if (debug_level > 6) {
989 node_map.begin_erase();
990 for (
int i = 0; i < nrec; i++) {
991 msg_t *ptr =
reinterpret_cast<msg_t*
>(&(rbuff[i*remove_msg_size]));
992 err = remove_local(ptr->adjData);
997 node_map.end_erase();
1004 sprintf (str,
"Processed %zu GIDs (%d local), %d GIDs not found",
1005 count, nrec, errcount);
1007 err = (errcount) ? 1 : 0;
1013 template <
typename g
id_t,
typename l
id_t,
typename user_t>
1017 const char * yo =
"Zoltan2_Directory::remove_local";
1021 throw std::logic_error(
"Invalid input argument");
1024 if (debug_level > 5) {
1028 if(node_map.exists(*gid)) {
1029 node_map.erase(*gid);
1034 if (debug_level > 5) {
1041 template <
typename g
id_t,
typename l
id_t,
typename user_t>
1043 const gid_t & gid)
const
1049 #define ZOLTAN2_ROTL32(x,r) (uint32_t) \
1050 (((uint32_t)(x) << (int8_t)(r)) | ((uint32_t)(x) >> (32 - (int8_t)(r))))
1052 const void * key = (
void *)(&gid);
1053 int len =
sizeof(gid_t);
1055 void * out = (
void *)&k;
1057 const uint8_t * data = (
const uint8_t*)key;
1058 const int nblocks = len / 4;
1061 uint32_t c1 = 0xcc9e2d51;
1062 uint32_t c2 = 0x1b873593;
1063 const uint32_t * blocks = (
const uint32_t *)(data + nblocks*4);
1064 for(i = -nblocks; i; i++)
1066 uint32_t k1 = blocks[i];
1072 h1 = h1*5+0xe6546b64;
1074 const uint8_t * tail = (
const uint8_t*)(data + nblocks*4);
1078 case 3: k1 ^= tail[2] << 16;
1079 case 2: k1 ^= tail[1] << 8;
1080 case 1: k1 ^= tail[0];
1089 *(uint32_t*)out = h1;
1091 return(k % comm->getSize());
1109 #endif // ZOLTAN2_DIRECTORY_IMPL_H_
#define ZOLTAN2_DD_FIND_MSG_TAG
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.
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.
void stats() const
stats. New Kokkos mode needs further development.
#define ZOLTAN2_DD_UPDATE_MSG_TAG
int remove_local(gid_t *gid)
int print() const
gids to remove.
int copy(const Zoltan2_Directory< gid_t, lid_t, user_t > &dd)
int do_reverse(int tag, const Teuchos::ArrayRCP< char > &send_data, int nbytes, const Teuchos::ArrayRCP< int > &sizes, Teuchos::ArrayRCP< char > &recv_data)
int update_local(gid_t *gid, lid_t *lid, user_t *user, int partition, int owner)
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...
Update_Mode
Update_Mode determines how update executes.
unsigned int hash_proc(const gid_t &gid) const
int find_local(gid_t *gid, lid_t *lid, user_t *user, int *partition, int *owner, bool throw_if_missing=true) const
#define ZOLTAN2_ROTL32(x, r)
#define ZOLTAN2_TRACE_OUT(proc, yo, str)
int do_forward(int tag, const Teuchos::ArrayRCP< char > &send_data, int nbytes, Teuchos::ArrayRCP< char > &recv_data)
int resize(const Teuchos::ArrayRCP< int > &sizes, int tag, int *sum_recv_sizes)
#define ZOLTAN2_DD_RESIZE_MSG_TAG
#define ZOLTAN2_TRACE_IN(proc, yo, str)
Zoltan2_Directory is an abstract base class.
#define ZOLTAN2_PRINT_INFO(proc, yo, str)
Zoltan2::BasicUserTypes< zscalar_t, zlno_t, zgno_t > user_t