10 #ifndef TPETRA_DETAILS_FIXEDHASHTABLE_DEF_HPP
11 #define TPETRA_DETAILS_FIXEDHASHTABLE_DEF_HPP
13 #include "Tpetra_Details_FixedHashTable_decl.hpp"
15 #ifdef TPETRA_USE_MURMUR_HASH
16 # include "Kokkos_Functional.hpp"
17 #endif // TPETRA_USE_MURMUR_HASH
18 #include "Kokkos_ArithTraits.hpp"
19 #include "Teuchos_TypeNameTraits.hpp"
21 #include <type_traits>
44 template<
class ExecSpace>
45 bool worthBuildingFixedHashTableInParallel () {
46 return ExecSpace().concurrency() > 1;
67 template<
class CountsViewType,
69 class SizeType =
typename KeysViewType::size_type>
72 typedef CountsViewType counts_view_type;
73 typedef KeysViewType keys_view_type;
74 typedef typename CountsViewType::execution_space execution_space;
75 typedef typename CountsViewType::memory_space memory_space;
76 typedef SizeType size_type;
77 typedef typename keys_view_type::non_const_value_type key_type;
93 const keys_view_type& keys,
94 const size_type size) :
104 KOKKOS_INLINE_FUNCTION
void
110 Kokkos::atomic_inc (&counts_[hashVal]);
113 using value_type = Kokkos::pair<int, key_type>;
118 KOKKOS_INLINE_FUNCTION
void
123 const key_type keyVal = keys_[i];
125 if (hashVal < hash_value_type (0) ||
126 hashVal >= hash_value_type (counts_.extent (0))) {
131 Kokkos::atomic_inc (&counts_[hashVal]);
136 KOKKOS_INLINE_FUNCTION
void init (value_type& dst)
const
139 dst.second = key_type (0);
142 KOKKOS_INLINE_FUNCTION
void
143 join (value_type& dst,
144 const value_type& src)
const
146 const bool good = dst.first == 0 || src.first == 0;
147 dst.first = good ? 0 : dst.first;
153 counts_view_type counts_;
155 keys_view_type keys_;
170 template<
class KeyType>
172 KOKKOS_INLINE_FUNCTION
174 minKey_ (::Kokkos::ArithTraits<KeyType>::max ()),
187 maxKey_ (::Kokkos::ArithTraits<KeyType>::is_integer ?
188 ::Kokkos::ArithTraits<KeyType>::min () :
189 -::Kokkos::ArithTraits<KeyType>::max ()),
192 static_assert (std::is_arithmetic<KeyType>::value,
"FillPairsResult: "
193 "KeyType must be some kind of number type.");
196 KOKKOS_INLINE_FUNCTION
197 FillPairsResult (
const KeyType& initMinKey,
198 const KeyType& initMaxKey) :
203 static_assert (std::is_arithmetic<KeyType>::value,
"FillPairsResult: "
204 "KeyType must be some kind of number type.");
241 template<
class PairsViewType,
243 class CountsViewType,
244 class SizeType =
typename KeysViewType::size_type>
247 typedef typename CountsViewType::non_const_type counts_view_type;
248 typedef typename counts_view_type::const_type offsets_view_type;
250 typedef PairsViewType pairs_view_type;
251 typedef typename KeysViewType::const_type keys_view_type;
252 typedef typename offsets_view_type::execution_space execution_space;
253 typedef typename offsets_view_type::memory_space memory_space;
254 typedef SizeType size_type;
256 typedef typename keys_view_type::non_const_value_type key_type;
257 typedef typename pairs_view_type::non_const_value_type pair_type;
281 const counts_view_type& counts,
282 const offsets_view_type& ptr,
283 const keys_view_type& keys,
284 const typename pair_type::second_type startingValue) :
289 size_ (counts.extent (0)),
290 startingValue_ (startingValue),
291 initMinKey_ (::Kokkos::ArithTraits<key_type>::max ()),
292 initMaxKey_ (::Kokkos::ArithTraits<key_type>::is_integer ?
293 ::Kokkos::ArithTraits<key_type>::min () :
294 -::Kokkos::ArithTraits<key_type>::max ())
316 const counts_view_type& counts,
317 const offsets_view_type& ptr,
318 const keys_view_type& keys,
319 const typename pair_type::second_type startingValue,
320 const key_type initMinKey,
321 const key_type initMaxKey) :
326 size_ (counts.extent (0)),
327 startingValue_ (startingValue),
328 initMinKey_ (initMinKey),
329 initMaxKey_ (initMaxKey)
340 KOKKOS_INLINE_FUNCTION
void
341 join (value_type& dst,
342 const value_type& src)
const
344 if (src.maxKey_ > dst.maxKey_) {
345 dst.maxKey_ = src.maxKey_;
347 if (src.minKey_ < dst.minKey_) {
348 dst.minKey_ = src.minKey_;
350 dst.success_ = dst.success_ && src.success_;
357 KOKKOS_INLINE_FUNCTION
void
361 typedef typename offsets_view_type::non_const_value_type offset_type;
362 typedef typename pair_type::second_type val_type;
363 typedef typename std::remove_reference< decltype( counts_[0] ) >::type atomic_incr_type;
365 const key_type key = keys_[i];
372 const val_type theVal = startingValue_ +
static_cast<val_type
> (i);
376 const offset_type count = Kokkos::atomic_fetch_add (&counts_[hashVal], atomic_incr_type(-1));
381 const offset_type curPos = ptr_[hashVal+1] - count;
383 pairs_[curPos].first = key;
384 pairs_[curPos].second = theVal;
389 pairs_view_type pairs_;
390 counts_view_type counts_;
391 offsets_view_type ptr_;
392 keys_view_type keys_;
394 typename pair_type::second_type startingValue_;
396 key_type initMinKey_;
398 key_type initMaxKey_;
424 template<
class OffsetsViewType,
426 class SizeType =
typename OffsetsViewType::size_type>
429 typedef typename OffsetsViewType::const_type offsets_view_type;
430 typedef typename PairsViewType::const_type pairs_view_type;
431 typedef typename offsets_view_type::execution_space execution_space;
432 typedef typename offsets_view_type::memory_space memory_space;
433 typedef SizeType size_type;
436 typedef int value_type;
443 const offsets_view_type& ptr) :
446 size_ (ptr_.extent (0) == 0 ?
452 KOKKOS_INLINE_FUNCTION
void init (value_type& dst)
const
458 KOKKOS_INLINE_FUNCTION
void
460 const value_type& src)
const
462 dst = dst + src > 0?1:0;
466 KOKKOS_INLINE_FUNCTION
void
469 typedef typename offsets_view_type::non_const_value_type offset_type;
470 typedef typename pairs_view_type::non_const_value_type pair_type;
471 typedef typename pair_type::first_type key_type;
477 const offset_type beg = ptr_[i];
478 const offset_type end = ptr_[i+1];
479 bool foundDuplicateKey =
false;
484 for (offset_type j = beg + 1; j < end; ++j) {
485 const key_type curKey = pairs_[j].first;
486 for (offset_type k = beg; k < j; ++k) {
487 if (pairs_[k].first == curKey) {
488 foundDuplicateKey =
true;
493 dst = (dst>0) || foundDuplicateKey?1:0;
498 pairs_view_type pairs_;
499 offsets_view_type ptr_;
509 template<
class KeyType,
class ValueType,
class DeviceType>
513 maxVal_ (keys.size () == 0 ?
514 static_cast<ValueType> (0) :
515 static_cast<ValueType> (keys.size () - 1)),
516 checkedForDuplicateKeys_ (false)
518 const ValueType startingValue =
static_cast<ValueType
> (0);
519 const KeyType initMinKey = this->minKey_;
520 const KeyType initMaxKey = this->maxKey_;
521 this->init (keys, startingValue, initMinKey, initMaxKey,
522 initMinKey, initMinKey,
false);
525 template<
class KeyType,
class ValueType,
class DeviceType>
529 maxVal_ (keys.size () == 0 ?
530 static_cast<ValueType> (0) :
531 static_cast<ValueType> (keys.size () - 1)),
532 checkedForDuplicateKeys_ (false)
534 typedef typename keys_type::non_const_type nonconst_keys_type;
539 const ValueType startingValue =
static_cast<ValueType
> (0);
540 host_input_keys_type keys_k (keys.size () == 0 ? NULL : keys.getRawPtr (),
542 using Kokkos::ViewAllocateWithoutInitializing;
543 nonconst_keys_type keys_d (ViewAllocateWithoutInitializing (
"FixedHashTable::keys"),
547 const KeyType initMinKey = this->minKey_;
548 const KeyType initMaxKey = this->maxKey_;
549 this->init (keys_d, startingValue, initMinKey, initMaxKey,
550 initMinKey, initMinKey,
false);
553 template<
class KeyType,
class ValueType,
class DeviceType>
556 const ValueType startingValue) :
557 minVal_ (startingValue),
558 maxVal_ (keys.size () == 0 ?
560 static_cast<ValueType> (startingValue + keys.size () - 1)),
561 checkedForDuplicateKeys_ (false)
563 typedef typename keys_type::non_const_type nonconst_keys_type;
568 host_input_keys_type keys_k (keys.size () == 0 ? NULL : keys.getRawPtr (),
570 using Kokkos::ViewAllocateWithoutInitializing;
571 nonconst_keys_type keys_d (ViewAllocateWithoutInitializing (
"FixedHashTable::keys"),
576 const KeyType initMinKey = ::Kokkos::ArithTraits<KeyType>::max ();
589 const KeyType initMaxKey = ::Kokkos::ArithTraits<KeyType>::is_integer ?
590 ::Kokkos::ArithTraits<KeyType>::min () :
591 -::Kokkos::ArithTraits<KeyType>::max ();
592 this->init (keys_d, startingValue, initMinKey, initMaxKey,
593 initMinKey, initMinKey,
false);
597 template<
class KeyType,
class ValueType,
class DeviceType>
600 const KeyType firstContigKey,
601 const KeyType lastContigKey,
602 const ValueType startingValue) :
603 minVal_ (startingValue),
604 maxVal_ (keys.size () == 0 ?
606 static_cast<ValueType> (startingValue + keys.size () - 1)),
607 firstContigKey_ (firstContigKey),
608 lastContigKey_ (lastContigKey),
609 checkedForDuplicateKeys_ (false)
611 const KeyType initMinKey = ::Kokkos::ArithTraits<KeyType>::max ();
624 const KeyType initMaxKey = ::Kokkos::ArithTraits<KeyType>::is_integer ?
625 ::Kokkos::ArithTraits<KeyType>::min () :
626 -::Kokkos::ArithTraits<KeyType>::max ();
627 this->init (keys, startingValue, initMinKey, initMaxKey,
628 firstContigKey, lastContigKey,
true);
631 template<
class KeyType,
class ValueType,
class DeviceType>
634 const KeyType firstContigKey,
635 const KeyType lastContigKey,
636 const ValueType startingValue) :
637 minVal_ (startingValue),
638 maxVal_ (keys.size () == 0 ?
640 static_cast<ValueType> (startingValue + keys.size () - 1)),
641 firstContigKey_ (firstContigKey),
642 lastContigKey_ (lastContigKey),
643 checkedForDuplicateKeys_ (false)
645 typedef typename keys_type::non_const_type nonconst_keys_type;
650 host_input_keys_type keys_k (keys.size () == 0 ? NULL : keys.getRawPtr (),
652 using Kokkos::ViewAllocateWithoutInitializing;
653 nonconst_keys_type keys_d (ViewAllocateWithoutInitializing (
"FixedHashTable::keys"),
658 const KeyType initMinKey = ::Kokkos::ArithTraits<KeyType>::max ();
671 const KeyType initMaxKey = ::Kokkos::ArithTraits<KeyType>::is_integer ?
672 ::Kokkos::ArithTraits<KeyType>::min () :
673 -::Kokkos::ArithTraits<KeyType>::max ();
674 this->init (keys_d, startingValue, initMinKey, initMaxKey,
675 firstContigKey, lastContigKey,
true);
678 template<
class KeyType,
class ValueType,
class DeviceType>
681 const ValueType startingValue) :
682 minVal_ (startingValue),
683 maxVal_ (keys.size () == 0 ?
685 static_cast<ValueType> (startingValue + keys.size () - 1)),
686 checkedForDuplicateKeys_ (false)
688 const KeyType initMinKey = ::Kokkos::ArithTraits<KeyType>::max ();
701 const KeyType initMaxKey = ::Kokkos::ArithTraits<KeyType>::is_integer ?
702 ::Kokkos::ArithTraits<KeyType>::min () :
703 -::Kokkos::ArithTraits<KeyType>::max ();
704 this->init (keys, startingValue, initMinKey, initMaxKey,
705 initMinKey, initMinKey,
false);
708 template<
class KeyType,
class ValueType,
class DeviceType>
711 const Teuchos::ArrayView<const ValueType>& vals) :
712 contiguousValues_ (false),
713 checkedForDuplicateKeys_ (false)
718 host_input_keys_type keys_k (keys.size () == 0 ? NULL : keys.getRawPtr (),
720 host_input_vals_type vals_k (vals.size () == 0 ? NULL : vals.getRawPtr (),
722 const KeyType initMinKey = ::Kokkos::ArithTraits<KeyType>::max ();
735 const KeyType initMaxKey = ::Kokkos::ArithTraits<KeyType>::is_integer ?
736 ::Kokkos::ArithTraits<KeyType>::min () :
737 -::Kokkos::ArithTraits<KeyType>::max ();
738 this->init (keys_k, vals_k, initMinKey, initMaxKey);
741 template<
class KeyType,
class ValueType,
class DeviceType>
744 init (
const keys_type& keys,
745 ValueType startingValue,
748 KeyType firstContigKey,
749 KeyType lastContigKey,
750 const bool computeInitContigKeys)
752 using Kokkos::subview;
753 using Kokkos::ViewAllocateWithoutInitializing;
754 using Teuchos::TypeNameTraits;
755 typedef typename std::decay<decltype (keys.extent (0)) >::type size_type;
757 const char prefix[] =
"Tpetra::Details::FixedHashTable: ";
759 const offset_type numKeys =
static_cast<offset_type
> (keys.extent (0));
761 const offset_type theMaxVal = ::Kokkos::ArithTraits<offset_type>::max ();
762 const size_type maxValST =
static_cast<size_type
> (theMaxVal);
763 TEUCHOS_TEST_FOR_EXCEPTION
764 (keys.extent (0) > maxValST, std::invalid_argument, prefix <<
"The "
765 "number of keys " << keys.extent (0) <<
" does not fit in "
766 "offset_type = " << TypeNameTraits<offset_type>::name () <<
", whose "
767 "max value is " << theMaxVal <<
". This means that it is not possible to "
768 "use this constructor.");
770 TEUCHOS_TEST_FOR_EXCEPTION
771 (static_cast<unsigned long long> (numKeys) >
772 static_cast<unsigned long long> (::Kokkos::ArithTraits<ValueType>::max ()),
773 std::invalid_argument,
"Tpetra::Details::FixedHashTable: The number of "
774 "keys " << numKeys <<
" is greater than the maximum representable "
775 "ValueType value " << ::Kokkos::ArithTraits<ValueType>::max () <<
". "
776 "This means that it is not possible to use this constructor.");
777 TEUCHOS_TEST_FOR_EXCEPTION
778 (numKeys > static_cast<offset_type> (INT_MAX), std::logic_error, prefix <<
779 "This class currently only works when the number of keys is <= INT_MAX = "
780 << INT_MAX <<
". If this is a problem for you, please talk to the Tpetra "
783 const bool buildInParallel =
784 FHT::worthBuildingFixedHashTableInParallel<execution_space> ();
795 if (computeInitContigKeys) {
809 auto keys_h = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
811 firstContigKey_ = keys_h[0];
815 lastContigKey_ = firstContigKey_ + 1;
821 for (offset_type k = 1; k < numKeys; ++k) {
822 if (lastContigKey_ != keys_h[k]) {
831 firstContigKey_ = firstContigKey;
832 lastContigKey_ = lastContigKey;
835 offset_type startIndex;
837 initMinKey = std::min (initMinKey, firstContigKey_);
838 initMaxKey = std::max (initMaxKey, lastContigKey_);
839 startIndex =
static_cast<offset_type
> (lastContigKey_ - firstContigKey_);
844 const offset_type theNumKeys = numKeys - startIndex;
845 const offset_type size = hash_type::getRecommendedSize (theNumKeys);
846 #ifdef HAVE_TPETRA_DEBUG
847 TEUCHOS_TEST_FOR_EXCEPTION(
848 size == 0 && numKeys != 0, std::logic_error,
849 "Tpetra::Details::FixedHashTable constructor: "
850 "getRecommendedSize(" << numKeys <<
") returned zero, "
851 "even though the number of keys " << numKeys <<
" is nonzero. "
852 "Please report this bug to the Tpetra developers.");
853 #endif // HAVE_TPETRA_DEBUG
855 subview (keys, std::pair<offset_type, offset_type> (startIndex, numKeys));
862 typedef typename ptr_type::non_const_type counts_type;
863 counts_type counts (
"Tpetra::FixedHashTable::counts", size);
870 typename keys_type::HostMirror theKeysHost;
877 if (buildInParallel) {
878 FHT::CountBuckets<counts_type, keys_type> functor (counts, theKeys, size);
879 using range_type = Kokkos::RangePolicy<execution_space, offset_type>;
880 const char kernelLabel[] =
"Tpetra::Details::FixedHashTable CountBuckets";
882 using key_type =
typename keys_type::non_const_value_type;
883 Kokkos::pair<int, key_type> err;
884 Kokkos::parallel_reduce (kernelLabel, range_type (0, theNumKeys),
886 TEUCHOS_TEST_FOR_EXCEPTION
887 (err.first != 0, std::logic_error,
"Tpetra::Details::FixedHashTable "
888 "constructor: CountBuckets found a key " << err.second <<
" that "
889 "results in an out-of-bounds hash value.");
892 Kokkos::parallel_for (kernelLabel, range_type (0, theNumKeys), functor);
896 Kokkos::HostSpace hostMemSpace;
897 theKeysHost = Kokkos::create_mirror_view(theKeys);
900 auto countsHost = Kokkos::create_mirror_view (hostMemSpace, counts);
902 for (offset_type k = 0; k < theNumKeys; ++k) {
903 using key_type =
typename keys_type::non_const_value_type;
904 const key_type key = theKeysHost[k];
906 using hash_value_type =
typename hash_type::result_type;
907 const hash_value_type hashVal = hash_type::hashFunc (key, size);
908 TEUCHOS_TEST_FOR_EXCEPTION
909 (hashVal < hash_value_type (0) ||
910 hashVal >= hash_value_type (countsHost.extent (0)),
911 std::logic_error,
"Tpetra::Details::FixedHashTable "
912 "constructor: Sequential CountBuckets found a key " << key
913 <<
" that results in an out-of-bounds hash value.");
915 ++countsHost[hashVal];
924 execution_space().fence ();
927 typename ptr_type::non_const_type ptr (
"Tpetra::FixedHashTable::ptr", size+1);
943 if (buildInParallel) {
947 if (! buildInParallel || debug) {
948 Kokkos::HostSpace hostMemSpace;
949 auto counts_h = Kokkos::create_mirror_view_and_copy (hostMemSpace, counts);
950 auto ptr_h = Kokkos::create_mirror_view (hostMemSpace, ptr);
952 #ifdef KOKKOS_ENABLE_SERIAL
953 Kokkos::Serial hostExecSpace;
955 Kokkos::DefaultHostExecutionSpace hostExecSpace;
956 #endif // KOKKOS_ENABLE_SERIAL
964 for (offset_type i = 0; i < size; ++i) {
965 if (ptr_h[i+1] != ptr_h[i] + counts_h[i]) {
969 TEUCHOS_TEST_FOR_EXCEPTION
970 (bad, std::logic_error,
"Tpetra::Details::FixedHashTable "
971 "constructor: computeOffsetsFromCounts gave an incorrect "
979 execution_space().fence ();
983 typedef typename val_type::non_const_type nonconst_val_type;
984 nonconst_val_type val (ViewAllocateWithoutInitializing (
"Tpetra::FixedHashTable::pairs"),
988 typedef FHT::FillPairs<
typename val_type::non_const_type, keys_type,
989 typename ptr_type::non_const_type> functor_type;
990 typename functor_type::value_type result (initMinKey, initMaxKey);
992 const ValueType newStartingValue = startingValue +
static_cast<ValueType
> (startIndex);
993 if (buildInParallel) {
994 functor_type functor (val, counts, ptr, theKeys, newStartingValue,
995 initMinKey, initMaxKey);
996 typedef Kokkos::RangePolicy<execution_space, offset_type> range_type;
997 Kokkos::parallel_reduce (
"Tpetra::Details::FixedHashTable::FillPairs", range_type (0, theNumKeys), functor, result);
1000 Kokkos::HostSpace hostMemSpace;
1001 auto counts_h = Kokkos::create_mirror_view_and_copy(hostMemSpace, counts);
1002 auto ptr_h = Kokkos::create_mirror_view_and_copy(hostMemSpace, ptr);
1003 auto val_h = Kokkos::create_mirror_view_and_copy(hostMemSpace, val);
1004 for (offset_type k = 0; k < theNumKeys; ++k) {
1005 typedef typename hash_type::result_type hash_value_type;
1006 const KeyType key = theKeysHost[k];
1007 if (key > result.maxKey_) {
1008 result.maxKey_ = key;
1010 if (key < result.minKey_) {
1011 result.minKey_ = key;
1013 const ValueType theVal = newStartingValue +
static_cast<ValueType
> (k);
1014 const hash_value_type hashVal = hash_type::hashFunc (key, size);
1017 const offset_type count = counts_h[hashVal];
1018 --counts_h[hashVal];
1020 result.success_ =
false;
1024 const offset_type curPos = ptr_h[hashVal+1] - count;
1025 val_h[curPos].first = key;
1026 val_h[curPos].second = theVal;
1045 minKey_ = result.minKey_;
1046 maxKey_ = result.maxKey_;
1051 template<
class KeyType,
class ValueType,
class DeviceType>
1053 FixedHashTable<KeyType, ValueType, DeviceType>::
1054 init (
const host_input_keys_type& keys,
1055 const host_input_vals_type& vals,
1060 const offset_type numKeys =
static_cast<offset_type
> (keys.extent (0));
1061 TEUCHOS_TEST_FOR_EXCEPTION
1062 (static_cast<unsigned long long> (numKeys) > static_cast<unsigned long long> (::Kokkos::ArithTraits<ValueType>::max ()),
1063 std::invalid_argument,
"Tpetra::Details::FixedHashTable: The number of "
1064 "keys " << numKeys <<
" is greater than the maximum representable "
1065 "ValueType value " << ::Kokkos::ArithTraits<ValueType>::max () <<
".");
1066 TEUCHOS_TEST_FOR_EXCEPTION
1067 (numKeys > static_cast<offset_type> (INT_MAX), std::logic_error,
"Tpetra::"
1068 "Details::FixedHashTable: This class currently only works when the number "
1069 "of keys is <= INT_MAX = " << INT_MAX <<
". If this is a problem for you"
1070 ", please talk to the Tpetra developers.");
1077 const offset_type size = hash_type::getRecommendedSize (numKeys);
1078 #ifdef HAVE_TPETRA_DEBUG
1079 TEUCHOS_TEST_FOR_EXCEPTION(
1080 size == 0 && numKeys != 0, std::logic_error,
1081 "Tpetra::Details::FixedHashTable constructor: "
1082 "getRecommendedSize(" << numKeys <<
") returned zero, "
1083 "even though the number of keys " << numKeys <<
" is nonzero. "
1084 "Please report this bug to the Tpetra developers.");
1085 #endif // HAVE_TPETRA_DEBUG
1093 Kokkos::HostSpace hostMemSpace;
1094 typename ptr_type::non_const_type ptr (
"Tpetra::FixedHashTable::ptr", size + 1);
1095 auto ptr_h = Kokkos::create_mirror_view_and_copy(hostMemSpace, ptr);
1099 using Kokkos::ViewAllocateWithoutInitializing;
1100 typedef typename val_type::non_const_type nonconst_val_type;
1101 nonconst_val_type val (ViewAllocateWithoutInitializing (
"Tpetra::FixedHashTable::pairs"),
1103 auto val_h = Kokkos::create_mirror_view_and_copy(hostMemSpace, val);
1106 for (offset_type k = 0; k < numKeys; ++k) {
1107 const typename hash_type::result_type hashVal =
1108 hash_type::hashFunc (keys[k], size);
1120 for (offset_type i = 0; i < size; ++i) {
1121 ptr_h[i+1] += ptr_h[i];
1126 typename ptr_type::non_const_type::HostMirror curRowStart (
"Tpetra::FixedHashTable::curRowStart", size);
1129 FHT::FillPairsResult<KeyType> result (initMinKey, initMaxKey);
1130 for (offset_type k = 0; k < numKeys; ++k) {
1131 typedef typename hash_type::result_type hash_value_type;
1132 const KeyType key = keys[k];
1133 if (key > result.maxKey_) {
1134 result.maxKey_ = key;
1136 if (key < result.minKey_) {
1137 result.minKey_ = key;
1139 const ValueType theVal = vals[k];
1140 if (theVal > maxVal_) {
1143 if (theVal < minVal_) {
1146 const hash_value_type hashVal = hash_type::hashFunc (key, size);
1148 const offset_type offset = curRowStart[hashVal];
1149 const offset_type curPos = ptr_h[hashVal] + offset;
1150 if (curPos >= ptr_h[hashVal+1]) {
1151 result.success_ =
false;
1154 val_h[curPos].first = key;
1155 val_h[curPos].second = theVal;
1156 ++curRowStart[hashVal];
1160 TEUCHOS_TEST_FOR_EXCEPTION
1161 (! result.success_, std::logic_error,
"Tpetra::Details::FixedHashTable::"
1162 "init: Filling the hash table failed! Please report this bug to the "
1163 "Tpetra developers.");
1171 minKey_ = result.minKey_;
1172 maxKey_ = result.maxKey_;
1176 template <
class KeyType,
class ValueType,
class DeviceType>
1181 if (! checkedForDuplicateKeys_) {
1182 hasDuplicateKeys_ = checkForDuplicateKeys ();
1183 checkedForDuplicateKeys_ =
true;
1185 return hasDuplicateKeys_;
1188 template <
class KeyType,
class ValueType,
class DeviceType>
1193 const offset_type size = this->getSize ();
1197 if (size == 0 || this->numPairs () == 0) {
1201 typedef FHT::CheckForDuplicateKeys<ptr_type, val_type> functor_type;
1202 functor_type functor (val_, ptr_);
1204 typedef Kokkos::RangePolicy<execution_space, offset_type> range_type;
1205 Kokkos::parallel_reduce (
"Tpetra::Details::FixedHashTable::CheckForDuplicateKeys", range_type (0, size), functor, hasDupKeys);
1206 return hasDupKeys > 0;
1210 template <
class KeyType,
class ValueType,
class DeviceType>
1215 std::ostringstream oss;
1216 oss <<
"FixedHashTable<"
1217 << Teuchos::TypeNameTraits<KeyType>::name () <<
","
1218 << Teuchos::TypeNameTraits<ValueType>::name () <<
">: "
1219 <<
"{ numKeys: " << val_.extent (0)
1220 <<
", tableSize: " << this->getSize () <<
" }";
1224 template <
class KeyType,
class ValueType,
class DeviceType>
1228 const Teuchos::EVerbosityLevel verbLevel)
const
1232 using Teuchos::OSTab;
1233 using Teuchos::rcpFromRef;
1234 using Teuchos::TypeNameTraits;
1235 using Teuchos::VERB_DEFAULT;
1236 using Teuchos::VERB_NONE;
1237 using Teuchos::VERB_LOW;
1238 using Teuchos::VERB_EXTREME;
1243 Teuchos::EVerbosityLevel vl = verbLevel;
1244 if (vl == VERB_DEFAULT) vl = VERB_LOW;
1246 if (vl == VERB_NONE) {
1249 else if (vl == VERB_LOW) {
1250 out << this->description() << endl;
1253 out <<
"FixedHashTable:" << endl;
1255 OSTab tab1 (rcpFromRef (out));
1261 out <<
"Template parameters:" << endl;
1263 OSTab tab2 (rcpFromRef (out));
1264 out <<
"KeyType: " << TypeNameTraits<KeyType>::name () << endl
1265 <<
"ValueType: " << TypeNameTraits<ValueType>::name () << endl;
1268 const offset_type tableSize = this->getSize ();
1269 const offset_type numKeys = val_.extent (0);
1271 out <<
"Table parameters:" << endl;
1273 OSTab tab2 (rcpFromRef (out));
1274 out <<
"numKeys: " << numKeys << endl
1275 <<
"tableSize: " << tableSize << endl;
1278 if (vl >= VERB_EXTREME) {
1279 out <<
"Contents: ";
1280 if (tableSize == 0 || numKeys == 0) {
1281 out <<
"[]" << endl;
1283 out <<
"[ " << endl;
1285 OSTab tab2 (rcpFromRef (out));
1286 for (offset_type i = 0; i < tableSize; ++i) {
1287 OSTab tab3 (rcpFromRef (out));
1289 for (offset_type k = ptr_[i]; k < ptr_[i+1]; ++k) {
1290 out <<
"(" << val_[k].first <<
"," << val_[k].second <<
")";
1291 if (k + 1 < ptr_[i+1]) {
1317 #define TPETRA_DETAILS_FIXEDHASHTABLE_INSTANT_DEFAULTNODE(LO,GO) \
1318 template class FixedHashTable< GO , LO >;
1329 #define TPETRA_DETAILS_FIXEDHASHTABLE_INSTANT(LO, GO, DEVICE) \
1330 template class FixedHashTable< GO , LO , DEVICE >;
1332 #endif // TPETRA_DETAILS_FIXEDHASHTABLE_DEF_HPP
CheckForDuplicateKeys(const pairs_view_type &pairs, const offsets_view_type &ptr)
Constructor.
Parallel reduce functor for filling the FixedHashTable, and computing the min and max keys...
FillPairs(const pairs_view_type &pairs, const counts_view_type &counts, const offsets_view_type &ptr, const keys_view_type &keys, const typename pair_type::second_type startingValue, const key_type initMinKey, const key_type initMaxKey)
Constructor that takes initial min and max key values.
KOKKOS_INLINE_FUNCTION void init(value_type &dst) const
Set the initial value of the reduction result.
KOKKOS_DEFAULTED_FUNCTION FixedHashTable()=default
Default constructor; makes an empty table.
static KOKKOS_INLINE_FUNCTION result_type hashFunc(const argument_type &, const offset_type &)
The hash function.
KOKKOS_INLINE_FUNCTION void operator()(const size_type &i) const
Do this for every entry of keys_.
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Print this object with the given verbosity to the output stream.
ResultType result_type
Type of the return value of the hash function.
Parallel for functor for counting "buckets" in the FixedHashTable.
static bool debug()
Whether Tpetra is in debug mode.
bool success_
Whether fill succeeded (it can only fail on a bug)
KeyType maxKey_
The current maximum key.
void deep_copy(MultiVector< DS, DL, DG, DN > &dst, const MultiVector< SS, SL, SG, SN > &src)
Copy the contents of the MultiVector src into dst.
The hash function for FixedHashTable.
Declare and define the functions Tpetra::Details::computeOffsetsFromCounts and Tpetra::computeOffsets...
std::string description() const
Implementation of Teuchos::Describable interface.
KOKKOS_INLINE_FUNCTION void operator()(const size_type &i, value_type &dst) const
Parallel loop body; do this for every entry of keys_.
FillPairs(const pairs_view_type &pairs, const counts_view_type &counts, const offsets_view_type &ptr, const keys_view_type &keys, const typename pair_type::second_type startingValue)
Constructor.
KOKKOS_INLINE_FUNCTION void init(value_type &dst) const
Set the initial value of the reduction result.
bool hasDuplicateKeys()
Whether the table has any duplicate keys.
CountBuckets(const counts_view_type &counts, const keys_view_type &keys, const size_type size)
Constructor.
KOKKOS_INLINE_FUNCTION void init(value_type &dst) const
Set the initial value of the reduction result.
Functor for checking whether a FixedHashTable has one or more duplicate entries.
KOKKOS_INLINE_FUNCTION void join(value_type &dst, const value_type &src) const
Combine two intermediate reduction results.
OffsetsViewType::non_const_value_type computeOffsetsFromCounts(const ExecutionSpace &execSpace, const OffsetsViewType &ptr, const CountsViewType &counts)
Compute offsets from counts.
KeyType minKey_
The current minimum key.
Reduction result for FillPairs functor below.
KOKKOS_INLINE_FUNCTION void operator()(const size_type &i, value_type &dst) const
Parallel loop body.
Kokkos::View< const KeyType *, Kokkos::LayoutLeft, device_type > keys_type
Type of a 1-D Kokkos::View (array) used to store keys.
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.