47 #ifndef ZOLTAN2_DIRECTORY_IMPL_H_
48 #define ZOLTAN2_DIRECTORY_IMPL_H_
59 #define ZOLTAN2_PRINT_INFO(proc,yo,str) \
60 printf("ZOLTAN2 (Processor %d) %s: %s\n", (proc), (yo), \
61 ((str) != NULL ? (char *)(str) : " "));
63 #define ZOLTAN2_TRACE(proc,where,yo,str) \
64 printf("ZOLTAN (Processor %d) %s %s %s\n", (proc), (where), (yo), \
65 ((str) != NULL ? (char *)(str) : " "));
67 #define ZOLTAN2_TRACE_IN(proc,yo,str) \
68 ZOLTAN2_TRACE((proc),"Entering",(yo),(str));
70 #define ZOLTAN2_TRACE_OUT(proc,yo,str) \
71 ZOLTAN2_TRACE((proc),"Exiting",(yo),(str));
75 #define ZOLTAN2_DD_FIND_MSG_TAG 29137
76 #define ZOLTAN2_DD_UPDATE_MSG_TAG 29140
77 #define ZOLTAN2_DD_REMOVE_MSG_TAG 29142
78 #define ZOLTAN2_DD_RESIZE_MSG_TAG 29150
80 template <
typename g
id_t,
typename l
id_t,
typename user_t>
83 const char * yo =
"Zoltan2_Directory::allocate";
85 if (debug_level > 4) {
90 size_t array[3], max_array[3], min_array[3];
91 array[0] =
sizeof(lid_t);
92 array[1] =
sizeof(gid_t);
94 Teuchos::reduceAll<int,size_t>(
95 *comm, Teuchos::REDUCE_MAX, 3, array, max_array);
96 Teuchos::reduceAll<int,size_t>(
97 *comm, Teuchos::REDUCE_MIN, 3, array, min_array);
98 if (max_array[0] != min_array[0] || max_array[1] != min_array[1]
99 || max_array[2] != min_array[2]) {
100 throw std::invalid_argument(
101 "Zoltan2_Directory() LID, GID, USER data lengths differ globally");
108 size_t user_base_size = is_Zoltan2_Directory_Vector() ?
sizeof(size_t) :
109 size_of_value_type();
112 size_t size =
sizeof(gid_t) + (use_lid?
sizeof(lid_t):0) + user_base_size;
118 size =
sizeof(gid_t);
135 max_id_size = std::max(
sizeof(gid_t),
sizeof(lid_t));
137 size = max_id_size + user_base_size;
149 if (debug_level > 4) {
155 template <
typename g
id_t,
typename l
id_t,
typename user_t>
162 template <
typename g
id_t,
typename l
id_t,
typename user_t>
164 size_t count,
const gid_t * gid,
const lid_t * lid,
165 const user_t * user,
const int * partition,
170 this->mode = update_mode;
172 const char * yo =
"Zoltan2_Directory::update";
174 if (debug_level > 4) {
181 for(
size_t n = 0; n < node_map.size(); ++n) {
182 node_map.value_at(n).errcheck = -1;
186 if (debug_level > 6) {
193 Teuchos::ArrayRCP<int> procs;
195 procs = Teuchos::arcp(
new int[count], 0, count,
true);
199 Teuchos::ArrayRCP<int> msg_sizes;
200 int sum_msg_size = 0;
201 if(is_Zoltan2_Directory_Vector() && count > 0) {
202 msg_sizes = Teuchos::arcp(
new int[count], 0, count,
true);
203 for (
size_t i = 0; i < count; i++) {
204 size_t msg_size = get_update_msg_size(user[i]);
205 sum_msg_size += msg_size;
206 msg_sizes[i] = msg_size;
210 sum_msg_size = update_msg_size * count;
213 Teuchos::ArrayRCP<char> sbuff;
215 sbuff = Teuchos::arcp(
new char[sum_msg_size], 0, sum_msg_size,
true);
221 int track_offset = 0;
222 char * trackptr = sbuff.getRawPtr();
223 for (
size_t i = 0; i < count; i++) {
225 procs[i] = hash_proc(gid[i]);
229 msg_t *ptr =
reinterpret_cast<msg_t*
>(trackptr);
232 ptr->lid_flag = lid ? 1 : 0;
233 ptr->user_flag = user ? 1 : 0;
234 ptr->partition_flag = partition ? 1 : 0;
235 ptr->partition = partition ? partition[i] : -1;
236 ptr->owner = comm->getRank();
239 gid_t * pgid = ptr->adjData;
245 throw std::logic_error(
246 "Did not pass lid values but directory was created to use them!");
248 lid_t * plid =
reinterpret_cast<lid_t*
>(ptr->adjData + 1);
253 throw std::logic_error(
254 "Passed lid values but directory was created not to use them!");
260 reinterpret_cast<char*
>(ptr->adjData) +
sizeof(gid_t) +
261 (use_lid?
sizeof(lid_t):0));
267 user_to_raw(user[i], puser);
277 size_t new_update_msg_size =
278 is_Zoltan2_Directory_Vector() ? msg_sizes[i] : update_msg_size;
279 track_offset += new_update_msg_size;
280 trackptr += new_update_msg_size;
285 if(track_offset != sum_msg_size) {
286 throw std::logic_error(
"Bad summing!");
289 if (debug_level > 6) {
298 int nrec = directoryComm.
getNRec();
301 throw std::logic_error(
"Zoltan2_Directory::update() Comm_Create error");
304 if (debug_level > 6) {
308 int sum_recv_sizes = 0;
309 if(is_Zoltan2_Directory_Vector()) {
311 err = directoryComm.
resize(msg_sizes,
315 sum_recv_sizes = update_msg_size * nrec;
319 throw std::logic_error(
"directoryComm.execute_resize error");
326 if(nrec && static_cast<int>(node_map.size()) < nrec) {
332 rehash_node_map(nrec);
336 Teuchos::ArrayRCP<char> rbuff;
337 if(sum_recv_sizes > 0) {
338 rbuff = Teuchos::arcp(
339 new char[sum_recv_sizes], 0, sum_recv_sizes,
true);
344 const int nbytes = is_Zoltan2_Directory_Vector() ? 1 : update_msg_size;
347 sbuff, nbytes, rbuff);
350 throw std::logic_error(
"Zoltan2_Directory::update() Comm_Do error");
353 if (debug_level > 6) {
361 trackptr = rbuff.getRawPtr();
362 for (
int i = 0; i < nrec; i++) {
363 msg_t *ptr =
reinterpret_cast<msg_t*
>(trackptr);
365 user_t * puser = (ptr->user_flag) ?
366 (
user_t*)(
reinterpret_cast<char*
>(ptr->adjData) +
367 sizeof(gid_t) + (use_lid?
sizeof(lid_t):0)) : NULL;
369 err = update_local(ptr->adjData,
370 (ptr->lid_flag) ? reinterpret_cast<lid_t*>(ptr->adjData + 1) : NULL,
372 (ptr->partition_flag) ? (ptr->partition) : -1,
381 size_t delta_msg_size = get_update_msg_size(puser);
382 trackptr += delta_msg_size;
383 track_offset += delta_msg_size;
388 if(track_offset != sum_recv_sizes) {
389 throw std::logic_error(
"Did not sum!");
392 if (debug_level > 6) {
399 err = (errcount) ? 1 : 0;
404 sprintf (str,
"Processed %lu GIDs (%d local), %d GID errors", count,
410 if (debug_level > 4) {
417 template <
typename g
id_t,
typename l
id_t,
typename user_t>
425 const char * yo =
"Zoltan2_Directory::update_local";
429 throw std::logic_error(
430 "Zoltan2_Directory::update_local() owner < 0");
432 if (owner >= comm->getSize()) {
433 throw std::logic_error(
434 "Zoltan2_Directory::update_local() owner >= comm->getSize()");
437 throw std::logic_error(
438 "Zoltan2_Directory::update_local() gid == NULL");
441 if (debug_level > 5) {
446 size_t node_index = node_map.find(*gid);
447 if(node_map.valid_at(node_index)) {
449 node_map.value_at(node_index);
456 update_local_user(user, node.
userData);
460 if (partition != -1) {
474 if(node.
errcheck != -1 && mode == Replace) {
513 if (debug_level > 5) {
525 node.
lid = lid ? (*lid) : lid_t();
541 if(node_map.insert(*gid, node).failed()) {
548 size_t new_guess_size = (node_map.size() < 10) ? 10 :
549 ( node_map.size() + node_map.size()/10);
550 rehash_node_map(new_guess_size);
551 if(node_map.insert(*gid, node).failed()) {
552 throw std::logic_error(
"Hash insert failed. Mem sufficient?....");
556 if (debug_level > 6) {
560 if (debug_level > 5) {
567 template <
typename g
id_t,
typename l
id_t,
typename user_t>
575 bool throw_if_missing)
577 const char * yo =
"Zoltan2_Directory::find";
579 if (debug_level > 4) {
586 Teuchos::ArrayRCP<int> procs;
588 procs = Teuchos::arcp(
589 new int[count], 0, count,
true);
593 for (
size_t i = 0; i < count; i++) {
594 procs[i] = hash_proc(gid[i]);
600 int nrec = directoryComm.
getNRec();
602 if (debug_level > 6) {
607 throw std::logic_error(
"Zoltan2_Directory::find() error");
610 Teuchos::ArrayRCP<char> sbuff;
612 sbuff = Teuchos::arcp(
new char[find_msg_size*count],
613 0, find_msg_size*count,
true);
619 char *trackptr = sbuff.getRawPtr();
620 for (
size_t i = 0; i < count; i++) {
621 msg_t *ptr =
reinterpret_cast<msg_t*
>(trackptr);
623 ptr->proc = procs[i];
624 *(ptr->adjData) = gid[i];
625 trackptr += find_msg_size;
628 if (debug_level > 6) {
633 throw std::logic_error(
"directoryComm.execute_resize error");
637 Teuchos::ArrayRCP<char> rbuff;
639 rbuff = Teuchos::arcp(
new char[nrec * find_msg_size],
640 0, nrec * find_msg_size,
true);
643 const int nbytes = find_msg_size;
649 throw std::logic_error(
"Zoltan2_Directory::find() error");
652 if (debug_level > 6) {
658 Teuchos::ArrayRCP<int> rmsg_sizes_resized;
660 rmsg_sizes_resized = Teuchos::arcp(
new int[nrec], 0, nrec,
true);
662 Teuchos::ArrayRCP<int>::size_type sum_rmsg_sizes_resized = 0;
664 char *track_ptr = rbuff.getRawPtr();
665 for (
int i = 0; i < nrec; i++) {
666 msg_t *msg =
reinterpret_cast<msg_t*
>(track_ptr);
667 track_ptr += find_msg_size;
668 size_t find_rmsg_size_resized = get_local_find_msg_size(msg->adjData,
670 rmsg_sizes_resized[i] = find_rmsg_size_resized;
671 sum_rmsg_sizes_resized += find_rmsg_size_resized;
674 Teuchos::ArrayRCP<char>::size_type track_offset_resized = 0;
676 Teuchos::ArrayRCP<char> rbuff_resized_build;
678 if(is_Zoltan2_Directory_Vector()) {
680 if(sum_rmsg_sizes_resized > 0) {
681 rbuff_resized_build = Teuchos::arcp(
new char[sum_rmsg_sizes_resized],
682 0, sum_rmsg_sizes_resized,
true);
685 track_ptr = rbuff.getRawPtr();
686 char * track_ptr_resized = rbuff_resized_build.getRawPtr();
687 for (
int i = 0; i < nrec; i++) {
688 memcpy(track_ptr_resized, track_ptr, find_msg_size);
689 track_ptr += find_msg_size;
690 track_ptr_resized += rmsg_sizes_resized[i];
696 Teuchos::ArrayRCP<char> rbuff_resized = is_Zoltan2_Directory_Vector() ?
697 rbuff_resized_build : rbuff;
700 track_offset_resized = 0;
701 track_ptr = rbuff_resized.getRawPtr();
702 for (
int i = 0; i < nrec; i++) {
704 find_msg_t *ptr =
reinterpret_cast<find_msg_t*
>(track_ptr);
706 reinterpret_cast<char*
>(ptr->adjData) + max_id_size);
712 err = find_local(ptr->adjData, (lid_t*)ptr->adjData,
713 puser, &ptr->partition, &ptr->proc, throw_if_missing);
715 const size_t & size_shift = rmsg_sizes_resized[i];
716 track_offset_resized += size_shift;
717 track_ptr += size_shift;
720 if(track_offset_resized != sum_rmsg_sizes_resized) {
721 throw std::logic_error(
"Bad sum!");
725 size_t size_scale = is_Zoltan2_Directory_Vector() ? 1 : find_msg_size;
727 Teuchos::ArrayRCP<char> sbuff_resized;
728 if(!is_Zoltan2_Directory_Vector()) {
729 sbuff_resized = sbuff;
732 if(is_Zoltan2_Directory_Vector()) {
734 rbuff_resized, size_scale, rmsg_sizes_resized, sbuff_resized);
738 rbuff_resized, size_scale, Teuchos::null, sbuff_resized);
742 throw std::logic_error(
"Zoltan2_Directory::find() do reverse failed");
745 if (debug_level > 6) {
750 track_offset_resized = 0;
753 char * trackptr_resized = sbuff_resized.getRawPtr();
754 for (
size_t i = 0; i < count; i++) {
756 if(track_offset_resized >= sbuff_resized.size()) {
758 "%d has gid.size() %d track_offset_resized: %d sbuff_resized: %d\n",
760 (int) count, (
int) track_offset_resized, (int) sbuff_resized.size());
761 throw std::logic_error(
"Bad buffer overflow! Internal error.");
764 msg_t *ptr =
reinterpret_cast<msg_t*
>(trackptr_resized);
767 owner[ptr->index] = ptr->proc;
769 partition[ptr->index] = ptr->partition ;
771 memcpy (&lid[ptr->index], ptr->adjData,
sizeof(lid_t));
775 reinterpret_cast<char*
>(ptr->adjData) + max_id_size);
783 if(ptr->proc != -1 && user) {
784 raw_to_user(pRead, user[ptr->index]);
789 size_t incoming_size = get_incoming_find_msg_size(ptr);
790 trackptr_resized += incoming_size;
791 track_offset_resized += incoming_size;
794 if(track_offset_resized != sbuff_resized.size()) {
795 throw std::logic_error(
"Bad buffer sum!");
798 if (debug_level > 6) {
803 Teuchos::reduceAll<int>(*comm, Teuchos::REDUCE_SUM, 1, &errcount, &err);
807 if (debug_level > 0) {
809 sprintf(str,
"Processed %lu GIDs, GIDs not found: %d", count, errcount);
813 if (debug_level > 4) {
820 template <
typename g
id_t,
typename l
id_t,
typename user_t>
827 bool throw_if_missing)
const
829 const char * yo =
"Zoltan2_Directory::find_local";
832 if (owner == NULL || gid == NULL) {
833 throw std::logic_error(
"Zoltan2_Directory::find_local() Invalid input");
836 if (debug_level > 5) {
845 size_t node_index = node_map.find(*gid);
846 if(node_map.valid_at(node_index))
849 node_map.value_at(node_index);
859 if (owner) *owner = node.
owner;
860 if (partition) *partition = node.
partition;
862 if (debug_level > 5) {
872 if (debug_level > 5) {
876 if(throw_if_missing) {
879 throw std::logic_error(
"find_local did not succeed");
886 template <
typename g
id_t,
typename l
id_t,
typename user_t>
889 const char * yo =
"Zoltan2_Directory::print";
891 if (debug_level > 4) {
895 for (
size_t i = 0; i < node_map.size(); i++) {
897 node_map.value_at(i);
898 printf (
"ZOLTAN DD Print(%d): \tList, \tGID ", comm->getRank());
911 printf(
"TODO: Decide how to print gid of arbitrary type.");
916 printf(
"TODO: Decide how to print lid of arbitrary type.");
920 printf (
"\tOwner %d\n", node.
owner);
923 if (debug_level > 4) {
930 template <
typename g
id_t,
typename l
id_t,
typename user_t>
933 const char *yo =
"Zoltan2_Directory::stats";
935 if (debug_level > 4) {
942 sprintf(str,
"Kokkos unordered map %d nodes.", node_map.size());
944 if (debug_level > 4) {
949 template <
typename g
id_t,
typename l
id_t,
typename user_t>
954 const char * yo =
"Zoltan2_Directory::remove";
956 if (debug_level > 4) {
963 Teuchos::ArrayRCP<int> procs;
964 Teuchos::ArrayRCP<char> sbuff;
966 procs = Teuchos::arcp(
967 new int[count], 0, count,
true);
968 sbuff = Teuchos::arcp(
969 new char[count*remove_msg_size], 0, count*remove_msg_size,
true);
975 char * trackptr = sbuff.getRawPtr();
976 for (
size_t i = 0; i < count; i++) {
977 procs[i] = hash_proc(gid[i]);
978 msg_t *ptr =
reinterpret_cast<msg_t*
>(trackptr);
979 ptr->owner = comm->getRank();
980 *(ptr->adjData) = gid[i];
981 trackptr += remove_msg_size;
987 int nrec = directoryComm.
getNRec();
990 throw std::logic_error(
"Zoltan_Comm_Create failed");
993 if (debug_level > 6) {
998 Teuchos::ArrayRCP<char> rbuff;
1000 rbuff = Teuchos::arcp(
new char[nrec*remove_msg_size],
1001 0, nrec*remove_msg_size,
true);
1006 sbuff, remove_msg_size, rbuff);
1009 throw std::logic_error(
"Comm_Do error");
1012 if (debug_level > 6) {
1026 node_map.begin_erase();
1027 for (
int i = 0; i < nrec; i++) {
1028 msg_t *ptr =
reinterpret_cast<msg_t*
>(&(rbuff[i*remove_msg_size]));
1029 err = remove_local(ptr->adjData);
1034 node_map.end_erase();
1041 sprintf (str,
"Processed %zu GIDs (%d local), %d GIDs not found",
1042 count, nrec, errcount);
1044 err = (errcount) ? 1 : 0;
1050 template <
typename g
id_t,
typename l
id_t,
typename user_t>
1054 const char * yo =
"Zoltan2_Directory::remove_local";
1058 throw std::logic_error(
"Invalid input argument");
1061 if (debug_level > 5) {
1065 if(node_map.exists(*gid)) {
1066 node_map.erase(*gid);
1071 if (debug_level > 5) {
1078 template <
typename g
id_t,
typename l
id_t,
typename user_t>
1080 const gid_t & gid)
const
1086 #define ZOLTAN2_ROTL32(x,r) (uint32_t) \
1087 (((uint32_t)(x) << (int8_t)(r)) | ((uint32_t)(x) >> (32 - (int8_t)(r))))
1089 const void * key = (
void *)(&gid);
1090 int len =
sizeof(gid_t);
1092 void * out = (
void *)&k;
1094 const uint8_t * data = (
const uint8_t*)key;
1095 const int nblocks = len / 4;
1098 uint32_t c1 = 0xcc9e2d51;
1099 uint32_t c2 = 0x1b873593;
1100 const uint32_t * blocks = (
const uint32_t *)(data + nblocks*4);
1101 for(i = -nblocks; i; i++)
1103 uint32_t k1 = blocks[i];
1109 h1 = h1*5+0xe6546b64;
1111 const uint8_t * tail = (
const uint8_t*)(data + nblocks*4);
1115 case 3: k1 ^= tail[2] << 16;
1116 case 2: k1 ^= tail[1] << 8;
1117 case 1: k1 ^= tail[0];
1126 *(uint32_t*)out = h1;
1128 return(k % comm->getSize());
1146 #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