44 #ifndef TPETRA_DETAILS_FIXEDHASHTABLE_DEF_HPP
45 #define TPETRA_DETAILS_FIXEDHASHTABLE_DEF_HPP
47 #include "Tpetra_Details_FixedHashTable_decl.hpp"
49 #ifdef TPETRA_USE_MURMUR_HASH
50 # include "Kokkos_Functional.hpp"
52 #include "Kokkos_ArithTraits.hpp"
53 #include "Teuchos_TypeNameTraits.hpp"
55 #include <type_traits>
78 template<
class ExecSpace>
79 bool worthBuildingFixedHashTableInParallel () {
80 return ExecSpace::concurrency() > 1;
101 template<
class CountsViewType,
103 class SizeType =
typename KeysViewType::size_type>
106 typedef CountsViewType counts_view_type;
107 typedef KeysViewType keys_view_type;
108 typedef typename CountsViewType::execution_space execution_space;
109 typedef typename CountsViewType::memory_space memory_space;
110 typedef SizeType size_type;
111 typedef typename keys_view_type::non_const_value_type key_type;
127 const keys_view_type& keys,
128 const size_type size) :
138 KOKKOS_INLINE_FUNCTION
void
144 Kokkos::atomic_increment (&counts_[hashVal]);
147 using value_type = Kokkos::pair<int, key_type>;
152 KOKKOS_INLINE_FUNCTION
void
157 const key_type keyVal = keys_[i];
159 if (hashVal < hash_value_type (0) ||
160 hashVal >= hash_value_type (counts_.extent (0))) {
165 Kokkos::atomic_increment (&counts_[hashVal]);
170 KOKKOS_INLINE_FUNCTION
void init (value_type& dst)
const
173 dst.second = key_type (0);
176 KOKKOS_INLINE_FUNCTION
void
177 join (
volatile value_type& dst,
178 const volatile value_type& src)
const
180 const bool good = dst.first == 0 || src.first == 0;
181 dst.first = good ? 0 : dst.first;
187 counts_view_type counts_;
189 keys_view_type keys_;
204 template<
class KeyType>
206 KOKKOS_INLINE_FUNCTION
208 minKey_ (::Kokkos::Details::ArithTraits<KeyType>::max ()),
221 maxKey_ (::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
222 ::Kokkos::Details::ArithTraits<KeyType>::min () :
223 -::Kokkos::Details::ArithTraits<KeyType>::max ()),
226 static_assert (std::is_arithmetic<KeyType>::value,
"FillPairsResult: "
227 "KeyType must be some kind of number type.");
230 KOKKOS_INLINE_FUNCTION
231 FillPairsResult (
const KeyType& initMinKey,
232 const KeyType& initMaxKey) :
237 static_assert (std::is_arithmetic<KeyType>::value,
"FillPairsResult: "
238 "KeyType must be some kind of number type.");
275 template<
class PairsViewType,
277 class CountsViewType,
278 class SizeType =
typename KeysViewType::size_type>
281 typedef typename CountsViewType::non_const_type counts_view_type;
282 typedef typename counts_view_type::const_type offsets_view_type;
284 typedef PairsViewType pairs_view_type;
285 typedef typename KeysViewType::const_type keys_view_type;
286 typedef typename offsets_view_type::execution_space execution_space;
287 typedef typename offsets_view_type::memory_space memory_space;
288 typedef SizeType size_type;
290 typedef typename keys_view_type::non_const_value_type key_type;
291 typedef typename pairs_view_type::non_const_value_type pair_type;
315 const counts_view_type& counts,
316 const offsets_view_type& ptr,
317 const keys_view_type& keys,
318 const typename pair_type::second_type startingValue) :
323 size_ (counts.extent (0)),
324 startingValue_ (startingValue),
325 initMinKey_ (::Kokkos::
Details::ArithTraits<key_type>::max ()),
326 initMaxKey_ (::Kokkos::
Details::ArithTraits<key_type>::is_integer ?
327 ::Kokkos::
Details::ArithTraits<key_type>::min () :
328 -::Kokkos::
Details::ArithTraits<key_type>::max ())
350 const counts_view_type& counts,
351 const offsets_view_type& ptr,
352 const keys_view_type& keys,
353 const typename pair_type::second_type startingValue,
354 const key_type initMinKey,
355 const key_type initMaxKey) :
360 size_ (counts.extent (0)),
361 startingValue_ (startingValue),
362 initMinKey_ (initMinKey),
363 initMaxKey_ (initMaxKey)
374 KOKKOS_INLINE_FUNCTION
void
375 join (
volatile value_type& dst,
376 const volatile value_type& src)
const
378 if (src.maxKey_ > dst.maxKey_) {
379 dst.maxKey_ = src.maxKey_;
381 if (src.minKey_ < dst.minKey_) {
382 dst.minKey_ = src.minKey_;
384 dst.success_ = dst.success_ && src.success_;
391 KOKKOS_INLINE_FUNCTION
void
395 typedef typename offsets_view_type::non_const_value_type offset_type;
396 typedef typename pair_type::second_type val_type;
397 typedef typename std::remove_reference< decltype( counts_[0] ) >::type atomic_incr_type;
399 const key_type key = keys_[i];
406 const val_type theVal = startingValue_ +
static_cast<val_type
> (i);
410 const offset_type count = Kokkos::atomic_fetch_add (&counts_[hashVal], atomic_incr_type(-1));
415 const offset_type curPos = ptr_[hashVal+1] - count;
417 pairs_[curPos].first = key;
418 pairs_[curPos].second = theVal;
423 pairs_view_type pairs_;
424 counts_view_type counts_;
425 offsets_view_type ptr_;
426 keys_view_type keys_;
428 typename pair_type::second_type startingValue_;
430 key_type initMinKey_;
432 key_type initMaxKey_;
458 template<
class OffsetsViewType,
460 class SizeType =
typename OffsetsViewType::size_type>
463 typedef typename OffsetsViewType::const_type offsets_view_type;
464 typedef typename PairsViewType::const_type pairs_view_type;
465 typedef typename offsets_view_type::execution_space execution_space;
466 typedef typename offsets_view_type::memory_space memory_space;
467 typedef SizeType size_type;
470 typedef int value_type;
477 const offsets_view_type& ptr) :
480 size_ (ptr_.extent (0) == 0 ?
486 KOKKOS_INLINE_FUNCTION
void init (value_type& dst)
const
492 KOKKOS_INLINE_FUNCTION
void
493 join (
volatile value_type& dst,
494 const volatile value_type& src)
const
496 dst = dst + src > 0?1:0;
500 KOKKOS_INLINE_FUNCTION
void
503 typedef typename offsets_view_type::non_const_value_type offset_type;
504 typedef typename pairs_view_type::non_const_value_type pair_type;
505 typedef typename pair_type::first_type key_type;
511 const offset_type beg = ptr_[i];
512 const offset_type end = ptr_[i+1];
513 bool foundDuplicateKey =
false;
518 for (offset_type j = beg + 1; j < end; ++j) {
519 const key_type curKey = pairs_[j].first;
520 for (offset_type k = beg; k < j; ++k) {
521 if (pairs_[k].first == curKey) {
522 foundDuplicateKey =
true;
527 dst = (dst>0) || foundDuplicateKey?1:0;
532 pairs_view_type pairs_;
533 offsets_view_type ptr_;
543 template<
class KeyType,
class ValueType,
class DeviceType>
553 return keys_.extent (0) == val_.extent (0);
556 template<
class KeyType,
class ValueType,
class DeviceType>
565 template<
class KeyType,
class ValueType,
class DeviceType>
568 minKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
569 maxKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
570 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
571 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
572 minVal_ (::Kokkos::
Details::ArithTraits<ValueType>::max ()),
573 maxVal_ (::Kokkos::
Details::ArithTraits<ValueType>::is_integer ?
574 ::Kokkos::
Details::ArithTraits<ValueType>::min () :
575 -::Kokkos::
Details::ArithTraits<ValueType>::max ()),
576 firstContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
577 lastContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
578 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
579 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
580 contiguousValues_ (true),
581 checkedForDuplicateKeys_ (true),
582 hasDuplicateKeys_ (false)
584 #ifdef HAVE_TPETRA_DEBUG
589 template<
class KeyType,
class ValueType,
class DeviceType>
593 minKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
594 maxKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
595 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
596 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
598 maxVal_ (keys.size () == 0 ?
599 static_cast<ValueType> (0) :
600 static_cast<ValueType> (keys.size () - 1)),
601 firstContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
602 lastContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
603 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
604 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
605 contiguousValues_ (true),
606 checkedForDuplicateKeys_ (false),
607 hasDuplicateKeys_ (false)
609 const ValueType startingValue =
static_cast<ValueType
> (0);
610 const KeyType initMinKey = this->minKey_;
611 const KeyType initMaxKey = this->maxKey_;
612 this->init (keys, startingValue, initMinKey, initMaxKey,
613 initMinKey, initMinKey,
false);
615 #ifdef HAVE_TPETRA_DEBUG
620 template<
class KeyType,
class ValueType,
class DeviceType>
623 const bool keepKeys) :
624 minKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
625 maxKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
626 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
627 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
629 maxVal_ (keys.size () == 0 ?
630 static_cast<ValueType> (0) :
631 static_cast<ValueType> (keys.size () - 1)),
632 firstContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
633 lastContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
634 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
635 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
636 contiguousValues_ (true),
637 checkedForDuplicateKeys_ (false),
638 hasDuplicateKeys_ (false)
640 typedef typename keys_type::non_const_type nonconst_keys_type;
645 const ValueType startingValue =
static_cast<ValueType
> (0);
646 host_input_keys_type keys_k (keys.size () == 0 ? NULL : keys.getRawPtr (),
648 using Kokkos::ViewAllocateWithoutInitializing;
649 nonconst_keys_type keys_d (ViewAllocateWithoutInitializing (
"FixedHashTable::keys"),
652 const KeyType initMinKey = this->minKey_;
653 const KeyType initMaxKey = this->maxKey_;
654 this->init (keys_d, startingValue, initMinKey, initMaxKey,
655 initMinKey, initMinKey,
false);
658 #ifdef HAVE_TPETRA_DEBUG
659 typedef typename keys_type::size_type size_type;
660 TEUCHOS_TEST_FOR_EXCEPTION
661 (keys_.extent (0) !=
static_cast<size_type
> (keys.size ()),
662 std::logic_error,
"Tpetra::Details::FixedHashTable constructor: "
663 "keepKeys is true, but on return, keys_.extent(0) = " <<
664 keys_.extent (0) <<
" != keys.size() = " << keys.size () <<
665 ". Please report this bug to the Tpetra developers.");
669 #ifdef HAVE_TPETRA_DEBUG
674 template<
class KeyType,
class ValueType,
class DeviceType>
677 const ValueType startingValue,
678 const bool keepKeys) :
679 minKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
680 maxKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
681 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
682 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
683 minVal_ (startingValue),
684 maxVal_ (keys.size () == 0 ?
686 static_cast<ValueType> (startingValue + keys.size () - 1)),
687 firstContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
688 lastContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
689 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
690 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
691 contiguousValues_ (true),
692 checkedForDuplicateKeys_ (false),
693 hasDuplicateKeys_ (false)
695 typedef typename keys_type::non_const_type nonconst_keys_type;
700 host_input_keys_type keys_k (keys.size () == 0 ? NULL : keys.getRawPtr (),
702 using Kokkos::ViewAllocateWithoutInitializing;
703 nonconst_keys_type keys_d (ViewAllocateWithoutInitializing (
"FixedHashTable::keys"),
707 const KeyType initMinKey = ::Kokkos::Details::ArithTraits<KeyType>::max ();
720 const KeyType initMaxKey = ::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
721 ::Kokkos::Details::ArithTraits<KeyType>::min () :
722 -::Kokkos::Details::ArithTraits<KeyType>::max ();
723 this->init (keys_d, startingValue, initMinKey, initMaxKey,
724 initMinKey, initMinKey,
false);
727 #ifdef HAVE_TPETRA_DEBUG
728 typedef typename keys_type::size_type size_type;
729 TEUCHOS_TEST_FOR_EXCEPTION
730 (keys_.extent (0) !=
static_cast<size_type
> (keys.size ()),
731 std::logic_error,
"Tpetra::Details::FixedHashTable constructor: "
732 "keepKeys is true, but on return, keys_.extent(0) = " <<
733 keys_.extent (0) <<
" != keys.size() = " << keys.size () <<
734 ". Please report this bug to the Tpetra developers.");
738 #ifdef HAVE_TPETRA_DEBUG
743 template<
class KeyType,
class ValueType,
class DeviceType>
746 const KeyType firstContigKey,
747 const KeyType lastContigKey,
748 const ValueType startingValue,
749 const bool keepKeys) :
750 minKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
751 maxKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
752 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
753 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
754 minVal_ (startingValue),
755 maxVal_ (keys.size () == 0 ?
757 static_cast<ValueType> (startingValue + keys.size () - 1)),
758 firstContigKey_ (firstContigKey),
759 lastContigKey_ (lastContigKey),
760 contiguousValues_ (true),
761 checkedForDuplicateKeys_ (false),
762 hasDuplicateKeys_ (false)
764 const KeyType initMinKey = ::Kokkos::Details::ArithTraits<KeyType>::max ();
777 const KeyType initMaxKey = ::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
778 ::Kokkos::Details::ArithTraits<KeyType>::min () :
779 -::Kokkos::Details::ArithTraits<KeyType>::max ();
780 this->init (keys, startingValue, initMinKey, initMaxKey,
781 firstContigKey, lastContigKey,
true);
784 #ifdef HAVE_TPETRA_DEBUG
785 typedef typename keys_type::size_type size_type;
786 TEUCHOS_TEST_FOR_EXCEPTION
787 (keys_.extent (0) !=
static_cast<size_type
> (keys.size ()),
788 std::logic_error,
"Tpetra::Details::FixedHashTable constructor: "
789 "keepKeys is true, but on return, keys_.extent(0) = " <<
790 keys_.extent (0) <<
" != keys.size() = " << keys.size () <<
791 ". Please report this bug to the Tpetra developers.");
795 #ifdef HAVE_TPETRA_DEBUG
800 template<
class KeyType,
class ValueType,
class DeviceType>
803 const KeyType firstContigKey,
804 const KeyType lastContigKey,
805 const ValueType startingValue,
806 const bool keepKeys) :
807 minKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
808 maxKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
809 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
810 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
811 minVal_ (startingValue),
812 maxVal_ (keys.size () == 0 ?
814 static_cast<ValueType> (startingValue + keys.size () - 1)),
815 firstContigKey_ (firstContigKey),
816 lastContigKey_ (lastContigKey),
817 contiguousValues_ (true),
818 checkedForDuplicateKeys_ (false),
819 hasDuplicateKeys_ (false)
821 typedef typename keys_type::non_const_type nonconst_keys_type;
826 host_input_keys_type keys_k (keys.size () == 0 ? NULL : keys.getRawPtr (),
828 using Kokkos::ViewAllocateWithoutInitializing;
829 nonconst_keys_type keys_d (ViewAllocateWithoutInitializing (
"FixedHashTable::keys"),
833 const KeyType initMinKey = ::Kokkos::Details::ArithTraits<KeyType>::max ();
846 const KeyType initMaxKey = ::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
847 ::Kokkos::Details::ArithTraits<KeyType>::min () :
848 -::Kokkos::Details::ArithTraits<KeyType>::max ();
849 this->init (keys_d, startingValue, initMinKey, initMaxKey,
850 firstContigKey, lastContigKey,
true);
853 #ifdef HAVE_TPETRA_DEBUG
854 typedef typename keys_type::size_type size_type;
855 TEUCHOS_TEST_FOR_EXCEPTION
856 (keys_.extent (0) !=
static_cast<size_type
> (keys.size ()),
857 std::logic_error,
"Tpetra::Details::FixedHashTable constructor: "
858 "keepKeys is true, but on return, keys_.extent(0) = " <<
859 keys_.extent (0) <<
" != keys.size() = " << keys.size () <<
860 ". Please report this bug to the Tpetra developers.");
864 #ifdef HAVE_TPETRA_DEBUG
869 template<
class KeyType,
class ValueType,
class DeviceType>
872 const ValueType startingValue) :
874 minKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
875 maxKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
876 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
877 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
878 minVal_ (startingValue),
879 maxVal_ (keys.size () == 0 ?
881 static_cast<ValueType> (startingValue + keys.size () - 1)),
882 firstContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
883 lastContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
884 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
885 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
886 contiguousValues_ (true),
887 checkedForDuplicateKeys_ (false),
888 hasDuplicateKeys_ (false)
890 const KeyType initMinKey = ::Kokkos::Details::ArithTraits<KeyType>::max ();
903 const KeyType initMaxKey = ::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
904 ::Kokkos::Details::ArithTraits<KeyType>::min () :
905 -::Kokkos::Details::ArithTraits<KeyType>::max ();
906 this->init (keys, startingValue, initMinKey, initMaxKey,
907 initMinKey, initMinKey,
false);
909 #ifdef HAVE_TPETRA_DEBUG
914 template<
class KeyType,
class ValueType,
class DeviceType>
917 const Teuchos::ArrayView<const ValueType>& vals) :
918 minKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
919 maxKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
920 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
921 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
922 minVal_ (::Kokkos::
Details::ArithTraits<ValueType>::max ()),
923 maxVal_ (::Kokkos::
Details::ArithTraits<ValueType>::is_integer ?
924 ::Kokkos::
Details::ArithTraits<ValueType>::min () :
925 -::Kokkos::
Details::ArithTraits<ValueType>::max ()),
926 firstContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
927 lastContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
928 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
929 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
930 contiguousValues_ (false),
931 checkedForDuplicateKeys_ (false),
932 hasDuplicateKeys_ (false)
937 host_input_keys_type keys_k (keys.size () == 0 ? NULL : keys.getRawPtr (),
939 host_input_vals_type vals_k (vals.size () == 0 ? NULL : vals.getRawPtr (),
941 const KeyType initMinKey = ::Kokkos::Details::ArithTraits<KeyType>::max ();
954 const KeyType initMaxKey = ::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
955 ::Kokkos::Details::ArithTraits<KeyType>::min () :
956 -::Kokkos::Details::ArithTraits<KeyType>::max ();
957 this->init (keys_k, vals_k, initMinKey, initMaxKey);
959 #ifdef HAVE_TPETRA_DEBUG
964 template<
class KeyType,
class ValueType,
class DeviceType>
967 init (
const keys_type& keys,
968 ValueType startingValue,
971 KeyType firstContigKey,
972 KeyType lastContigKey,
973 const bool computeInitContigKeys)
975 using Kokkos::subview;
976 using Kokkos::ViewAllocateWithoutInitializing;
977 using Teuchos::TypeNameTraits;
978 typedef typename std::decay<decltype (keys.extent (0)) >::type size_type;
979 const char prefix[] =
"Tpetra::Details::FixedHashTable: ";
981 const offset_type numKeys =
static_cast<offset_type
> (keys.extent (0));
983 const offset_type theMaxVal = ::Kokkos::Details::ArithTraits<offset_type>::max ();
984 const size_type maxValST =
static_cast<size_type
> (theMaxVal);
985 TEUCHOS_TEST_FOR_EXCEPTION
986 (keys.extent (0) > maxValST, std::invalid_argument, prefix <<
"The "
987 "number of keys " << keys.extent (0) <<
" does not fit in "
988 "offset_type = " << TypeNameTraits<offset_type>::name () <<
", whose "
989 "max value is " << theMaxVal <<
". This means that it is not possible to "
990 "use this constructor.");
992 TEUCHOS_TEST_FOR_EXCEPTION
993 (
static_cast<unsigned long long> (numKeys) >
994 static_cast<unsigned long long> (::Kokkos::Details::ArithTraits<ValueType>::max ()),
995 std::invalid_argument,
"Tpetra::Details::FixedHashTable: The number of "
996 "keys " << numKeys <<
" is greater than the maximum representable "
997 "ValueType value " << ::Kokkos::Details::ArithTraits<ValueType>::max () <<
". "
998 "This means that it is not possible to use this constructor.");
999 TEUCHOS_TEST_FOR_EXCEPTION
1000 (numKeys >
static_cast<offset_type
> (INT_MAX), std::logic_error, prefix <<
1001 "This class currently only works when the number of keys is <= INT_MAX = "
1002 << INT_MAX <<
". If this is a problem for you, please talk to the Tpetra "
1005 const bool buildInParallel =
1006 FHT::worthBuildingFixedHashTableInParallel<execution_space> ();
1017 if (computeInitContigKeys) {
1036 firstContigKey_ = keys[0];
1040 lastContigKey_ = firstContigKey_ + 1;
1046 for (offset_type k = 1; k < numKeys; ++k) {
1047 if (lastContigKey_ != keys[k]) {
1056 firstContigKey_ = firstContigKey;
1057 lastContigKey_ = lastContigKey;
1060 offset_type startIndex;
1062 initMinKey = std::min (initMinKey, firstContigKey_);
1063 initMaxKey = std::max (initMaxKey, lastContigKey_);
1064 startIndex =
static_cast<offset_type
> (lastContigKey_ - firstContigKey_);
1069 const offset_type theNumKeys = numKeys - startIndex;
1070 const offset_type size = hash_type::getRecommendedSize (theNumKeys);
1071 #ifdef HAVE_TPETRA_DEBUG
1072 TEUCHOS_TEST_FOR_EXCEPTION(
1073 size == 0 && numKeys != 0, std::logic_error,
1074 "Tpetra::Details::FixedHashTable constructor: "
1075 "getRecommendedSize(" << numKeys <<
") returned zero, "
1076 "even though the number of keys " << numKeys <<
" is nonzero. "
1077 "Please report this bug to the Tpetra developers.");
1080 subview (keys, std::pair<offset_type, offset_type> (startIndex, numKeys));
1087 typedef typename ptr_type::non_const_type counts_type;
1088 counts_type counts (
"FixedHashTable::counts", size);
1099 if (buildInParallel) {
1100 FHT::CountBuckets<counts_type, keys_type> functor (counts, theKeys, size);
1101 using execution_space =
typename counts_type::execution_space;
1102 using range_type = Kokkos::RangePolicy<execution_space, offset_type>;
1103 const char kernelLabel[] =
"Tpetra::Details::FixedHashTable CountBuckets";
1105 using key_type =
typename keys_type::non_const_value_type;
1106 Kokkos::pair<int, key_type> err;
1107 Kokkos::parallel_reduce (kernelLabel, range_type (0, theNumKeys),
1109 TEUCHOS_TEST_FOR_EXCEPTION
1110 (err.first != 0, std::logic_error,
"Tpetra::Details::FixedHashTable "
1111 "constructor: CountBuckets found a key " << err.second <<
" that "
1112 "results in an out-of-bounds hash value.");
1115 Kokkos::parallel_for (kernelLabel, range_type (0, theNumKeys), functor);
1123 auto countsHost = Kokkos::create_mirror_view (counts);
1127 for (offset_type k = 0; k < theNumKeys; ++k) {
1128 using key_type =
typename keys_type::non_const_value_type;
1129 const key_type key = theKeys[k];
1131 using hash_value_type =
typename hash_type::result_type;
1132 const hash_value_type hashVal = hash_type::hashFunc (key, size);
1133 TEUCHOS_TEST_FOR_EXCEPTION
1134 (hashVal < hash_value_type (0) ||
1135 hashVal >= hash_value_type (countsHost.extent (0)),
1136 std::logic_error,
"Tpetra::Details::FixedHashTable "
1137 "constructor: Sequential CountBuckets found a key " << key
1138 <<
" that results in an out-of-bounds hash value.");
1140 ++countsHost[hashVal];
1148 execution_space().fence ();
1151 typename ptr_type::non_const_type ptr (
"FixedHashTable::ptr", size+1);
1167 if (buildInParallel) {
1171 if (! buildInParallel || debug) {
1172 Kokkos::HostSpace hostMemSpace;
1173 auto counts_h = Kokkos::create_mirror_view (hostMemSpace, counts);
1175 auto ptr_h = Kokkos::create_mirror_view (hostMemSpace, ptr);
1177 #ifdef KOKKOS_ENABLE_SERIAL
1178 Kokkos::Serial hostExecSpace;
1180 Kokkos::DefaultHostExecutionSpace hostExecSpace;
1188 for (offset_type i = 0; i < size; ++i) {
1189 if (ptr_h[i+1] != ptr_h[i] + counts_h[i]) {
1193 TEUCHOS_TEST_FOR_EXCEPTION
1194 (bad, std::logic_error,
"Tpetra::Details::FixedHashTable "
1195 "constructor: computeOffsetsFromCounts gave an incorrect "
1203 execution_space().fence ();
1207 using Kokkos::ViewAllocateWithoutInitializing;
1208 typedef typename val_type::non_const_type nonconst_val_type;
1209 nonconst_val_type val (ViewAllocateWithoutInitializing (
"FixedHashTable::pairs"),
1213 typedef FHT::FillPairs<
typename val_type::non_const_type, keys_type,
1214 typename ptr_type::non_const_type> functor_type;
1215 typename functor_type::value_type result (initMinKey, initMaxKey);
1217 const ValueType newStartingValue = startingValue +
static_cast<ValueType
> (startIndex);
1218 if (buildInParallel) {
1219 functor_type functor (val, counts, ptr, theKeys, newStartingValue,
1220 initMinKey, initMaxKey);
1221 typedef Kokkos::RangePolicy<execution_space, offset_type> range_type;
1222 Kokkos::parallel_reduce (range_type (0, theNumKeys), functor, result);
1225 for (offset_type k = 0; k < theNumKeys; ++k) {
1226 typedef typename hash_type::result_type hash_value_type;
1227 const KeyType key = theKeys[k];
1228 if (key > result.maxKey_) {
1229 result.maxKey_ = key;
1231 if (key < result.minKey_) {
1232 result.minKey_ = key;
1234 const ValueType theVal = newStartingValue +
static_cast<ValueType
> (k);
1235 const hash_value_type hashVal = hash_type::hashFunc (key, size);
1241 const offset_type count = counts[hashVal];
1244 result.success_ =
false;
1249 const offset_type curPos = ptr[hashVal+1] - count;
1252 val[curPos].first = key;
1253 val[curPos].second = theVal;
1270 minKey_ = result.minKey_;
1271 maxKey_ = result.maxKey_;
1276 template<
class KeyType,
class ValueType,
class DeviceType>
1278 FixedHashTable<KeyType, ValueType, DeviceType>::
1279 init (
const host_input_keys_type& keys,
1280 const host_input_vals_type& vals,
1284 const offset_type numKeys =
static_cast<offset_type
> (keys.extent (0));
1285 TEUCHOS_TEST_FOR_EXCEPTION
1286 (
static_cast<unsigned long long> (numKeys) >
static_cast<unsigned long long> (::Kokkos::Details::ArithTraits<ValueType>::max ()),
1287 std::invalid_argument,
"Tpetra::Details::FixedHashTable: The number of "
1288 "keys " << numKeys <<
" is greater than the maximum representable "
1289 "ValueType value " << ::Kokkos::Details::ArithTraits<ValueType>::max () <<
".");
1290 TEUCHOS_TEST_FOR_EXCEPTION
1291 (numKeys >
static_cast<offset_type
> (INT_MAX), std::logic_error,
"Tpetra::"
1292 "Details::FixedHashTable: This class currently only works when the number "
1293 "of keys is <= INT_MAX = " << INT_MAX <<
". If this is a problem for you"
1294 ", please talk to the Tpetra developers.");
1301 const offset_type size = hash_type::getRecommendedSize (numKeys);
1302 #ifdef HAVE_TPETRA_DEBUG
1303 TEUCHOS_TEST_FOR_EXCEPTION(
1304 size == 0 && numKeys != 0, std::logic_error,
1305 "Tpetra::Details::FixedHashTable constructor: "
1306 "getRecommendedSize(" << numKeys <<
") returned zero, "
1307 "even though the number of keys " << numKeys <<
" is nonzero. "
1308 "Please report this bug to the Tpetra developers.");
1319 typename ptr_type::non_const_type ptr (
"FixedHashTable::ptr", size + 1);
1323 using Kokkos::ViewAllocateWithoutInitializing;
1324 typedef typename val_type::non_const_type nonconst_val_type;
1325 nonconst_val_type val (ViewAllocateWithoutInitializing (
"FixedHashTable::pairs"),
1329 for (offset_type k = 0; k < numKeys; ++k) {
1330 const typename hash_type::result_type hashVal =
1331 hash_type::hashFunc (keys[k], size);
1343 for (offset_type i = 0; i < size; ++i) {
1349 typename ptr_type::non_const_type curRowStart (
"FixedHashTable::curRowStart", size);
1352 FHT::FillPairsResult<KeyType> result (initMinKey, initMaxKey);
1353 for (offset_type k = 0; k < numKeys; ++k) {
1354 typedef typename hash_type::result_type hash_value_type;
1355 const KeyType key = keys[k];
1356 if (key > result.maxKey_) {
1357 result.maxKey_ = key;
1359 if (key < result.minKey_) {
1360 result.minKey_ = key;
1362 const ValueType theVal = vals[k];
1363 if (theVal > maxVal_) {
1366 if (theVal < minVal_) {
1369 const hash_value_type hashVal = hash_type::hashFunc (key, size);
1371 const offset_type offset = curRowStart[hashVal];
1372 const offset_type curPos = ptr[hashVal] + offset;
1373 if (curPos >= ptr[hashVal+1]) {
1374 result.success_ =
false;
1377 val[curPos].first = key;
1378 val[curPos].second = theVal;
1379 ++curRowStart[hashVal];
1383 TEUCHOS_TEST_FOR_EXCEPTION
1384 (! result.success_, std::logic_error,
"Tpetra::Details::FixedHashTable::"
1385 "init: Filling the hash table failed! Please report this bug to the "
1386 "Tpetra developers.");
1391 minKey_ = result.minKey_;
1392 maxKey_ = result.maxKey_;
1396 template <
class KeyType,
class ValueType,
class DeviceType>
1401 if (! checkedForDuplicateKeys_) {
1402 hasDuplicateKeys_ = checkForDuplicateKeys ();
1403 checkedForDuplicateKeys_ =
true;
1405 return hasDuplicateKeys_;
1408 template <
class KeyType,
class ValueType,
class DeviceType>
1413 const offset_type size = this->getSize ();
1417 if (size == 0 || this->numPairs () == 0) {
1421 typedef FHT::CheckForDuplicateKeys<ptr_type, val_type> functor_type;
1422 functor_type functor (val_, ptr_);
1424 typedef Kokkos::RangePolicy<execution_space, offset_type> range_type;
1425 Kokkos::parallel_reduce (range_type (0, size), functor, hasDupKeys);
1426 return hasDupKeys > 0;
1430 template <
class KeyType,
class ValueType,
class DeviceType>
1435 std::ostringstream oss;
1436 oss <<
"FixedHashTable<"
1437 << Teuchos::TypeNameTraits<KeyType>::name () <<
","
1438 << Teuchos::TypeNameTraits<ValueType>::name () <<
">: "
1439 <<
"{ numKeys: " << val_.extent (0)
1440 <<
", tableSize: " << this->getSize () <<
" }";
1444 template <
class KeyType,
class ValueType,
class DeviceType>
1447 describe (Teuchos::FancyOStream& out,
1448 const Teuchos::EVerbosityLevel verbLevel)
const
1452 using Teuchos::OSTab;
1453 using Teuchos::rcpFromRef;
1454 using Teuchos::TypeNameTraits;
1455 using Teuchos::VERB_DEFAULT;
1456 using Teuchos::VERB_NONE;
1457 using Teuchos::VERB_LOW;
1458 using Teuchos::VERB_EXTREME;
1463 Teuchos::EVerbosityLevel vl = verbLevel;
1464 if (vl == VERB_DEFAULT) vl = VERB_LOW;
1466 if (vl == VERB_NONE) {
1469 else if (vl == VERB_LOW) {
1470 out << this->description() << endl;
1473 out <<
"FixedHashTable:" << endl;
1475 OSTab tab1 (rcpFromRef (out));
1481 out <<
"Template parameters:" << endl;
1483 OSTab tab2 (rcpFromRef (out));
1484 out <<
"KeyType: " << TypeNameTraits<KeyType>::name () << endl
1485 <<
"ValueType: " << TypeNameTraits<ValueType>::name () << endl;
1488 const offset_type tableSize = this->getSize ();
1489 const offset_type numKeys = val_.extent (0);
1491 out <<
"Table parameters:" << endl;
1493 OSTab tab2 (rcpFromRef (out));
1494 out <<
"numKeys: " << numKeys << endl
1495 <<
"tableSize: " << tableSize << endl;
1498 if (vl >= VERB_EXTREME) {
1499 out <<
"Contents: ";
1500 if (tableSize == 0 || numKeys == 0) {
1501 out <<
"[]" << endl;
1503 out <<
"[ " << endl;
1505 OSTab tab2 (rcpFromRef (out));
1506 for (offset_type i = 0; i < tableSize; ++i) {
1507 OSTab tab3 (rcpFromRef (out));
1509 for (offset_type k = ptr_[i]; k < ptr_[i+1]; ++k) {
1510 out <<
"(" << val_[k].first <<
"," << val_[k].second <<
")";
1511 if (k + 1 < ptr_[i+1]) {
1537 #define TPETRA_DETAILS_FIXEDHASHTABLE_INSTANT_DEFAULTNODE(LO,GO) \
1538 template class FixedHashTable< GO , LO >;
1549 #define TPETRA_DETAILS_FIXEDHASHTABLE_INSTANT(LO, GO, DEVICE) \
1550 template class FixedHashTable< GO , LO , DEVICE >;
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.
Declare and define the functions Tpetra::Details::computeOffsetsFromCounts and Tpetra::computeOffsets...
static bool debug()
Whether Tpetra is in debug mode.
Functor for checking whether a FixedHashTable has one or more duplicate entries.
KOKKOS_INLINE_FUNCTION void init(value_type &dst) const
Set the initial value of the reduction result.
KOKKOS_INLINE_FUNCTION void operator()(const size_type &i, value_type &dst) const
Parallel loop body.
KOKKOS_INLINE_FUNCTION void join(volatile value_type &dst, const volatile value_type &src) const
Combine two intermediate reduction results.
CheckForDuplicateKeys(const pairs_view_type &pairs, const offsets_view_type &ptr)
Constructor.
Parallel for functor for counting "buckets" in the FixedHashTable.
KOKKOS_INLINE_FUNCTION void init(value_type &dst) const
Set the initial value of the reduction result.
KOKKOS_INLINE_FUNCTION void operator()(const size_type &i) const
Do this for every entry of keys_.
CountBuckets(const counts_view_type &counts, const keys_view_type &keys, const size_type size)
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_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.
bool hasKeys() const
Whether it is safe to call getKey().
std::string description() const
Implementation of Teuchos::Describable interface.
bool hasDuplicateKeys()
Whether the table has any duplicate keys.
Kokkos::View< const KeyType *, Kokkos::LayoutLeft, device_type > keys_type
Type of a 1-D Kokkos::View (array) used to store 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.
Implementation details of Tpetra.
OffsetsViewType::non_const_value_type computeOffsetsFromCounts(const ExecutionSpace &execSpace, const OffsetsViewType &ptr, const CountsViewType &counts)
Compute offsets from counts.
Namespace Tpetra contains the class and methods constituting the Tpetra library.
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.
Reduction result for FillPairs functor below.
KeyType maxKey_
The current maximum key.
KeyType minKey_
The current minimum key.
bool success_
Whether fill succeeded (it can only fail on a bug)
The hash function for FixedHashTable.
ResultType result_type
Type of the return value of the hash function.
static KOKKOS_INLINE_FUNCTION result_type hashFunc(const argument_type &key, const offset_type &size)
The hash function.