mirror of
https://github.com/greg7mdp/parallel-hashmap.git
synced 2026-08-29 08:34:39 +08:00
wip
This commit is contained in:
Vendored
+4
-5
@@ -8,6 +8,7 @@ PROGS = stl_unordered_map sparsepp phmap abseil_flat abseil_parallel_flat
|
||||
BUILD_PROGS = $(addprefix build/,$(PROGS))
|
||||
SIZE = 100000000
|
||||
ABSEIL = ../../abseil-cpp
|
||||
PHMAP_SRC = ../parallel_hashmap
|
||||
|
||||
all: test
|
||||
|
||||
@@ -20,7 +21,7 @@ build/stl_unordered_map: bench.cc Makefile
|
||||
build/sparsepp: bench.cc Makefile
|
||||
$(CXX) -DSPARSEPP -I../../sparsepp bench.cc -o $@
|
||||
|
||||
build/phmap: bench.cc Makefile
|
||||
build/phmap: bench.cc Makefile $(PHMAP_SRC)/phmap.h
|
||||
$(CXX) -DPHMAP -I.. bench.cc /MD -o $@
|
||||
|
||||
build/abseil_flat: bench.cc Makefile
|
||||
@@ -34,7 +35,8 @@ progs: $(BUILD_PROGS)
|
||||
test: builddir progs
|
||||
-rm -f output
|
||||
#./build/stl_unordered_map $(SIZE) random >> output
|
||||
./build/abseil_flat $(SIZE) random >> output
|
||||
#./build/abseil_flat $(SIZE) random >> output
|
||||
./build/phmap $(SIZE) random >> output
|
||||
#./build/sparsepp $(SIZE) random >> output
|
||||
./build/abseil_parallel_flat $(SIZE) random >> output
|
||||
python make_chart_data.py < output
|
||||
@@ -47,11 +49,8 @@ test_cust:
|
||||
./build/abseil_parallel_flat $(SIZE) random >> output
|
||||
python make_chart_data.py < output
|
||||
|
||||
|
||||
|
||||
chart:
|
||||
python make_chart_data.py < output
|
||||
|
||||
clean:
|
||||
-rm -fr output build
|
||||
|
||||
|
||||
+13
-8
@@ -17,27 +17,29 @@
|
||||
#if defined(ABSEIL_PARALLEL_FLAT)
|
||||
#include "absl/container/parallel_flat_hash_map.h"
|
||||
#define MAPNAME absl::parallel_flat_hash_map
|
||||
#define NMSP absl
|
||||
#else
|
||||
#include "parallel_hashmap/phmap.h"
|
||||
#define MAPNAME phmap::parallel_flat_hash_map
|
||||
#define NMSP phmap
|
||||
#endif
|
||||
|
||||
//#define MT_SUPPORT 2
|
||||
#define MT_SUPPORT 1
|
||||
#if MT_SUPPORT == 1
|
||||
// create the parallel_flat_hash_map without internal mutexes, for when
|
||||
// we programatically ensure that each thread uses different internal submaps
|
||||
// --------------------------------------------------------------------------
|
||||
#define EXTRAARGS , absl::container_internal::hash_default_hash<K>, \
|
||||
absl::container_internal::hash_default_eq<K>, \
|
||||
std::allocator<std::pair<const K, V>>, 4, absl::NullMutex
|
||||
#define EXTRAARGS , NMSP::container_internal::hash_default_hash<K>, \
|
||||
NMSP::container_internal::hash_default_eq<K>, \
|
||||
std::allocator<std::pair<const K, V>>, 4, NMSP::NullMutex
|
||||
#elif MT_SUPPORT == 2
|
||||
// create the parallel_flat_hash_map with internal mutexes, for when
|
||||
// we read/write the same parallel_flat_hash_map from multiple threads,
|
||||
// without any special precautions.
|
||||
// --------------------------------------------------------------------------
|
||||
#define EXTRAARGS , absl::container_internal::hash_default_hash<K>, \
|
||||
absl::container_internal::hash_default_eq<K>, \
|
||||
std::allocator<std::pair<const K, V>>, 4, absl::Mutex
|
||||
#define EXTRAARGS , NMSP::container_internal::hash_default_hash<K>, \
|
||||
NMSP::container_internal::hash_default_eq<K>, \
|
||||
std::allocator<std::pair<const K, V>>, 4, NMSP::Mutex
|
||||
#else
|
||||
#define EXTRAARGS
|
||||
#endif
|
||||
@@ -357,8 +359,11 @@ int main(int argc, char ** argv)
|
||||
srand(1); // for a fair/deterministic comparison
|
||||
Timer timer(true);
|
||||
|
||||
if (!strcmp(program_slug,"absl::parallel_flat_hash_map"))
|
||||
#ifdef MT_SUPPORT
|
||||
if (!strcmp(program_slug,"absl::parallel_flat_hash_map") ||
|
||||
!strcmp(program_slug,"phmap::parallel_flat_hash_map"))
|
||||
program_slug = xstr(MAPNAME) "_mt";
|
||||
#endif
|
||||
|
||||
std::thread t1(memlog);
|
||||
|
||||
|
||||
Vendored
+13
-7
@@ -44,6 +44,8 @@ proper_names = {
|
||||
'std::unordered_map': 'std::unordered_map (1 thread)',
|
||||
'spp::sparse_hash_map': 'sparsepp (1 thread, use_spp_alloc)',
|
||||
'absl::flat_hash_map': 'absl::flat_hash_map (1 thread)',
|
||||
'phmap::parallel_flat_hash_map': 'phmap::parallel_flat_hash_map (1 thread)',
|
||||
'phmap::parallel_flat_hash_map_mt': 'phmap::parallel_flat_hash_map (8 thread8)',
|
||||
'absl::parallel_flat_hash_map': 'absl::parallel_flat_hash_map (1 thread)',
|
||||
'absl::parallel_flat_hash_map_mt': 'absl::parallel_flat_hash_map (8 threads)',
|
||||
'absl::parallel_flat_hash_map_4': 'absl::parallel_flat_hash_map (N=4, 8 threads)',
|
||||
@@ -52,14 +54,16 @@ proper_names = {
|
||||
}
|
||||
|
||||
proper_color = {
|
||||
'std::unordered_map': 0,
|
||||
'std::unordered_map': 0,
|
||||
'spp::sparse_hash_map': 0,
|
||||
'absl::flat_hash_map': 1,
|
||||
'absl::parallel_flat_hash_map': 2,
|
||||
'absl::parallel_flat_hash_map_mt': 2,
|
||||
'absl::parallel_flat_hash_map_4': 2,
|
||||
'absl::parallel_flat_hash_map_5': 3,
|
||||
'absl::parallel_flat_hash_map_6': 4
|
||||
'absl::flat_hash_map': 1,
|
||||
'phmap::parallel_flat_hash_map': 2,
|
||||
'phmap::parallel_flat_hash_map_mt': 2,
|
||||
'absl::parallel_flat_hash_map': 3,
|
||||
'absl::parallel_flat_hash_map_mt': 3,
|
||||
'absl::parallel_flat_hash_map_4': 3,
|
||||
'absl::parallel_flat_hash_map_5': 4,
|
||||
'absl::parallel_flat_hash_map_6': 5
|
||||
}
|
||||
|
||||
bench_titles = {
|
||||
@@ -79,6 +83,8 @@ program_slugs = [
|
||||
'sparsepp',
|
||||
'absl::flat_hash_map',
|
||||
'absl::parallel_flat_hash_map',
|
||||
'phmap::parallel_flat_hash_map',
|
||||
'phmap::parallel_flat_hash_map_mt',
|
||||
'absl::parallel_flat_hash_map_mt',
|
||||
'absl::parallel_flat_hash_map_4',
|
||||
'absl::parallel_flat_hash_map_5',
|
||||
|
||||
Vendored
+21
-3
@@ -34,8 +34,6 @@
|
||||
// limitations under the License.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
@@ -263,6 +261,7 @@ inline size_t HashSeed(const ctrl_t* ctrl) {
|
||||
inline size_t H1(size_t hash, const ctrl_t* ctrl) {
|
||||
return (hash >> 7) ^ HashSeed(ctrl);
|
||||
}
|
||||
|
||||
inline ctrl_t H2(size_t hash) { return hash & 0x7F; }
|
||||
|
||||
inline bool IsEmpty(ctrl_t c) { return c == kEmpty; }
|
||||
@@ -301,6 +300,7 @@ struct GroupSse2Impl
|
||||
}
|
||||
|
||||
// Returns a bitmask representing the positions of slots that match hash.
|
||||
// ----------------------------------------------------------------------
|
||||
BitMask<uint32_t, kWidth> Match(h2_t hash) const {
|
||||
auto match = _mm_set1_epi8(hash);
|
||||
return BitMask<uint32_t, kWidth>(
|
||||
@@ -308,6 +308,7 @@ struct GroupSse2Impl
|
||||
}
|
||||
|
||||
// Returns a bitmask representing the positions of empty slots.
|
||||
// ------------------------------------------------------------
|
||||
BitMask<uint32_t, kWidth> MatchEmpty() const {
|
||||
#if PHMAP_HAVE_SSSE3
|
||||
// This only works because kEmpty is -128.
|
||||
@@ -319,6 +320,7 @@ struct GroupSse2Impl
|
||||
}
|
||||
|
||||
// Returns a bitmask representing the positions of empty or deleted slots.
|
||||
// -----------------------------------------------------------------------
|
||||
BitMask<uint32_t, kWidth> MatchEmptyOrDeleted() const {
|
||||
auto special = _mm_set1_epi8(kSentinel);
|
||||
return BitMask<uint32_t, kWidth>(
|
||||
@@ -326,12 +328,14 @@ struct GroupSse2Impl
|
||||
}
|
||||
|
||||
// Returns the number of trailing empty or deleted elements in the group.
|
||||
// ----------------------------------------------------------------------
|
||||
uint32_t CountLeadingEmptyOrDeleted() const {
|
||||
auto special = _mm_set1_epi8(kSentinel);
|
||||
return TrailingZeros(
|
||||
_mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl)) + 1);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
|
||||
auto msbs = _mm_set1_epi8(static_cast<char>(-128));
|
||||
auto x126 = _mm_set1_epi8(126);
|
||||
@@ -3971,6 +3975,20 @@ struct HashEq
|
||||
|
||||
#if 0
|
||||
|
||||
struct int64_t_hash
|
||||
{
|
||||
using is_transparent = void;
|
||||
size_t operator()(int64_t v) const {
|
||||
return (size_t)v;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct HashEq<int64_t> {
|
||||
using Hash = int64_t_hash;
|
||||
using Eq = std::equal_to<int64_t>;
|
||||
};
|
||||
|
||||
struct StringHash
|
||||
{
|
||||
using is_transparent = void;
|
||||
@@ -4118,7 +4136,7 @@ struct HashtableDebugAccess<Set, phmap::void_t<typename Set::raw_hash_set>>
|
||||
// -----------------------------------------------------------------------------
|
||||
// A class that implements the Mutex interface, but does nothing. This is to be
|
||||
// used as a default template parameters for classes who provide optional
|
||||
// internal locking (like absl::parallel_flat_hash_map).
|
||||
// internal locking (like phmap::parallel_flat_hash_map).
|
||||
// -----------------------------------------------------------------------------
|
||||
class PHMAP_LOCKABLE NullMutex {
|
||||
public:
|
||||
|
||||
Reference in New Issue
Block a user