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"
51 #endif // TPETRA_USE_MURMUR_HASH
52 #include "Kokkos_ArithTraits.hpp"
53 #include "Teuchos_TypeNameTraits.hpp"
54 #include <type_traits>
77 template<
class ExecSpace>
78 bool worthBuildingFixedHashTableInParallel () {
79 return ExecSpace::concurrency() > 1;
90 template<
class KeyType,
93 class OutputExecSpace,
94 const bool mustDeepCopy =
95 ! std::is_same<
typename InputExecSpace::memory_space,
96 typename OutputExecSpace::memory_space>::value>
97 struct DeepCopyIfNeeded {
103 template<
class KeyType,
105 class InputExecSpace,
106 class OutputExecSpace>
107 struct DeepCopyIfNeeded<KeyType, ArrayLayout, InputExecSpace, OutputExecSpace, true>
109 typedef Kokkos::View<
const KeyType*, ArrayLayout,
110 InputExecSpace, Kokkos::MemoryUnmanaged> input_view_type;
116 typedef Kokkos::View<const KeyType*, ArrayLayout, OutputExecSpace> output_view_type;
118 static output_view_type copy (
const input_view_type& src) {
119 typedef typename output_view_type::non_const_type NC;
121 NC dst (Kokkos::ViewAllocateWithoutInitializing (src.tracker ().label ()),
124 return output_view_type (dst);
129 template<
class KeyType,
131 class InputExecSpace,
132 class OutputExecSpace>
133 struct DeepCopyIfNeeded<KeyType, ArrayLayout, InputExecSpace, OutputExecSpace, false> {
134 typedef Kokkos::View<
const KeyType*, ArrayLayout,
135 InputExecSpace, Kokkos::MemoryUnmanaged> input_view_type;
136 typedef Kokkos::View<
const KeyType*, ArrayLayout, OutputExecSpace,
137 Kokkos::MemoryUnmanaged> output_view_type;
139 static output_view_type copy (
const input_view_type& src) {
140 return output_view_type (src);
162 template<
class CountsViewType,
164 class SizeType =
typename KeysViewType::size_type>
167 typedef CountsViewType counts_view_type;
168 typedef KeysViewType keys_view_type;
169 typedef typename CountsViewType::execution_space execution_space;
170 typedef typename CountsViewType::memory_space memory_space;
171 typedef SizeType size_type;
172 typedef typename keys_view_type::non_const_value_type key_type;
188 const keys_view_type& keys,
189 const size_type size) :
199 KOKKOS_INLINE_FUNCTION
void
205 Kokkos::atomic_increment (&counts_[hashVal]);
210 counts_view_type counts_;
212 keys_view_type keys_;
227 template<
class KeyType>
229 KOKKOS_INLINE_FUNCTION
231 minKey_ (::Kokkos::Details::ArithTraits<KeyType>::max ()),
244 maxKey_ (::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
245 ::Kokkos::Details::ArithTraits<KeyType>::min () :
246 -::Kokkos::Details::ArithTraits<KeyType>::max ()),
249 static_assert (std::is_arithmetic<KeyType>::value,
"FillPairsResult: "
250 "KeyType must be some kind of number type.");
253 KOKKOS_INLINE_FUNCTION
254 FillPairsResult (
const KeyType& initMinKey,
255 const KeyType& initMaxKey) :
260 static_assert (std::is_arithmetic<KeyType>::value,
"FillPairsResult: "
261 "KeyType must be some kind of number type.");
298 template<
class PairsViewType,
300 class CountsViewType,
301 class SizeType =
typename KeysViewType::size_type>
304 typedef typename CountsViewType::non_const_type counts_view_type;
305 typedef typename counts_view_type::const_type offsets_view_type;
307 typedef PairsViewType pairs_view_type;
308 typedef typename KeysViewType::const_type keys_view_type;
309 typedef typename offsets_view_type::execution_space execution_space;
310 typedef typename offsets_view_type::memory_space memory_space;
311 typedef SizeType size_type;
313 typedef typename keys_view_type::non_const_value_type key_type;
314 typedef typename pairs_view_type::non_const_value_type pair_type;
338 const counts_view_type& counts,
339 const offsets_view_type& ptr,
340 const keys_view_type& keys,
341 const typename pair_type::second_type startingValue) :
346 size_ (counts.extent (0)),
347 startingValue_ (startingValue),
348 initMinKey_ (::Kokkos::Details::ArithTraits<key_type>::max ()),
349 initMaxKey_ (::Kokkos::Details::ArithTraits<key_type>::is_integer ?
350 ::Kokkos::Details::ArithTraits<key_type>::min () :
351 -::Kokkos::Details::ArithTraits<key_type>::max ())
373 const counts_view_type& counts,
374 const offsets_view_type& ptr,
375 const keys_view_type& keys,
376 const typename pair_type::second_type startingValue,
377 const key_type initMinKey,
378 const key_type initMaxKey) :
383 size_ (counts.extent (0)),
384 startingValue_ (startingValue),
385 initMinKey_ (initMinKey),
386 initMaxKey_ (initMaxKey)
397 KOKKOS_INLINE_FUNCTION
void
398 join (
volatile value_type& dst,
399 const volatile value_type& src)
const
401 if (src.maxKey_ > dst.maxKey_) {
402 dst.maxKey_ = src.maxKey_;
404 if (src.minKey_ < dst.minKey_) {
405 dst.minKey_ = src.minKey_;
407 dst.success_ = dst.success_ && src.success_;
414 KOKKOS_INLINE_FUNCTION
void
418 typedef typename offsets_view_type::non_const_value_type offset_type;
419 typedef typename pair_type::second_type val_type;
420 typedef typename std::remove_reference< decltype( counts_[0] ) >::type atomic_incr_type;
422 const key_type key = keys_[i];
429 const val_type theVal = startingValue_ +
static_cast<val_type
> (i);
433 const offset_type count = Kokkos::atomic_fetch_add (&counts_[hashVal], atomic_incr_type(-1));
438 const offset_type curPos = ptr_[hashVal+1] - count;
440 pairs_[curPos].first = key;
441 pairs_[curPos].second = theVal;
446 pairs_view_type pairs_;
447 counts_view_type counts_;
448 offsets_view_type ptr_;
449 keys_view_type keys_;
451 typename pair_type::second_type startingValue_;
453 key_type initMinKey_;
455 key_type initMaxKey_;
481 template<
class OffsetsViewType,
483 class SizeType =
typename OffsetsViewType::size_type>
486 typedef typename OffsetsViewType::const_type offsets_view_type;
487 typedef typename PairsViewType::const_type pairs_view_type;
488 typedef typename offsets_view_type::execution_space execution_space;
489 typedef typename offsets_view_type::memory_space memory_space;
490 typedef SizeType size_type;
493 typedef int value_type;
500 const offsets_view_type& ptr) :
503 size_ (ptr_.extent (0) == 0 ?
509 KOKKOS_INLINE_FUNCTION
void init (value_type& dst)
const
515 KOKKOS_INLINE_FUNCTION
void
516 join (
volatile value_type& dst,
517 const volatile value_type& src)
const
519 dst = dst + src > 0?1:0;
523 KOKKOS_INLINE_FUNCTION
void
526 typedef typename offsets_view_type::non_const_value_type offset_type;
527 typedef typename pairs_view_type::non_const_value_type pair_type;
528 typedef typename pair_type::first_type key_type;
534 const offset_type beg = ptr_[i];
535 const offset_type end = ptr_[i+1];
536 bool foundDuplicateKey =
false;
541 for (offset_type j = beg + 1; j < end; ++j) {
542 const key_type curKey = pairs_[j].first;
543 for (offset_type k = beg; k < j; ++k) {
544 if (pairs_[k].first == curKey) {
545 foundDuplicateKey =
true;
550 dst = (dst>0) || foundDuplicateKey?1:0;
555 pairs_view_type pairs_;
556 offsets_view_type ptr_;
566 template<
class KeyType,
class ValueType,
class DeviceType>
576 return keys_.extent (0) == val_.extent (0);
579 template<
class KeyType,
class ValueType,
class DeviceType>
588 template<
class KeyType,
class ValueType,
class DeviceType>
591 minKey_ (::Kokkos::Details::ArithTraits<KeyType>::max ()),
592 maxKey_ (::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
593 ::Kokkos::Details::ArithTraits<KeyType>::min () :
594 -::Kokkos::Details::ArithTraits<KeyType>::max ()),
595 minVal_ (::Kokkos::Details::ArithTraits<ValueType>::max ()),
596 maxVal_ (::Kokkos::Details::ArithTraits<ValueType>::is_integer ?
597 ::Kokkos::Details::ArithTraits<ValueType>::min () :
598 -::Kokkos::Details::ArithTraits<ValueType>::max ()),
599 firstContigKey_ (::Kokkos::Details::ArithTraits<KeyType>::max ()),
600 lastContigKey_ (::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
601 ::Kokkos::Details::ArithTraits<KeyType>::min () :
602 -::Kokkos::Details::ArithTraits<KeyType>::max ()),
603 contiguousValues_ (true),
604 checkedForDuplicateKeys_ (true),
605 hasDuplicateKeys_ (false)
607 #ifdef HAVE_TPETRA_DEBUG
609 #endif // HAVE_TPETRA_DEBUG
612 template<
class KeyType,
class ValueType,
class DeviceType>
616 minKey_ (::Kokkos::Details::ArithTraits<KeyType>::max ()),
617 maxKey_ (::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
618 ::Kokkos::Details::ArithTraits<KeyType>::min () :
619 -::Kokkos::Details::ArithTraits<KeyType>::max ()),
621 maxVal_ (keys.size () == 0 ?
622 static_cast<ValueType> (0) :
623 static_cast<ValueType> (keys.size () - 1)),
624 firstContigKey_ (::Kokkos::Details::ArithTraits<KeyType>::max ()),
625 lastContigKey_ (::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
626 ::Kokkos::Details::ArithTraits<KeyType>::min () :
627 -::Kokkos::Details::ArithTraits<KeyType>::max ()),
628 contiguousValues_ (true),
629 checkedForDuplicateKeys_ (false),
630 hasDuplicateKeys_ (false)
632 const ValueType startingValue =
static_cast<ValueType
> (0);
633 const KeyType initMinKey = this->minKey_;
634 const KeyType initMaxKey = this->maxKey_;
635 this->init (keys, startingValue, initMinKey, initMaxKey,
636 initMinKey, initMinKey,
false);
638 #ifdef HAVE_TPETRA_DEBUG
640 #endif // HAVE_TPETRA_DEBUG
643 template<
class KeyType,
class ValueType,
class DeviceType>
646 const bool keepKeys) :
647 minKey_ (::Kokkos::Details::ArithTraits<KeyType>::max ()),
648 maxKey_ (::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
649 ::Kokkos::Details::ArithTraits<KeyType>::min () :
650 -::Kokkos::Details::ArithTraits<KeyType>::max ()),
652 maxVal_ (keys.size () == 0 ?
653 static_cast<ValueType> (0) :
654 static_cast<ValueType> (keys.size () - 1)),
655 firstContigKey_ (::Kokkos::Details::ArithTraits<KeyType>::max ()),
656 lastContigKey_ (::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
657 ::Kokkos::Details::ArithTraits<KeyType>::min () :
658 -::Kokkos::Details::ArithTraits<KeyType>::max ()),
659 contiguousValues_ (true),
660 checkedForDuplicateKeys_ (false),
661 hasDuplicateKeys_ (false)
663 typedef typename keys_type::non_const_type nonconst_keys_type;
668 const ValueType startingValue =
static_cast<ValueType
> (0);
669 host_input_keys_type keys_k (keys.size () == 0 ? NULL : keys.getRawPtr (),
671 using Kokkos::ViewAllocateWithoutInitializing;
672 nonconst_keys_type keys_d (ViewAllocateWithoutInitializing (
"FixedHashTable::keys"),
675 const KeyType initMinKey = this->minKey_;
676 const KeyType initMaxKey = this->maxKey_;
677 this->init (keys_d, startingValue, initMinKey, initMaxKey,
678 initMinKey, initMinKey,
false);
681 #ifdef HAVE_TPETRA_DEBUG
682 typedef typename keys_type::size_type size_type;
683 TEUCHOS_TEST_FOR_EXCEPTION
684 (keys_.extent (0) !=
static_cast<size_type
> (keys.size ()),
685 std::logic_error,
"Tpetra::Details::FixedHashTable constructor: "
686 "keepKeys is true, but on return, keys_.extent(0) = " <<
687 keys_.extent (0) <<
" != keys.size() = " << keys.size () <<
688 ". Please report this bug to the Tpetra developers.");
689 #endif // HAVE_TPETRA_DEBUG
692 #ifdef HAVE_TPETRA_DEBUG
694 #endif // HAVE_TPETRA_DEBUG
697 template<
class KeyType,
class ValueType,
class DeviceType>
700 const ValueType startingValue,
701 const bool keepKeys) :
702 minKey_ (::Kokkos::Details::ArithTraits<KeyType>::max ()),
703 maxKey_ (::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
704 ::Kokkos::Details::ArithTraits<KeyType>::min () :
705 -::Kokkos::Details::ArithTraits<KeyType>::max ()),
706 minVal_ (startingValue),
707 maxVal_ (keys.size () == 0 ?
709 static_cast<ValueType> (startingValue + keys.size () - 1)),
710 firstContigKey_ (::Kokkos::Details::ArithTraits<KeyType>::max ()),
711 lastContigKey_ (::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
712 ::Kokkos::Details::ArithTraits<KeyType>::min () :
713 -::Kokkos::Details::ArithTraits<KeyType>::max ()),
714 contiguousValues_ (true),
715 checkedForDuplicateKeys_ (false),
716 hasDuplicateKeys_ (false)
718 typedef typename keys_type::non_const_type nonconst_keys_type;
723 host_input_keys_type keys_k (keys.size () == 0 ? NULL : keys.getRawPtr (),
725 using Kokkos::ViewAllocateWithoutInitializing;
726 nonconst_keys_type keys_d (ViewAllocateWithoutInitializing (
"FixedHashTable::keys"),
730 const KeyType initMinKey = ::Kokkos::Details::ArithTraits<KeyType>::max ();
743 const KeyType initMaxKey = ::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
744 ::Kokkos::Details::ArithTraits<KeyType>::min () :
745 -::Kokkos::Details::ArithTraits<KeyType>::max ();
746 this->init (keys_d, startingValue, initMinKey, initMaxKey,
747 initMinKey, initMinKey,
false);
750 #ifdef HAVE_TPETRA_DEBUG
751 typedef typename keys_type::size_type size_type;
752 TEUCHOS_TEST_FOR_EXCEPTION
753 (keys_.extent (0) !=
static_cast<size_type
> (keys.size ()),
754 std::logic_error,
"Tpetra::Details::FixedHashTable constructor: "
755 "keepKeys is true, but on return, keys_.extent(0) = " <<
756 keys_.extent (0) <<
" != keys.size() = " << keys.size () <<
757 ". Please report this bug to the Tpetra developers.");
758 #endif // HAVE_TPETRA_DEBUG
761 #ifdef HAVE_TPETRA_DEBUG
763 #endif // HAVE_TPETRA_DEBUG
766 template<
class KeyType,
class ValueType,
class DeviceType>
769 const KeyType firstContigKey,
770 const KeyType lastContigKey,
771 const ValueType startingValue,
772 const bool keepKeys) :
773 minKey_ (::Kokkos::Details::ArithTraits<KeyType>::max ()),
774 maxKey_ (::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
775 ::Kokkos::Details::ArithTraits<KeyType>::min () :
776 -::Kokkos::Details::ArithTraits<KeyType>::max ()),
777 minVal_ (startingValue),
778 maxVal_ (keys.size () == 0 ?
780 static_cast<ValueType> (startingValue + keys.size () - 1)),
781 firstContigKey_ (firstContigKey),
782 lastContigKey_ (lastContigKey),
783 contiguousValues_ (true),
784 checkedForDuplicateKeys_ (false),
785 hasDuplicateKeys_ (false)
787 const KeyType initMinKey = ::Kokkos::Details::ArithTraits<KeyType>::max ();
800 const KeyType initMaxKey = ::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
801 ::Kokkos::Details::ArithTraits<KeyType>::min () :
802 -::Kokkos::Details::ArithTraits<KeyType>::max ();
803 this->init (keys, startingValue, initMinKey, initMaxKey,
804 firstContigKey, lastContigKey,
true);
807 #ifdef HAVE_TPETRA_DEBUG
808 typedef typename keys_type::size_type size_type;
809 TEUCHOS_TEST_FOR_EXCEPTION
810 (keys_.extent (0) !=
static_cast<size_type
> (keys.size ()),
811 std::logic_error,
"Tpetra::Details::FixedHashTable constructor: "
812 "keepKeys is true, but on return, keys_.extent(0) = " <<
813 keys_.extent (0) <<
" != keys.size() = " << keys.size () <<
814 ". Please report this bug to the Tpetra developers.");
815 #endif // HAVE_TPETRA_DEBUG
818 #ifdef HAVE_TPETRA_DEBUG
820 #endif // HAVE_TPETRA_DEBUG
823 template<
class KeyType,
class ValueType,
class DeviceType>
826 const KeyType firstContigKey,
827 const KeyType lastContigKey,
828 const ValueType startingValue,
829 const bool keepKeys) :
830 minKey_ (::Kokkos::Details::ArithTraits<KeyType>::max ()),
831 maxKey_ (::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
832 ::Kokkos::Details::ArithTraits<KeyType>::min () :
833 -::Kokkos::Details::ArithTraits<KeyType>::max ()),
834 minVal_ (startingValue),
835 maxVal_ (keys.size () == 0 ?
837 static_cast<ValueType> (startingValue + keys.size () - 1)),
838 firstContigKey_ (firstContigKey),
839 lastContigKey_ (lastContigKey),
840 contiguousValues_ (true),
841 checkedForDuplicateKeys_ (false),
842 hasDuplicateKeys_ (false)
844 typedef typename keys_type::non_const_type nonconst_keys_type;
849 host_input_keys_type keys_k (keys.size () == 0 ? NULL : keys.getRawPtr (),
851 using Kokkos::ViewAllocateWithoutInitializing;
852 nonconst_keys_type keys_d (ViewAllocateWithoutInitializing (
"FixedHashTable::keys"),
856 const KeyType initMinKey = ::Kokkos::Details::ArithTraits<KeyType>::max ();
869 const KeyType initMaxKey = ::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
870 ::Kokkos::Details::ArithTraits<KeyType>::min () :
871 -::Kokkos::Details::ArithTraits<KeyType>::max ();
872 this->init (keys_d, startingValue, initMinKey, initMaxKey,
873 firstContigKey, lastContigKey,
true);
876 #ifdef HAVE_TPETRA_DEBUG
877 typedef typename keys_type::size_type size_type;
878 TEUCHOS_TEST_FOR_EXCEPTION
879 (keys_.extent (0) !=
static_cast<size_type
> (keys.size ()),
880 std::logic_error,
"Tpetra::Details::FixedHashTable constructor: "
881 "keepKeys is true, but on return, keys_.extent(0) = " <<
882 keys_.extent (0) <<
" != keys.size() = " << keys.size () <<
883 ". Please report this bug to the Tpetra developers.");
884 #endif // HAVE_TPETRA_DEBUG
887 #ifdef HAVE_TPETRA_DEBUG
889 #endif // HAVE_TPETRA_DEBUG
892 template<
class KeyType,
class ValueType,
class DeviceType>
895 const ValueType startingValue) :
897 minKey_ (::Kokkos::Details::ArithTraits<KeyType>::max ()),
898 maxKey_ (::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
899 ::Kokkos::Details::ArithTraits<KeyType>::min () :
900 -::Kokkos::Details::ArithTraits<KeyType>::max ()),
901 minVal_ (startingValue),
902 maxVal_ (keys.size () == 0 ?
904 static_cast<ValueType> (startingValue + keys.size () - 1)),
905 firstContigKey_ (::Kokkos::Details::ArithTraits<KeyType>::max ()),
906 lastContigKey_ (::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
907 ::Kokkos::Details::ArithTraits<KeyType>::min () :
908 -::Kokkos::Details::ArithTraits<KeyType>::max ()),
909 contiguousValues_ (true),
910 checkedForDuplicateKeys_ (false),
911 hasDuplicateKeys_ (false)
913 const KeyType initMinKey = ::Kokkos::Details::ArithTraits<KeyType>::max ();
926 const KeyType initMaxKey = ::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
927 ::Kokkos::Details::ArithTraits<KeyType>::min () :
928 -::Kokkos::Details::ArithTraits<KeyType>::max ();
929 this->init (keys, startingValue, initMinKey, initMaxKey,
930 initMinKey, initMinKey,
false);
932 #ifdef HAVE_TPETRA_DEBUG
934 #endif // HAVE_TPETRA_DEBUG
937 template<
class KeyType,
class ValueType,
class DeviceType>
940 const Teuchos::ArrayView<const ValueType>& vals) :
941 minKey_ (::Kokkos::Details::ArithTraits<KeyType>::max ()),
942 maxKey_ (::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
943 ::Kokkos::Details::ArithTraits<KeyType>::min () :
944 -::Kokkos::Details::ArithTraits<KeyType>::max ()),
945 minVal_ (::Kokkos::Details::ArithTraits<ValueType>::max ()),
946 maxVal_ (::Kokkos::Details::ArithTraits<ValueType>::is_integer ?
947 ::Kokkos::Details::ArithTraits<ValueType>::min () :
948 -::Kokkos::Details::ArithTraits<ValueType>::max ()),
949 firstContigKey_ (::Kokkos::Details::ArithTraits<KeyType>::max ()),
950 lastContigKey_ (::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
951 ::Kokkos::Details::ArithTraits<KeyType>::min () :
952 -::Kokkos::Details::ArithTraits<KeyType>::max ()),
953 contiguousValues_ (false),
954 checkedForDuplicateKeys_ (false),
955 hasDuplicateKeys_ (false)
960 host_input_keys_type keys_k (keys.size () == 0 ? NULL : keys.getRawPtr (),
962 host_input_vals_type vals_k (vals.size () == 0 ? NULL : vals.getRawPtr (),
964 const KeyType initMinKey = ::Kokkos::Details::ArithTraits<KeyType>::max ();
977 const KeyType initMaxKey = ::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
978 ::Kokkos::Details::ArithTraits<KeyType>::min () :
979 -::Kokkos::Details::ArithTraits<KeyType>::max ();
980 this->init (keys_k, vals_k, initMinKey, initMaxKey);
982 #ifdef HAVE_TPETRA_DEBUG
984 #endif // HAVE_TPETRA_DEBUG
987 template<
class KeyType,
class ValueType,
class DeviceType>
990 init (
const keys_type& keys,
991 ValueType startingValue,
994 KeyType firstContigKey,
995 KeyType lastContigKey,
996 const bool computeInitContigKeys)
998 using Kokkos::subview;
999 using Kokkos::ViewAllocateWithoutInitializing;
1000 using Teuchos::TypeNameTraits;
1001 typedef typename std::decay<decltype (keys.extent (0)) >::type size_type;
1002 const char prefix[] =
"Tpetra::Details::FixedHashTable: ";
1004 const offset_type numKeys =
static_cast<offset_type
> (keys.extent (0));
1006 const offset_type theMaxVal = ::Kokkos::Details::ArithTraits<offset_type>::max ();
1007 const size_type maxValST =
static_cast<size_type
> (theMaxVal);
1008 TEUCHOS_TEST_FOR_EXCEPTION
1009 (keys.extent (0) > maxValST, std::invalid_argument, prefix <<
"The "
1010 "number of keys " << keys.extent (0) <<
" does not fit in "
1011 "offset_type = " << TypeNameTraits<offset_type>::name () <<
", whose "
1012 "max value is " << theMaxVal <<
". This means that it is not possible to "
1013 "use this constructor.");
1015 TEUCHOS_TEST_FOR_EXCEPTION
1016 (static_cast<unsigned long long> (numKeys) >
1017 static_cast<unsigned long long> (::Kokkos::Details::ArithTraits<ValueType>::max ()),
1018 std::invalid_argument,
"Tpetra::Details::FixedHashTable: The number of "
1019 "keys " << numKeys <<
" is greater than the maximum representable "
1020 "ValueType value " << ::Kokkos::Details::ArithTraits<ValueType>::max () <<
". "
1021 "This means that it is not possible to use this constructor.");
1022 TEUCHOS_TEST_FOR_EXCEPTION
1023 (numKeys > static_cast<offset_type> (INT_MAX), std::logic_error, prefix <<
1024 "This class currently only works when the number of keys is <= INT_MAX = "
1025 << INT_MAX <<
". If this is a problem for you, please talk to the Tpetra "
1028 const bool buildInParallel =
1029 FHT::worthBuildingFixedHashTableInParallel<execution_space> ();
1039 if (computeInitContigKeys) {
1058 firstContigKey_ = keys[0];
1062 lastContigKey_ = firstContigKey_ + 1;
1068 for (offset_type k = 1; k < numKeys; ++k) {
1069 if (lastContigKey_ != keys[k]) {
1078 firstContigKey_ = firstContigKey;
1079 lastContigKey_ = lastContigKey;
1082 offset_type startIndex;
1084 initMinKey = std::min (initMinKey, firstContigKey_);
1085 initMaxKey = std::max (initMaxKey, lastContigKey_);
1086 startIndex =
static_cast<offset_type
> (lastContigKey_ - firstContigKey_);
1091 const offset_type theNumKeys = numKeys - startIndex;
1092 const offset_type size = hash_type::getRecommendedSize (theNumKeys);
1093 #ifdef HAVE_TPETRA_DEBUG
1094 TEUCHOS_TEST_FOR_EXCEPTION(
1095 size == 0 && numKeys != 0, std::logic_error,
1096 "Tpetra::Details::FixedHashTable constructor: "
1097 "getRecommendedSize(" << numKeys <<
") returned zero, "
1098 "even though the number of keys " << numKeys <<
" is nonzero. "
1099 "Please report this bug to the Tpetra developers.");
1100 #endif // HAVE_TPETRA_DEBUG
1102 subview (keys, std::pair<offset_type, offset_type> (startIndex, numKeys));
1109 typedef typename ptr_type::non_const_type counts_type;
1110 counts_type counts (
"FixedHashTable::counts", size);
1121 if (buildInParallel) {
1122 FHT::CountBuckets<counts_type, keys_type> functor (counts, theKeys, size);
1124 typedef typename counts_type::execution_space execution_space;
1125 typedef Kokkos::RangePolicy<execution_space, offset_type> range_type;
1126 Kokkos::parallel_for (range_type (0, theNumKeys), functor);
1133 auto countsHost = Kokkos::create_mirror_view (counts);
1137 for (offset_type k = 0; k < theNumKeys; ++k) {
1138 typedef typename hash_type::result_type hash_value_type;
1139 const hash_value_type hashVal = hash_type::hashFunc (theKeys[k], size);
1140 ++countsHost[hashVal];
1147 execution_space::fence ();
1150 typename ptr_type::non_const_type ptr (
"FixedHashTable::ptr", size+1);
1164 if (buildInParallel) {
1170 typename decltype (ptr)::HostMirror ptrHost = Kokkos::create_mirror_view (ptr);
1173 for (offset_type i = 0; i < size; ++i) {
1175 ptrHost[i+1] = ptrHost[i] + counts[i];
1182 execution_space::fence ();
1186 using Kokkos::ViewAllocateWithoutInitializing;
1187 typedef typename val_type::non_const_type nonconst_val_type;
1188 nonconst_val_type val (ViewAllocateWithoutInitializing (
"FixedHashTable::pairs"),
1192 typedef FHT::FillPairs<
typename val_type::non_const_type, keys_type,
1193 typename ptr_type::non_const_type> functor_type;
1194 typename functor_type::value_type result (initMinKey, initMaxKey);
1196 const ValueType newStartingValue = startingValue +
static_cast<ValueType
> (startIndex);
1197 if (buildInParallel) {
1198 functor_type functor (val, counts, ptr, theKeys, newStartingValue,
1199 initMinKey, initMaxKey);
1200 typedef Kokkos::RangePolicy<execution_space, offset_type> range_type;
1201 Kokkos::parallel_reduce (range_type (0, theNumKeys), functor, result);
1204 for (offset_type k = 0; k < theNumKeys; ++k) {
1205 typedef typename hash_type::result_type hash_value_type;
1206 const KeyType key = theKeys[k];
1207 if (key > result.maxKey_) {
1208 result.maxKey_ = key;
1210 if (key < result.minKey_) {
1211 result.minKey_ = key;
1213 const ValueType theVal = newStartingValue +
static_cast<ValueType
> (k);
1214 const hash_value_type hashVal = hash_type::hashFunc (key, size);
1220 const offset_type count = counts[hashVal];
1223 result.success_ =
false;
1228 const offset_type curPos = ptr[hashVal+1] - count;
1231 val[curPos].first = key;
1232 val[curPos].second = theVal;
1249 minKey_ = result.minKey_;
1250 maxKey_ = result.maxKey_;
1255 template<
class KeyType,
class ValueType,
class DeviceType>
1257 FixedHashTable<KeyType, ValueType, DeviceType>::
1258 init (
const host_input_keys_type& keys,
1259 const host_input_vals_type& vals,
1263 const offset_type numKeys =
static_cast<offset_type
> (keys.extent (0));
1264 TEUCHOS_TEST_FOR_EXCEPTION
1265 (static_cast<unsigned long long> (numKeys) > static_cast<unsigned long long> (::Kokkos::Details::ArithTraits<ValueType>::max ()),
1266 std::invalid_argument,
"Tpetra::Details::FixedHashTable: The number of "
1267 "keys " << numKeys <<
" is greater than the maximum representable "
1268 "ValueType value " << ::Kokkos::Details::ArithTraits<ValueType>::max () <<
".");
1269 TEUCHOS_TEST_FOR_EXCEPTION
1270 (numKeys > static_cast<offset_type> (INT_MAX), std::logic_error,
"Tpetra::"
1271 "Details::FixedHashTable: This class currently only works when the number "
1272 "of keys is <= INT_MAX = " << INT_MAX <<
". If this is a problem for you"
1273 ", please talk to the Tpetra developers.");
1280 const offset_type size = hash_type::getRecommendedSize (numKeys);
1281 #ifdef HAVE_TPETRA_DEBUG
1282 TEUCHOS_TEST_FOR_EXCEPTION(
1283 size == 0 && numKeys != 0, std::logic_error,
1284 "Tpetra::Details::FixedHashTable constructor: "
1285 "getRecommendedSize(" << numKeys <<
") returned zero, "
1286 "even though the number of keys " << numKeys <<
" is nonzero. "
1287 "Please report this bug to the Tpetra developers.");
1288 #endif // HAVE_TPETRA_DEBUG
1298 typename ptr_type::non_const_type ptr (
"FixedHashTable::ptr", size + 1);
1302 using Kokkos::ViewAllocateWithoutInitializing;
1303 typedef typename val_type::non_const_type nonconst_val_type;
1304 nonconst_val_type val (ViewAllocateWithoutInitializing (
"FixedHashTable::pairs"),
1308 for (offset_type k = 0; k < numKeys; ++k) {
1309 const typename hash_type::result_type hashVal =
1310 hash_type::hashFunc (keys[k], size);
1322 for (offset_type i = 0; i < size; ++i) {
1328 typename ptr_type::non_const_type curRowStart (
"FixedHashTable::curRowStart", size);
1331 FHT::FillPairsResult<KeyType> result (initMinKey, initMaxKey);
1332 for (offset_type k = 0; k < numKeys; ++k) {
1333 typedef typename hash_type::result_type hash_value_type;
1334 const KeyType key = keys[k];
1335 if (key > result.maxKey_) {
1336 result.maxKey_ = key;
1338 if (key < result.minKey_) {
1339 result.minKey_ = key;
1341 const ValueType theVal = vals[k];
1342 if (theVal > maxVal_) {
1345 if (theVal < minVal_) {
1348 const hash_value_type hashVal = hash_type::hashFunc (key, size);
1350 const offset_type offset = curRowStart[hashVal];
1351 const offset_type curPos = ptr[hashVal] + offset;
1352 if (curPos >= ptr[hashVal+1]) {
1353 result.success_ =
false;
1356 val[curPos].first = key;
1357 val[curPos].second = theVal;
1358 ++curRowStart[hashVal];
1362 TEUCHOS_TEST_FOR_EXCEPTION
1363 (! result.success_, std::logic_error,
"Tpetra::Details::FixedHashTable::"
1364 "init: Filling the hash table failed! Please report this bug to the "
1365 "Tpetra developers.");
1370 minKey_ = result.minKey_;
1371 maxKey_ = result.maxKey_;
1375 template <
class KeyType,
class ValueType,
class DeviceType>
1380 if (! checkedForDuplicateKeys_) {
1381 hasDuplicateKeys_ = checkForDuplicateKeys ();
1382 checkedForDuplicateKeys_ =
true;
1384 return hasDuplicateKeys_;
1387 template <
class KeyType,
class ValueType,
class DeviceType>
1392 const offset_type size = this->getSize ();
1396 if (size == 0 || this->numPairs () == 0) {
1400 typedef FHT::CheckForDuplicateKeys<ptr_type, val_type> functor_type;
1401 functor_type functor (val_, ptr_);
1403 typedef Kokkos::RangePolicy<execution_space, offset_type> range_type;
1404 Kokkos::parallel_reduce (range_type (0, size), functor, hasDupKeys);
1405 return hasDupKeys > 0;
1409 template <
class KeyType,
class ValueType,
class DeviceType>
1414 std::ostringstream oss;
1415 oss <<
"FixedHashTable<"
1416 << Teuchos::TypeNameTraits<KeyType>::name () <<
","
1417 << Teuchos::TypeNameTraits<ValueType>::name () <<
">: "
1418 <<
"{ numKeys: " << val_.extent (0)
1419 <<
", tableSize: " << this->getSize () <<
" }";
1423 template <
class KeyType,
class ValueType,
class DeviceType>
1427 const Teuchos::EVerbosityLevel verbLevel)
const
1431 using Teuchos::OSTab;
1432 using Teuchos::rcpFromRef;
1433 using Teuchos::TypeNameTraits;
1434 using Teuchos::VERB_DEFAULT;
1435 using Teuchos::VERB_NONE;
1436 using Teuchos::VERB_LOW;
1437 using Teuchos::VERB_EXTREME;
1442 Teuchos::EVerbosityLevel vl = verbLevel;
1443 if (vl == VERB_DEFAULT) vl = VERB_LOW;
1445 if (vl == VERB_NONE) {
1448 else if (vl == VERB_LOW) {
1449 out << this->description() << endl;
1452 out <<
"FixedHashTable:" << endl;
1454 OSTab tab1 (rcpFromRef (out));
1460 out <<
"Template parameters:" << endl;
1462 OSTab tab2 (rcpFromRef (out));
1463 out <<
"KeyType: " << TypeNameTraits<KeyType>::name () << endl
1464 <<
"ValueType: " << TypeNameTraits<ValueType>::name () << endl;
1467 const offset_type tableSize = this->getSize ();
1468 const offset_type numKeys = val_.extent (0);
1470 out <<
"Table parameters:" << endl;
1472 OSTab tab2 (rcpFromRef (out));
1473 out <<
"numKeys: " << numKeys << endl
1474 <<
"tableSize: " << tableSize << endl;
1477 if (vl >= VERB_EXTREME) {
1478 out <<
"Contents: ";
1479 if (tableSize == 0 || numKeys == 0) {
1480 out <<
"[]" << endl;
1482 out <<
"[ " << endl;
1484 OSTab tab2 (rcpFromRef (out));
1485 for (offset_type i = 0; i < tableSize; ++i) {
1486 OSTab tab3 (rcpFromRef (out));
1488 for (offset_type k = ptr_[i]; k < ptr_[i+1]; ++k) {
1489 out <<
"(" << val_[k].first <<
"," << val_[k].second <<
")";
1490 if (k + 1 < ptr_[i+1]) {
1516 #define TPETRA_DETAILS_FIXEDHASHTABLE_INSTANT_DEFAULTNODE(LO,GO) \
1517 template class FixedHashTable< GO , LO >;
1528 #define TPETRA_DETAILS_FIXEDHASHTABLE_INSTANT(LO, GO, DEVICE) \
1529 template class FixedHashTable< GO , LO , DEVICE >;
1531 #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_INLINE_FUNCTION void join(volatile value_type &dst, const volatile value_type &src) const
Combine two intermediate reduction results.
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.
bool hasKeys() const
Whether it is safe to call getKey().
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 function Tpetra::Details::computeOffsetsFromCounts, an implementation detail o...
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_.
OffsetsViewType::non_const_value_type computeOffsetsFromCounts(const OffsetsViewType &ptr, const CountsViewType &counts)
Compute offsets from counts.
FixedHashTable()
Default constructor; makes an empty table.
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 hasDuplicateKeys()
Whether the table has any duplicate keys.
static KOKKOS_INLINE_FUNCTION result_type hashFunc(const argument_type &key, const offset_type &size)
The hash function.
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.
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.