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 200 operator () (
const size_type& i)
const 204 const hash_value_type hashVal = hash_type::hashFunc (keys_[i], size_);
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) :
256 minKey_ (initMinKey),
257 maxKey_ (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)
390 KOKKOS_INLINE_FUNCTION
void init (value_type& dst)
const 397 KOKKOS_INLINE_FUNCTION
void 398 join (
volatile value_type& dst,
399 const volatile value_type& src)
const 414 KOKKOS_INLINE_FUNCTION
void 415 operator () (
const size_type& i, value_type& dst)
const 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);
430 const hash_value_type hashVal = hash_type::hashFunc (key, size_);
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 524 operator () (
const size_type& i, value_type& dst)
const 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>
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) {
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) {
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"),
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) {
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>
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) {
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);
1332 for (offset_type k = 0; k < numKeys; ++k) {
1334 const KeyType key = keys[k];
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]) {
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.");
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) {
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.
Namespace Tpetra contains the class and methods constituting the Tpetra library.
ResultType result_type
Type of the return value of the hash function.
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.
bool success_
Whether fill succeeded (it can only fail on a bug)
KeyType maxKey_
The current maximum key.
Implementation details of Tpetra.
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...
OffsetsViewType::non_const_value_type computeOffsetsFromCounts(const OffsetsViewType &ptr, const CountsViewType &counts)
Compute offsets from counts.
FixedHashTable()
Default constructor; makes an empty table.
bool hasKeys() const
Whether it is safe to call getKey().
KOKKOS_INLINE_FUNCTION void init(value_type &dst) const
Set the initial value of the reduction result.
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.
CountBuckets(const counts_view_type &counts, const keys_view_type &keys, const size_type size)
Constructor.
Functor for checking whether a FixedHashTable has one or more duplicate entries.
KOKKOS_INLINE_FUNCTION void join(volatile value_type &dst, const volatile value_type &src) const
Combine two intermediate reduction results.
KeyType minKey_
The current minimum key.
Reduction result for FillPairs functor below.
Kokkos::View< const GlobalOrdinal *, Kokkos::LayoutLeft, device_type > keys_type
Type of a 1-D Kokkos::View (array) used to store keys.