403 if (
key < dst.minKey_) {
406 const val_type
theVal = startingValue_ +
static_cast<val_type
> (
i);
412 dst.success_ =
false;
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_;
458template<
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;
477 const offsets_view_type& ptr) :
480 size_ (ptr_.extent (0) == 0 ?
496 dst = dst + src > 0?1:0;
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];
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) {
532 pairs_view_type pairs_;
533 offsets_view_type ptr_;
543template<
class KeyType,
class ValueType,
class DeviceType>
558 contiguousValues_ (
true),
559 checkedForDuplicateKeys_ (
true),
560 hasDuplicateKeys_ (
false)
564template<
class KeyType,
class ValueType,
class DeviceType>
579 contiguousValues_ (
true),
580 checkedForDuplicateKeys_ (
false),
581 hasDuplicateKeys_ (
false)
590template<
class KeyType,
class ValueType,
class DeviceType>
605 contiguousValues_ (
true),
606 checkedForDuplicateKeys_ (
false),
607 hasDuplicateKeys_ (
false)
617 using Kokkos::ViewAllocateWithoutInitializing;
627template<
class KeyType,
class ValueType,
class DeviceType>
643 contiguousValues_ (
true),
644 checkedForDuplicateKeys_ (
false),
645 hasDuplicateKeys_ (
false)
654 using Kokkos::ViewAllocateWithoutInitializing;
673 ::Kokkos::Details::ArithTraits<KeyType>::min () :
674 -::Kokkos::Details::ArithTraits<KeyType>::max ();
680template<
class KeyType,
class ValueType,
class DeviceType>
696 contiguousValues_ (
true),
697 checkedForDuplicateKeys_ (
false),
698 hasDuplicateKeys_ (
false)
714 ::Kokkos::Details::ArithTraits<KeyType>::min () :
715 -::Kokkos::Details::ArithTraits<KeyType>::max ();
720template<
class KeyType,
class ValueType,
class DeviceType>
736 contiguousValues_ (
true),
737 checkedForDuplicateKeys_ (
false),
738 hasDuplicateKeys_ (
false)
747 using Kokkos::ViewAllocateWithoutInitializing;
766 ::Kokkos::Details::ArithTraits<KeyType>::min () :
767 -::Kokkos::Details::ArithTraits<KeyType>::max ();
772template<
class KeyType,
class ValueType,
class DeviceType>
788 contiguousValues_ (
true),
789 checkedForDuplicateKeys_ (
false),
790 hasDuplicateKeys_ (
false)
806 ::Kokkos::Details::ArithTraits<KeyType>::min () :
807 -::Kokkos::Details::ArithTraits<KeyType>::max ();
812template<
class KeyType,
class ValueType,
class DeviceType>
815 const Teuchos::ArrayView<const ValueType>&
vals) :
828 contiguousValues_ (
false),
829 checkedForDuplicateKeys_ (
false),
830 hasDuplicateKeys_ (
false)
853 ::Kokkos::Details::ArithTraits<KeyType>::min () :
854 -::Kokkos::Details::ArithTraits<KeyType>::max ();
858template<
class KeyType,
class ValueType,
class DeviceType>
869 using Kokkos::subview;
870 using Kokkos::ViewAllocateWithoutInitializing;
871 using Teuchos::TypeNameTraits;
872 typedef typename std::decay<
decltype (
keys.extent (0)) >::type size_type;
873 const char prefix[] =
"Tpetra::Details::FixedHashTable: ";
875 const offset_type
numKeys =
static_cast<offset_type
> (
keys.extent (0));
877 const offset_type
theMaxVal = ::Kokkos::Details::ArithTraits<offset_type>::max ();
881 "number of keys " <<
keys.extent (0) <<
" does not fit in "
883 "max value is " <<
theMaxVal <<
". This means that it is not possible to "
884 "use this constructor.");
887 (
static_cast<unsigned long long> (
numKeys) >
888 static_cast<unsigned long long> (::Kokkos::Details::ArithTraits<ValueType>::max ()),
889 std::invalid_argument,
"Tpetra::Details::FixedHashTable: The number of "
890 "keys " <<
numKeys <<
" is greater than the maximum representable "
891 "ValueType value " << ::Kokkos::Details::ArithTraits<ValueType>::max () <<
". "
892 "This means that it is not possible to use this constructor.");
895 "This class currently only works when the number of keys is <= INT_MAX = "
896 <<
INT_MAX <<
". If this is a problem for you, please talk to the Tpetra "
900 FHT::worthBuildingFixedHashTableInParallel<execution_space> ();
925 auto keys_h = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(),
927 firstContigKey_ =
keys_h[0];
931 lastContigKey_ = firstContigKey_ + 1;
938 if (lastContigKey_ !=
keys_h[
k]) {
947 firstContigKey_ = firstContigKey;
948 lastContigKey_ = lastContigKey;
951 offset_type startIndex;
953 initMinKey = std::min (initMinKey, firstContigKey_);
954 initMaxKey = std::max (initMaxKey, lastContigKey_);
955 startIndex =
static_cast<offset_type
> (lastContigKey_ - firstContigKey_);
960 const offset_type theNumKeys = numKeys - startIndex;
961 const offset_type size = hash_type::getRecommendedSize (theNumKeys);
962#ifdef HAVE_TPETRA_DEBUG
963 TEUCHOS_TEST_FOR_EXCEPTION(
964 size == 0 && numKeys != 0, std::logic_error,
965 "Tpetra::Details::FixedHashTable constructor: "
966 "getRecommendedSize(" << numKeys <<
") returned zero, "
967 "even though the number of keys " << numKeys <<
" is nonzero. "
968 "Please report this bug to the Tpetra developers.");
971 subview (keys, std::pair<offset_type, offset_type> (startIndex, numKeys));
978 typedef typename ptr_type::non_const_type counts_type;
979 counts_type counts (
"Tpetra::FixedHashTable::counts", size);
986 typename keys_type::HostMirror theKeysHost;
993 if (buildInParallel) {
994 FHT::CountBuckets<counts_type, keys_type> functor (counts, theKeys, size);
995 using execution_space =
typename counts_type::execution_space;
996 using range_type = Kokkos::RangePolicy<execution_space, offset_type>;
997 const char kernelLabel[] =
"Tpetra::Details::FixedHashTable CountBuckets";
999 using key_type =
typename keys_type::non_const_value_type;
1000 Kokkos::pair<int, key_type> err;
1001 Kokkos::parallel_reduce (kernelLabel, range_type (0, theNumKeys),
1003 TEUCHOS_TEST_FOR_EXCEPTION
1004 (err.first != 0, std::logic_error,
"Tpetra::Details::FixedHashTable "
1005 "constructor: CountBuckets found a key " << err.second <<
" that "
1006 "results in an out-of-bounds hash value.");
1009 Kokkos::parallel_for (kernelLabel, range_type (0, theNumKeys), functor);
1013 Kokkos::HostSpace hostMemSpace;
1014 theKeysHost = Kokkos::create_mirror_view(theKeys);
1015 Kokkos::deep_copy(theKeysHost, theKeys);
1016 auto countsHost = Kokkos::create_mirror_view (hostMemSpace, counts);
1018 for (offset_type k = 0; k < theNumKeys; ++k) {
1019 using key_type =
typename keys_type::non_const_value_type;
1020 const key_type key = theKeysHost[k];
1022 using hash_value_type =
typename hash_type::result_type;
1023 const hash_value_type hashVal = hash_type::hashFunc (key, size);
1024 TEUCHOS_TEST_FOR_EXCEPTION
1025 (hashVal < hash_value_type (0) ||
1026 hashVal >= hash_value_type (countsHost.extent (0)),
1027 std::logic_error,
"Tpetra::Details::FixedHashTable "
1028 "constructor: Sequential CountBuckets found a key " << key
1029 <<
" that results in an out-of-bounds hash value.");
1031 ++countsHost[hashVal];
1033 Kokkos::deep_copy (counts, countsHost);
1039 execution_space().fence ();
1042 typename ptr_type::non_const_type ptr (
"Tpetra::FixedHashTable::ptr", size+1);
1057 using ::Tpetra::Details::computeOffsetsFromCounts;
1058 if (buildInParallel) {
1062 if (! buildInParallel || debug) {
1063 Kokkos::HostSpace hostMemSpace;
1064 auto counts_h = Kokkos::create_mirror_view_and_copy (hostMemSpace, counts);
1065 auto ptr_h = Kokkos::create_mirror_view (hostMemSpace, ptr);
1067#ifdef KOKKOS_ENABLE_SERIAL
1068 Kokkos::Serial hostExecSpace;
1070 Kokkos::DefaultHostExecutionSpace hostExecSpace;
1074 Kokkos::deep_copy (ptr, ptr_h);
1078 for (offset_type i = 0; i < size; ++i) {
1079 if (ptr_h[i+1] != ptr_h[i] + counts_h[i]) {
1083 TEUCHOS_TEST_FOR_EXCEPTION
1084 (bad, std::logic_error,
"Tpetra::Details::FixedHashTable "
1085 "constructor: computeOffsetsFromCounts gave an incorrect "
1093 execution_space().fence ();
1097 typedef typename val_type::non_const_type nonconst_val_type;
1098 nonconst_val_type val (ViewAllocateWithoutInitializing (
"Tpetra::FixedHashTable::pairs"),
1102 typedef FHT::FillPairs<
typename val_type::non_const_type, keys_type,
1103 typename ptr_type::non_const_type> functor_type;
1104 typename functor_type::value_type result (initMinKey, initMaxKey);
1106 const ValueType newStartingValue = startingValue +
static_cast<ValueType
> (startIndex);
1107 if (buildInParallel) {
1108 functor_type functor (val, counts, ptr, theKeys, newStartingValue,
1109 initMinKey, initMaxKey);
1110 typedef Kokkos::RangePolicy<execution_space, offset_type> range_type;
1111 Kokkos::parallel_reduce (range_type (0, theNumKeys), functor, result);
1114 Kokkos::HostSpace hostMemSpace;
1115 auto counts_h = Kokkos::create_mirror_view_and_copy(hostMemSpace, counts);
1116 auto ptr_h = Kokkos::create_mirror_view_and_copy(hostMemSpace, ptr);
1117 auto val_h = Kokkos::create_mirror_view_and_copy(hostMemSpace, val);
1118 for (offset_type k = 0; k < theNumKeys; ++k) {
1119 typedef typename hash_type::result_type hash_value_type;
1120 const KeyType key = theKeysHost[k];
1121 if (key > result.maxKey_) {
1122 result.maxKey_ = key;
1124 if (key < result.minKey_) {
1125 result.minKey_ = key;
1127 const ValueType theVal = newStartingValue +
static_cast<ValueType
> (k);
1128 const hash_value_type hashVal = hash_type::hashFunc (key, size);
1131 const offset_type count = counts_h[hashVal];
1132 --counts_h[hashVal];
1134 result.success_ =
false;
1138 const offset_type curPos = ptr_h[hashVal+1] - count;
1139 val_h[curPos].first = key;
1140 val_h[curPos].second = theVal;
1143 Kokkos::deep_copy(counts, counts_h);
1144 Kokkos::deep_copy(val, val_h);
1159 minKey_ = result.minKey_;
1160 maxKey_ = result.maxKey_;
1165template<
class KeyType,
class ValueType,
class DeviceType>
1167FixedHashTable<KeyType, ValueType, DeviceType>::
1168init (
const host_input_keys_type& keys,
1169 const host_input_vals_type& vals,
1173 const offset_type numKeys =
static_cast<offset_type
> (keys.extent (0));
1174 TEUCHOS_TEST_FOR_EXCEPTION
1175 (
static_cast<unsigned long long> (numKeys) >
static_cast<unsigned long long> (::Kokkos::Details::ArithTraits<ValueType>::max ()),
1176 std::invalid_argument,
"Tpetra::Details::FixedHashTable: The number of "
1177 "keys " << numKeys <<
" is greater than the maximum representable "
1178 "ValueType value " << ::Kokkos::Details::ArithTraits<ValueType>::max () <<
".");
1179 TEUCHOS_TEST_FOR_EXCEPTION
1180 (numKeys >
static_cast<offset_type
> (INT_MAX), std::logic_error,
"Tpetra::"
1181 "Details::FixedHashTable: This class currently only works when the number "
1182 "of keys is <= INT_MAX = " << INT_MAX <<
". If this is a problem for you"
1183 ", please talk to the Tpetra developers.");
1190 const offset_type size = hash_type::getRecommendedSize (numKeys);
1191#ifdef HAVE_TPETRA_DEBUG
1192 TEUCHOS_TEST_FOR_EXCEPTION(
1193 size == 0 && numKeys != 0, std::logic_error,
1194 "Tpetra::Details::FixedHashTable constructor: "
1195 "getRecommendedSize(" << numKeys <<
") returned zero, "
1196 "even though the number of keys " << numKeys <<
" is nonzero. "
1197 "Please report this bug to the Tpetra developers.");
1206 Kokkos::HostSpace hostMemSpace;
1207 typename ptr_type::non_const_type ptr (
"Tpetra::FixedHashTable::ptr", size + 1);
1208 auto ptr_h = Kokkos::create_mirror_view_and_copy(hostMemSpace, ptr);
1212 using Kokkos::ViewAllocateWithoutInitializing;
1213 typedef typename val_type::non_const_type nonconst_val_type;
1214 nonconst_val_type val (ViewAllocateWithoutInitializing (
"Tpetra::FixedHashTable::pairs"),
1216 auto val_h = Kokkos::create_mirror_view_and_copy(hostMemSpace, val);
1219 for (offset_type k = 0; k < numKeys; ++k) {
1220 const typename hash_type::result_type hashVal =
1221 hash_type::hashFunc (keys[k], size);
1233 for (offset_type i = 0; i < size; ++i) {
1234 ptr_h[i+1] += ptr_h[i];
1239 typename ptr_type::non_const_type::HostMirror curRowStart (
"Tpetra::FixedHashTable::curRowStart", size);
1242 FHT::FillPairsResult<KeyType> result (initMinKey, initMaxKey);
1243 for (offset_type k = 0; k < numKeys; ++k) {
1244 typedef typename hash_type::result_type hash_value_type;
1245 const KeyType key = keys[k];
1246 if (key > result.maxKey_) {
1247 result.maxKey_ = key;
1249 if (key < result.minKey_) {
1250 result.minKey_ = key;
1252 const ValueType theVal = vals[k];
1253 if (theVal > maxVal_) {
1256 if (theVal < minVal_) {
1259 const hash_value_type hashVal = hash_type::hashFunc (key, size);
1261 const offset_type offset = curRowStart[hashVal];
1262 const offset_type curPos = ptr_h[hashVal] + offset;
1263 if (curPos >= ptr_h[hashVal+1]) {
1264 result.success_ =
false;
1267 val_h[curPos].first = key;
1268 val_h[curPos].second = theVal;
1269 ++curRowStart[hashVal];
1273 TEUCHOS_TEST_FOR_EXCEPTION
1274 (! result.success_, std::logic_error,
"Tpetra::Details::FixedHashTable::"
1275 "init: Filling the hash table failed! Please report this bug to the "
1276 "Tpetra developers.");
1279 Kokkos::deep_copy(ptr, ptr_h);
1280 Kokkos::deep_copy(val, val_h);
1284 minKey_ = result.minKey_;
1285 maxKey_ = result.maxKey_;
1289template <
class KeyType,
class ValueType,
class DeviceType>
1294 if (! checkedForDuplicateKeys_) {
1295 hasDuplicateKeys_ = checkForDuplicateKeys ();
1296 checkedForDuplicateKeys_ =
true;
1298 return hasDuplicateKeys_;
1301template <
class KeyType,
class ValueType,
class DeviceType>
1306 const offset_type
size = this->getSize ();
1310 if (
size == 0 || this->numPairs () == 0) {
1314 typedef FHT::CheckForDuplicateKeys<ptr_type, val_type>
functor_type;
1317 typedef Kokkos::RangePolicy<execution_space, offset_type> range_type;
1323template <
class KeyType,
class ValueType,
class DeviceType>
1328 std::ostringstream
oss;
1329 oss <<
"FixedHashTable<"
1330 << Teuchos::TypeNameTraits<KeyType>::name () <<
","
1331 << Teuchos::TypeNameTraits<ValueType>::name () <<
">: "
1332 <<
"{ numKeys: " << val_.extent (0)
1333 <<
", tableSize: " << this->getSize () <<
" }";
1337template <
class KeyType,
class ValueType,
class DeviceType>
1341 const Teuchos::EVerbosityLevel
verbLevel)
const
1345 using Teuchos::OSTab;
1346 using Teuchos::rcpFromRef;
1347 using Teuchos::TypeNameTraits;
1348 using Teuchos::VERB_DEFAULT;
1349 using Teuchos::VERB_NONE;
1350 using Teuchos::VERB_LOW;
1351 using Teuchos::VERB_EXTREME;
1363 out << this->description() <<
endl;
1366 out <<
"FixedHashTable:" <<
endl;
1374 out <<
"Template parameters:" <<
endl;
1381 const offset_type
tableSize = this->getSize ();
1382 const offset_type
numKeys = val_.extent (0);
1384 out <<
"Table parameters:" <<
endl;
1392 out <<
"Contents: ";
1402 for (offset_type
k = ptr_[
i];
k < ptr_[
i+1]; ++
k) {
1403 out <<
"(" << val_[
k].first <<
"," << val_[
k].second <<
")";
1404 if (
k + 1 < ptr_[
i+1]) {