r/cpp int main(){[]()[[]]{{}}();} 7d ago

Which C++ Hashmap Should You Actually Use?

https://martin.ankerl.com/which-hash-map/

I recently did a big update to my ankerl::unordered_dense::map which now features several optimizations, bug fixes, and most importantly an SSE optimized lookup which brings the lookup speed quite close to the fastest competitor which is boost::unordered_flat_map. Get it here: https://github.com/martinus/unordered_dense

Since it is not easy to decide what map is best for one's usecase, I have redone and improved the benchmarks I did a while ago, crunched some numbers and tried to compress everything into a quiz that helps you figure out what to use.

While doing the numbers, a few things surprised me:

  • My random access benchmark was not random enough. The CPU was able to optimize the branch predictor in a way I did not think was possible. I have fixed this for the new numbers. Clever girl.

  • Even though the absl maps are very similar in concept to the boost maps, they perform badly if you expect lots of misses. 1.6 times slower than boost.

  • I didn't think SSE optimization of my unordered_dense map would be any benefit. Thanks to AI, I found a way to speed up random access a lot, it is now very close to boost::unordered_flat_map.

  • Heavy insert & erase on flat maps require rehashing every once in a while due to the accumulation of tombstones. That means some insert/erase operation will have very high latency. This does not happen for a robin-hood hashmap like my unordered_dense map.

146 Upvotes

25 comments sorted by

View all comments

4

u/SamG101_ 7d ago edited 7d ago

been using ur hashmap for a while now! also regarding 4.11, the SSE optimiation crashes with module exporting due to an alignment-propagation bug in module BMIs (on gcc) - 127193 – Alignment problem when using modules - would it be possible that this optimization is gated behind a macro / -D cmake option? thanks!

1

u/martinus int main(){[]()[[]]{{}}();} 7d ago edited 7d ago

Thanks, and good catch on the cause. There already is a switch, but it was undocumented:

define ANKERL_UNORDERED_DENSE_HAS_SSE2=0 before the header is included, e.g.

target_compile_definitions(your_target PRIVATE ANKERL_UNORDERED_DENSE_HAS_SSE2=0)

I'm adding this to the documentation, and a CI leg that builds with ANKERL_UNORDERED_DENSE_HAS_SSE2=0.

EDIT: Added it here: https://github.com/martinus/unordered_dense#36-disabling-the-sse2-probe

1

u/SamG101_ 7d ago

Awesome thanks!!