Files
parallel-hashmap/README.md
T

108 lines
5.5 KiB
Markdown
Raw Normal View History

2019-03-28 07:53:20 -04:00
# The Parallel Hashmap [![Build Status](https://travis-ci.org/greg7mdp/parallel-hashmap.svg?branch=master)](https://travis-ci.org/greg7mdp/parallel-hashmap) [![Build Status](https://ci.appveyor.com/api/projects/status/86kc657lp4cja8ju?svg=true)](https://ci.appveyor.com/project/greg7mdp/parallel-hashmap)
2019-03-18 21:11:58 -04:00
2019-03-28 07:53:20 -04:00
## Overview
2019-03-18 21:11:58 -04:00
2019-03-18 21:25:08 -04:00
This repository aims to provide an set of excellent hash map implementations, with the following characteristics:
2019-03-18 21:19:38 -04:00
2019-03-18 21:11:58 -04:00
- **header only**: nothing to build, just copy the `parallel_hashmap` directory to your project and you are good to go.
2019-03-18 21:19:38 -04:00
2019-03-18 21:18:07 -04:00
- compiler with **C++11 support** required, **C++14 and C++17 APIs are provided**
2019-03-18 21:19:38 -04:00
2019-03-18 21:11:58 -04:00
- **Very efficient**, significantly faster than your compiler's unordered map/set or Boost's, or than [sparsepp](https://github.com/greg7mdp/sparsepp)
2019-03-18 21:19:38 -04:00
2019-03-24 10:28:46 -04:00
- **Memory friendly**: low memory usage, although a little higher than [sparsepp](https://github.com/greg7mdp/sparsepp)
2019-03-18 21:19:38 -04:00
- supports **heterogeneous lookup**
2019-03-27 23:25:59 -04:00
2019-03-28 21:18:10 -04:00
- easy to **forward declare**: just include `phmap_fwd_decl.h` in your header files to forward declare Parallel Hashmap containers. This header is only 111 lines including comments.
2019-03-18 21:19:38 -04:00
- **Tested** on Windows (vs2015 & vs2017), linux (g++ 5, 6, 7, 8, clang++ 3.9, 4.0, 5.0) and MacOS (g++ and clang++) - click on travis and appveyor icons above for detailed test status.
2019-03-18 21:11:58 -04:00
## Fast *and* memory friendly
2019-03-28 07:53:20 -04:00
Click here [For a full writeup explaining the design and benefits of the Parallel Hashmap](https://greg7mdp.github.io/parallel-hashmap/).
2019-03-28 21:12:43 -04:00
The hashmaps provided here are built upon those open sourced by Google in the Abseil library. They use closed hashing, where values are stored directly into a memory array, avoiding memory indirections. By using parallel SSE2 instructions, these hashmaps are able to look up items by checking 16 slots in parallel, allowing the implementation to remain fast even when the table is filled up to 87.5% capacity.
2019-03-28 07:53:20 -04:00
2019-03-28 21:12:43 -04:00
> **IMPORTANT:** This repository borrows code from the [abseil-cpp](https://github.com/abseil/abseil-cpp) repository, with modifications, and may behave differently from the original. This repository is an independent work, with no guarantees implied or provided by the authors. Please visit [abseil-cpp](https://github.com/abseil/abseil-cpp) for the official Abseil libraries.
2019-03-28 07:53:20 -04:00
2019-03-19 17:58:24 -04:00
## Installation
2019-03-27 23:25:59 -04:00
Copy the parallel_hashmap directory to your project. Update your include path. That's all.
2019-03-19 17:58:24 -04:00
> A cmake configuration files (CMakeLists.txt) is provided for building the tests and examples. Command for building and running the tests is: `mkdir build && cd build && cmake -DPHMAP_BUILD_TESTS=ON .. && cmake --build . && make test`
2019-03-18 21:11:58 -04:00
## Example
```
#include <iostream>
#include <string>
#include <parallel_hashmap/phmap.h>
using phmap::flat_hash_map;
int main()
{
// Create an unordered_map of three strings (that map to strings)
flat_hash_map<std::string, std::string> email =
{
{ "tom", "tom@gmail.com"},
{ "jeff", "jk@gmail.com"},
{ "jim", "jimg@microsoft.com"}
};
// Iterate and print keys and values
for (const auto& n : email)
std::cout << n.first << "'s email is: " << n.second << "\n";
// Add a new entry
email["bill"] = "bg@whatever.com";
// and print it
std::cout << "bill's email is: " << email["bill"] << "\n";
return 0;
}
```
## Various hash maps and their pros and cons
2019-03-28 22:45:25 -04:00
The header `parallel_hashmap/phmap.h` provides the implementation for the following eight hash tables:
- phmap::flat_hash_set
- phmap::flat_hash_map
- phmap::node_hash_set
- phmap::node_hash_map
- phmap::parallel_flat_hash_set
- phmap::parallel_flat_hash_map
- phmap::parallel_node_hash_set
- phmap::parallel_node_hash_map
The full types with template parameters can be found in the [parallel_hashmap/phmap_fwd_decl.h](https://raw.githubusercontent.com/greg7mdp/parallel-hashmap/master/parallel_hashmap/phmap_fwd_decl.h) header, which is useful for forward declaring the Parallel Hashmaps when necessaary.
**Key points:**
2019-03-18 21:11:58 -04:00
2019-03-18 21:25:08 -04:00
- The `flat` hash maps may move the keys and values in memory. So if you keep a pointer to something inside a `flat` hash map, this pointer may become invalid when the map is mutated. The `node` hash maps don't, and should be used instead if this is a problem.
2019-03-18 21:11:58 -04:00
2019-03-18 21:25:08 -04:00
- The `flat` hash maps will use less memory, and usually be faster than the `node` hash maps, so use them if you can. A possible exception is when the values inserted in the hash map are large (say more than 100 bytes [*needs testing*]).
2019-03-18 21:11:58 -04:00
2019-03-18 21:25:08 -04:00
- The `parallel` hash maps are preferred when you have a few hash maps that will store a very large number of values. The `non-parallel` hash maps are preferred if you have a large number of hash maps, each storing a relatively small number of values.
2019-03-18 21:29:59 -04:00
- The benefits of the `parallel` hash maps are:
2019-03-18 21:29:33 -04:00
a. reduced peak memory usage (when resizing), and
2019-03-18 21:27:55 -04:00
b. multithreading support (and inherent internal parallelism)
2019-03-18 21:11:58 -04:00
2019-03-27 20:07:59 -04:00
## Memory usage
2019-03-28 22:45:25 -04:00
| type | memory usage |
|--------|-------------------|
| flat tables | ![flat_mem_usage](https://github.com/greg7mdp/parallel-hashmap/blob/master/html/img/flat_mem_usage.gif?raw=true) |
2019-03-28 22:46:10 -04:00
| node tables | ![node_mem_usage](https://github.com/greg7mdp/parallel-hashmap/blob/master/html/img/node_mem_usage.gif?raw=true) |
2019-03-28 22:45:25 -04:00
The load factor varies between 0.4375 (just after the resize) and 0.875 (just before the resize).
2019-03-27 20:07:59 -04:00
2019-03-28 22:45:25 -04:00
In addition, when the table resizes, the peak memory usage is an additional 50% of the new size for the *non-parallel* hashmaps, and an additional 3% of the new size for the *parallel* hashmaps (single threaded usage).
2019-03-27 20:07:59 -04:00
2019-03-18 21:11:58 -04:00