From 221dce25461e7eb2885e23c786c75224d170d793 Mon Sep 17 00:00:00 2001 From: Jake Hemstad Date: Tue, 14 Jan 2020 16:03:06 -0600 Subject: [PATCH 1/9] Create design.md --- design.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 design.md diff --git a/design.md b/design.md new file mode 100644 index 000000000..d211d44b7 --- /dev/null +++ b/design.md @@ -0,0 +1,25 @@ +There are several “hash map” like data structures lie on a spectrum from high-performance, bare metal with restricted features to more convenient, +full-featured structures that may be less performant. +cuCollections will likely have several classes that are on different points on this spectrum. + +# HashArray (TODO Naming) + +Lowest-level, highest performance "bare metal" data structure with limited feature set. + +## Keys and Values + +- `sizeof(Key) + sizeof(Values) <= largest supported CAS (64bits)` + +## Layout + +### Array of Structs + +- Enables + +### Struct of Arrays + +## Operations + + + +# HashMap (TODO Name) From e8b446034f13272d81f173d5ae115f55a4245863 Mon Sep 17 00:00:00 2001 From: Jake Hemstad Date: Tue, 14 Jan 2020 17:37:15 -0600 Subject: [PATCH 2/9] Update design.md --- design.md | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 107 insertions(+), 6 deletions(-) diff --git a/design.md b/design.md index d211d44b7..ce35e5f16 100644 --- a/design.md +++ b/design.md @@ -4,22 +4,123 @@ cuCollections will likely have several classes that are on different points on t # HashArray (TODO Naming) +## Summary + Lowest-level, highest performance "bare metal" data structure with limited feature set. +- Fixed-size +- Keys limited to native integral types where `sizeof(Key) <= largest atomicCAS (64bits) +- Insert/Find/Erase + - Storage for "Erased" values cannot be reclaimed +- Uses sentinel values to indicate empty/erased cells + +```c++ +template +class HashArray{ + using value_type = thrust::pair; +} +``` + ## Keys and Values -- `sizeof(Key) + sizeof(Values) <= largest supported CAS (64bits)` +Key types are limited to native, integral types to allow bitwise equality comparison (i.e., no floating-point keys). -## Layout +### DECISION REQUIRED: Integral Values vs Arbitrary Values + +#### Integral, Packable Values + +Require `Value` to be an integral, "packable" type. + +"Packable" key/value types are those types where `sizeof(Key) + sizeof(Value) <= largest atomicCAS (64bits)` + +Requires Array of Struct layout. + +- Pros: + - Performance: enables update of key/value in a single atomicCAS operation (assumes AoS layout) + - Find/Insert/Erase can be concurrent -### Array of Structs +- Cons: + - Least flexible + - Requires user to specify `EMPTY/ERASED` sentinels for both `Key` and `Value` -- Enables +#### Arbitrary Values -### Struct of Arrays +`Value` can be any device constructible type. + +Can use either AoS or SoA. + +- Pros: + - Flexible + - Sentinels only required for `Key` `EMPTY/ERASED/(FILLING)` + +- Cons: + - Potentially Less Performant: + - `atomicCAS` key w/ dependent write for value (placement new) + - Concurrent insert/find/erase requires additional sentinel for FILLING state + +## Layout + +### DECISION NEEDED: Array of Structs vs Struct of Arrays + +Layout largely determined by decision on integral vs. arbitrary `Value`s. ## Operations +### `insert` +```c++ +/** + * @brief Attempts to insert a key, value pair into the map. + * + * Returns an iterator, boolean pair. + * + * If the new key already present in the map, the iterator points to + * the location of the existing key and the boolean is `false` indicating + * that the insert did not succeed. + * + * If the new key was not present, the iterator points to the location + * where the insert occured and the boolean is `true` indicating that the + * insert succeeded. + * + * @param insert_pair The pair to insert + * @param key_equal Binary predicate to use for equality comparison between keys + * @return Iterator, Boolean pair. Iterator is to the location of the + * newly inserted pair, or the existing pair that prevented the insert. + * Boolean indicates insert success. + */ +template +thrust::pair insert( value_type const& v, KeyEqual key_equal = std::equal_to{}); +``` +### `find` +```c++ +/** + * @brief Searches the map for the specified key. + * + * @param k The key to search for + * @param key_equal Binary predicate to use for equality comparison between keys + * @return An iterator to the key if it exists, else map.end() + */ +template +const_iterator find( Key const& k, KeyEqual key_equal = std::equal_to{}); + +### `erase` +```c++ +/** + * @brief Erases the specified key (if it exists). + * + * @param k The key to erase + * @param key_equal Binary predicate to use for equality comparison between keys + * @returns `true` If `key` existed as was removed + * @returns `false` If `key` does not exists + */ +template +bool erase( Key const& k, KeyEqual key_equal = std::equal_to{}); +``` + +# HashMap, Bryce version from SC libcu++ talk (TODO Name) -# HashMap (TODO Name) +Higher-level, with more features: +- Arbitrary key/value types +- Per-bucket status byte/bit(s) + - EMPTY, FILLING, FILLED, DELETED +- Fixed Size? From f10529d6c37f8717cf9dc59ac6515147f36b9817 Mon Sep 17 00:00:00 2001 From: Jake Hemstad Date: Tue, 14 Jan 2020 17:42:24 -0600 Subject: [PATCH 3/9] Update design.md Update markdown mistake. --- design.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/design.md b/design.md index ce35e5f16..ca29e8cb7 100644 --- a/design.md +++ b/design.md @@ -101,8 +101,10 @@ thrust::pair insert( value_type const& v, KeyEqual key_equal = st */ template const_iterator find( Key const& k, KeyEqual key_equal = std::equal_to{}); +``` ### `erase` + ```c++ /** * @brief Erases the specified key (if it exists). From fada531987c0e5d59cd948480b267e88f33853fd Mon Sep 17 00:00:00 2001 From: Jake Hemstad Date: Tue, 14 Jan 2020 17:42:59 -0600 Subject: [PATCH 4/9] Update design.md --- design.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design.md b/design.md index ca29e8cb7..7da3fff1b 100644 --- a/design.md +++ b/design.md @@ -9,7 +9,7 @@ cuCollections will likely have several classes that are on different points on t Lowest-level, highest performance "bare metal" data structure with limited feature set. - Fixed-size -- Keys limited to native integral types where `sizeof(Key) <= largest atomicCAS (64bits) +- Keys limited to native integral types where `sizeof(Key) <= largest atomicCAS (64bits)` - Insert/Find/Erase - Storage for "Erased" values cannot be reclaimed - Uses sentinel values to indicate empty/erased cells From bcb19ebbf50da681afe59e5644e4256c5aa7a8e2 Mon Sep 17 00:00:00 2001 From: Jake Hemstad Date: Wed, 15 Jan 2020 13:25:15 -0600 Subject: [PATCH 5/9] Update design.md --- design.md | 97 +++++++++++++++++++------------------------------------ 1 file changed, 34 insertions(+), 63 deletions(-) diff --git a/design.md b/design.md index 7da3fff1b..6adf89ffa 100644 --- a/design.md +++ b/design.md @@ -2,67 +2,46 @@ There are several “hash map” like data structures lie on a spectrum from hig full-featured structures that may be less performant. cuCollections will likely have several classes that are on different points on this spectrum. -# HashArray (TODO Naming) +# insert_only_hash_array ## Summary +- Fixed size +- Concurrent Insert/Find only (no erase) +- Primitive Key/Value Support: + - Packable key/value no overhead + - Non-packable incur additional memory overhead for in-place locks +- Require single sentinel for key/values: `EMPTY` +- AoS layout + -`cuda::std::atomic>` + +## Questions: +- When is `key_equal` respected? + - atomicCAS doesn't use the `key_equal` + +- Require unique object representation? + - Sentinel may have padding bits, which requires zero-init of buffer before sentinel init + - Can add support in the future in C++17 and on + + +# insert_erase_hash_array +## Summary +- Fixed Size +- Concurrent insert/find/erase +- Primitive (CASable) keys +- Arbitrary value types +- *THREE* key sentinel values: `EMPTY, FILLING, ERASED` -Lowest-level, highest performance "bare metal" data structure with limited feature set. - -- Fixed-size -- Keys limited to native integral types where `sizeof(Key) <= largest atomicCAS (64bits)` -- Insert/Find/Erase - - Storage for "Erased" values cannot be reclaimed -- Uses sentinel values to indicate empty/erased cells - -```c++ -template -class HashArray{ - using value_type = thrust::pair; -} -``` - -## Keys and Values - -Key types are limited to native, integral types to allow bitwise equality comparison (i.e., no floating-point keys). - -### DECISION REQUIRED: Integral Values vs Arbitrary Values - -#### Integral, Packable Values - -Require `Value` to be an integral, "packable" type. - -"Packable" key/value types are those types where `sizeof(Key) + sizeof(Value) <= largest atomicCAS (64bits)` - -Requires Array of Struct layout. - -- Pros: - - Performance: enables update of key/value in a single atomicCAS operation (assumes AoS layout) - - Find/Insert/Erase can be concurrent - -- Cons: - - Least flexible - - Requires user to specify `EMPTY/ERASED` sentinels for both `Key` and `Value` - -#### Arbitrary Values - -`Value` can be any device constructible type. - -Can use either AoS or SoA. - -- Pros: - - Flexible - - Sentinels only required for `Key` `EMPTY/ERASED/(FILLING)` - -- Cons: - - Potentially Less Performant: - - `atomicCAS` key w/ dependent write for value (placement new) - - Concurrent insert/find/erase requires additional sentinel for FILLING state -## Layout +# general_purpose_hash_array +## Summary +- Fixed size +- Arbitrary key/value +- Control state (byte/bits) per cell + - Additional memory overhead +- Concurrent insert/find/erase +- No sentinel values required -### DECISION NEEDED: Array of Structs vs Struct of Arrays -Layout largely determined by decision on integral vs. arbitrary `Value`s. ## Operations @@ -118,11 +97,3 @@ template bool erase( Key const& k, KeyEqual key_equal = std::equal_to{}); ``` - -# HashMap, Bryce version from SC libcu++ talk (TODO Name) - -Higher-level, with more features: -- Arbitrary key/value types -- Per-bucket status byte/bit(s) - - EMPTY, FILLING, FILLED, DELETED -- Fixed Size? From c60474619eefe6f93bee5540c7fb2631fffc79b1 Mon Sep 17 00:00:00 2001 From: Jake Hemstad Date: Thu, 16 Jan 2020 12:11:30 -0600 Subject: [PATCH 6/9] Update design.md --- design.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/design.md b/design.md index 6adf89ffa..7a3ed20a3 100644 --- a/design.md +++ b/design.md @@ -9,9 +9,10 @@ cuCollections will likely have several classes that are on different points on t - Concurrent Insert/Find only (no erase) - Primitive Key/Value Support: - Packable key/value no overhead + - "Packable" means a key/value can be CASed in a single operation (`sizeof(Key) + sizeof(Value) <= max CAS`) - Non-packable incur additional memory overhead for in-place locks - Require single sentinel for key/values: `EMPTY` -- AoS layout +- Array of Struct layout -`cuda::std::atomic>` ## Questions: From aeca41df66041aad6eb0bfd7565de530a88d34a1 Mon Sep 17 00:00:00 2001 From: Jake Hemstad Date: Thu, 30 Jan 2020 15:27:46 -0600 Subject: [PATCH 7/9] Update design.md --- design.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/design.md b/design.md index 7a3ed20a3..627900fb8 100644 --- a/design.md +++ b/design.md @@ -3,7 +3,7 @@ full-featured structures that may be less performant. cuCollections will likely have several classes that are on different points on this spectrum. -# insert_only_hash_array +# insert_only_hash_array (P0) ## Summary - Fixed size - Concurrent Insert/Find only (no erase) @@ -13,27 +13,34 @@ cuCollections will likely have several classes that are on different points on t - Non-packable incur additional memory overhead for in-place locks - Require single sentinel for key/values: `EMPTY` - Array of Struct layout - -`cuda::std::atomic>` + -`cuda::atomic>` +- Needs template parameter for atomic scope + - System, Shared, etc. see libcu++ thread_scope ## Questions: - When is `key_equal` respected? - atomicCAS doesn't use the `key_equal` + - Use memcmp for checking against sentinel value(s) + - Document that bitwise equality is used - Require unique object representation? - Sentinel may have padding bits, which requires zero-init of buffer before sentinel init - Can add support in the future in C++17 and on -# insert_erase_hash_array +# insert_erase_hash_array (P1) ## Summary - Fixed Size - Concurrent insert/find/erase - Primitive (CASable) keys - Arbitrary value types - *THREE* key sentinel values: `EMPTY, FILLING, ERASED` +- Needs template parameter for atomic scope + - System, Shared, etc. see libcu++ thread_scope +- *Needs more study of DL use case* -# general_purpose_hash_array +# general_purpose_hash_array (P2) ## Summary - Fixed size - Arbitrary key/value From 9d8922af767665a2d79ed9916aaf6744d5c13e82 Mon Sep 17 00:00:00 2001 From: Jake Hemstad Date: Thu, 9 Jul 2020 11:56:01 -0500 Subject: [PATCH 8/9] Update design.md --- design.md | 112 +++++------------------------------------------------- 1 file changed, 10 insertions(+), 102 deletions(-) diff --git a/design.md b/design.md index 627900fb8..cb395a0c4 100644 --- a/design.md +++ b/design.md @@ -3,105 +3,13 @@ full-featured structures that may be less performant. cuCollections will likely have several classes that are on different points on this spectrum. -# insert_only_hash_array (P0) -## Summary -- Fixed size -- Concurrent Insert/Find only (no erase) -- Primitive Key/Value Support: - - Packable key/value no overhead - - "Packable" means a key/value can be CASed in a single operation (`sizeof(Key) + sizeof(Value) <= max CAS`) - - Non-packable incur additional memory overhead for in-place locks -- Require single sentinel for key/values: `EMPTY` -- Array of Struct layout - -`cuda::atomic>` -- Needs template parameter for atomic scope - - System, Shared, etc. see libcu++ thread_scope - -## Questions: -- When is `key_equal` respected? - - atomicCAS doesn't use the `key_equal` - - Use memcmp for checking against sentinel value(s) - - Document that bitwise equality is used - -- Require unique object representation? - - Sentinel may have padding bits, which requires zero-init of buffer before sentinel init - - Can add support in the future in C++17 and on - - -# insert_erase_hash_array (P1) -## Summary -- Fixed Size -- Concurrent insert/find/erase -- Primitive (CASable) keys -- Arbitrary value types -- *THREE* key sentinel values: `EMPTY, FILLING, ERASED` -- Needs template parameter for atomic scope - - System, Shared, etc. see libcu++ thread_scope -- *Needs more study of DL use case* - - -# general_purpose_hash_array (P2) -## Summary -- Fixed size -- Arbitrary key/value -- Control state (byte/bits) per cell - - Additional memory overhead -- Concurrent insert/find/erase -- No sentinel values required - - - -## Operations - -### `insert` -```c++ -/** - * @brief Attempts to insert a key, value pair into the map. - * - * Returns an iterator, boolean pair. - * - * If the new key already present in the map, the iterator points to - * the location of the existing key and the boolean is `false` indicating - * that the insert did not succeed. - * - * If the new key was not present, the iterator points to the location - * where the insert occured and the boolean is `true` indicating that the - * insert succeeded. - * - * @param insert_pair The pair to insert - * @param key_equal Binary predicate to use for equality comparison between keys - * @return Iterator, Boolean pair. Iterator is to the location of the - * newly inserted pair, or the existing pair that prevented the insert. - * Boolean indicates insert success. - */ -template -thrust::pair insert( value_type const& v, KeyEqual key_equal = std::equal_to{}); -``` -### `find` -```c++ -/** - * @brief Searches the map for the specified key. - * - * @param k The key to search for - * @param key_equal Binary predicate to use for equality comparison between keys - * @return An iterator to the key if it exists, else map.end() - */ -template -const_iterator find( Key const& k, KeyEqual key_equal = std::equal_to{}); -``` - -### `erase` - -```c++ -/** - * @brief Erases the specified key (if it exists). - * - * @param k The key to erase - * @param key_equal Binary predicate to use for equality comparison between keys - * @returns `true` If `key` existed as was removed - * @returns `false` If `key` does not exists - */ -template -bool erase( Key const& k, KeyEqual key_equal = std::equal_to{}); -``` - +| Tentative Name | Summary | Priority | Est. Release | Size | Supported Key Types | Supported Value Types | Duplicate Keys? | Sentinel Values? | Insert | Find | Concurrent
Insert/Find? | Erase | Concurrent
Insert/Find/Erase? | Bulk Insert | Bulk Find | +|:--------------------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------:|:------------:|:--------:|:-------------------:|:---------------------:|:---------------:|:----------------:|:------:|:----:|:---------------------------:|:-----:|:---------------------------------:|:-----------:|:---------:| +| `static_map` | A fixed-size, open addressing hash map using linear probing.
Requires reserving sentinel key/values for empty slots.
Supports insert/find (not concurrent). Does not support erase. | P0 | Aug 2020 | Static | Arithmetic | Trivially Copyable | No | Yes. Key & Value | Yes | Yes | No | No | N/A | Yes | Yes | +| `chained_map` | A hash map that can grow by chaining together multiple `static_map`
submaps. Requires reserving sentinel key/values for empty slots.
Growth happens automatically in bulk insert operations, or
can be done manually by user. | P0 | Aug 2020 | Dynamic | Arithmetic | Trivially Copyable | No | Yes. Key & Value | Yes | Yes | No | No | N/A | Yes | Yes | +| `static_multimap` | A fixed-size, open addressing hash multimap using linear probing.
Supports insert/find (not concurrent). Does not support erase.
Requires reserving sentinel key/values for empty slots. | P1 | ? | Static | Arithmetic | Trivially Copyable | Yes | Yes. Key & Value | Yes | Yes | No | No | N/A | Yes | Yes | +| `chained_multimap` | A hash multimap that can grow by chaining together multiple `static_multimap`
submaps. Growth happens automatically in bulk insert operations, or
can be done manually by user. Requires reserving sentinel key/values for empty slots. | P1 | ? | Dynamic | Arithmetic | Trivially Copyable | Yes | Yes. Key & Value | Yes | Yes | No | No | N/A | Yes | Yes | +| `general_static_map` | A fixed-size, open addressing hash map using linear probing.
Uses an additional array of status bits instead of sentinels for empty slots.
Tentatively supports concurrent insert/find/erase. | P2 | ? | Static | Trivially Copyable? | Trivially Copyable? | No | No | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `general_chained_map` | A hash map that can grow by chaining together multiple `general_static_map`
submaps. Growth happens automatically in bulk insert operations, or
can be done manually by user. Uses status bits instead of sentinel values. | P2 | ? | Dynamic | Trivially Copyable? | Trivially Copyable? | No | No | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `general_static_multimap` | A fixed-size, open addressing hash multimap using linear probing.
Uses an additional array of status bits instead of sentinels for empty slots.
Tentatively supports concurrent insert/find/erase. | P2 | ? | Static | Trivially Copyable? | Trivially Copyable? | Yes | No | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| `general_chained_multimap` | A hash multimap that can grow by chaining together multiple `general_static_multimap`
submaps. Growth happens automatically in bulk insert operations, or
can be done manually by user. Uses status bits instead of sentinel values. | P2 | ? | Dynamic | Trivially Copyable? | Trivially Copyable? | Yes | No | Yes | Yes | Yes | Yes | Yes | Yes | Yes | From 896f60cc4029cf8b8ebe3bd850d051943e581524 Mon Sep 17 00:00:00 2001 From: Jake Hemstad Date: Thu, 9 Jul 2020 12:26:48 -0500 Subject: [PATCH 9/9] Update design.md --- design.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/design.md b/design.md index cb395a0c4..29fc2fa83 100644 --- a/design.md +++ b/design.md @@ -3,13 +3,13 @@ full-featured structures that may be less performant. cuCollections will likely have several classes that are on different points on this spectrum. -| Tentative Name | Summary | Priority | Est. Release | Size | Supported Key Types | Supported Value Types | Duplicate Keys? | Sentinel Values? | Insert | Find | Concurrent
Insert/Find? | Erase | Concurrent
Insert/Find/Erase? | Bulk Insert | Bulk Find | -|:--------------------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------:|:------------:|:--------:|:-------------------:|:---------------------:|:---------------:|:----------------:|:------:|:----:|:---------------------------:|:-----:|:---------------------------------:|:-----------:|:---------:| -| `static_map` | A fixed-size, open addressing hash map using linear probing.
Requires reserving sentinel key/values for empty slots.
Supports insert/find (not concurrent). Does not support erase. | P0 | Aug 2020 | Static | Arithmetic | Trivially Copyable | No | Yes. Key & Value | Yes | Yes | No | No | N/A | Yes | Yes | -| `chained_map` | A hash map that can grow by chaining together multiple `static_map`
submaps. Requires reserving sentinel key/values for empty slots.
Growth happens automatically in bulk insert operations, or
can be done manually by user. | P0 | Aug 2020 | Dynamic | Arithmetic | Trivially Copyable | No | Yes. Key & Value | Yes | Yes | No | No | N/A | Yes | Yes | -| `static_multimap` | A fixed-size, open addressing hash multimap using linear probing.
Supports insert/find (not concurrent). Does not support erase.
Requires reserving sentinel key/values for empty slots. | P1 | ? | Static | Arithmetic | Trivially Copyable | Yes | Yes. Key & Value | Yes | Yes | No | No | N/A | Yes | Yes | -| `chained_multimap` | A hash multimap that can grow by chaining together multiple `static_multimap`
submaps. Growth happens automatically in bulk insert operations, or
can be done manually by user. Requires reserving sentinel key/values for empty slots. | P1 | ? | Dynamic | Arithmetic | Trivially Copyable | Yes | Yes. Key & Value | Yes | Yes | No | No | N/A | Yes | Yes | -| `general_static_map` | A fixed-size, open addressing hash map using linear probing.
Uses an additional array of status bits instead of sentinels for empty slots.
Tentatively supports concurrent insert/find/erase. | P2 | ? | Static | Trivially Copyable? | Trivially Copyable? | No | No | Yes | Yes | Yes | Yes | Yes | Yes | Yes | -| `general_chained_map` | A hash map that can grow by chaining together multiple `general_static_map`
submaps. Growth happens automatically in bulk insert operations, or
can be done manually by user. Uses status bits instead of sentinel values. | P2 | ? | Dynamic | Trivially Copyable? | Trivially Copyable? | No | No | Yes | Yes | Yes | Yes | Yes | Yes | Yes | -| `general_static_multimap` | A fixed-size, open addressing hash multimap using linear probing.
Uses an additional array of status bits instead of sentinels for empty slots.
Tentatively supports concurrent insert/find/erase. | P2 | ? | Static | Trivially Copyable? | Trivially Copyable? | Yes | No | Yes | Yes | Yes | Yes | Yes | Yes | Yes | -| `general_chained_multimap` | A hash multimap that can grow by chaining together multiple `general_static_multimap`
submaps. Growth happens automatically in bulk insert operations, or
can be done manually by user. Uses status bits instead of sentinel values. | P2 | ? | Dynamic | Trivially Copyable? | Trivially Copyable? | Yes | No | Yes | Yes | Yes | Yes | Yes | Yes | Yes | +| Tentative Name | Summary | Priority | Est. Release | Size | Supported Key Types | Supported Value Types | Duplicate Keys? | Sentinel Values? | Insert | Find | Concurrent
Insert/Find? | Erase | Concurrent
Insert/Find/Erase? | Bulk Insert | Bulk Find | +|:--------------------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------:|:------------:|:--------:|:-------------------:|:---------------------:|:---------------:|:----------------:|:------:|:----:|:---------------------------:|:-----------------------------------:|:---------------------------------:|:-----------:|:---------:| +| `static_map` | A fixed-size, open addressing hash map using linear probing.
Requires reserving sentinel key/values for empty slots.
Supports insert/find (not concurrent). Does not support erase. | P0 | Aug 2020 | Static | Arithmetic | Trivially Copyable | No | Yes. Key & Value | Yes | Yes | No | No | N/A | Yes | Yes | +| `chained_map` | A hash map that can grow by chaining together multiple `static_map`
submaps. Requires reserving sentinel key/values for empty slots.
Growth happens automatically in bulk insert operations, or
can be done manually by user. | P0 | Aug 2020 | Dynamic | Arithmetic | Trivially Copyable | No | Yes. Key & Value | Yes | Yes | No | No | N/A | Yes | Yes | +| `static_multimap` | A fixed-size, open addressing hash multimap using linear probing.
Supports insert/find (not concurrent). Does not support erase.
Requires reserving sentinel key/values for empty slots. | P1 | ? | Static | Arithmetic | Trivially Copyable | Yes | Yes. Key & Value | Yes | Yes | No | No | N/A | Yes | Yes | +| `chained_multimap` | A hash multimap that can grow by chaining together multiple `static_multimap`
submaps. Growth happens automatically in bulk insert operations, or
can be done manually by user. Requires reserving sentinel key/values for empty slots. | P1 | ? | Dynamic | Arithmetic | Trivially Copyable | Yes | Yes. Key & Value | Yes | Yes | No | No | N/A | Yes | Yes | +| `general_static_map` | A fixed-size, open addressing hash map using linear probing.
Uses an additional array of status bits instead of sentinels for empty slots.
Tentatively supports concurrent insert/find/erase. | P2 | ? | Static | Trivially Copyable? | Trivially Copyable? | No | No | Yes | Yes | Yes | Yes, but slot
cannot be reused. | Yes | Yes | Yes | +| `general_chained_map` | A hash map that can grow by chaining together multiple `general_static_map`
submaps. Growth happens automatically in bulk insert operations, or
can be done manually by user. Uses status bits instead of sentinel values. | P2 | ? | Dynamic | Trivially Copyable? | Trivially Copyable? | No | No | Yes | Yes | Yes | Yes, but slot
cannot be reused. | Yes | Yes | Yes | +| `general_static_multimap` | A fixed-size, open addressing hash multimap using linear probing.
Uses an additional array of status bits instead of sentinels for empty slots.
Tentatively supports concurrent insert/find/erase. | P2 | ? | Static | Trivially Copyable? | Trivially Copyable? | Yes | No | Yes | Yes | Yes | Yes, but slot
cannot be reused. | Yes | Yes | Yes | +| `general_chained_multimap` | A hash multimap that can grow by chaining together multiple `general_static_multimap`
submaps. Growth happens automatically in bulk insert operations, or
can be done manually by user. Uses status bits instead of sentinel values. | P2 | ? | Dynamic | Trivially Copyable? | Trivially Copyable? | Yes | No | Yes | Yes | Yes | Yes, but slot
cannot be reused. | Yes | Yes | Yes |