hud*_*dac 6 c++ boost memory-management unordered-map allocator
我想创建unordered_map(因为我特别想要一个哈希映射).我想在开头分配它的最大尺寸(根据我的约束).
所以,如果我想分配256个条目,每个条目的大小是1B(只是一个例子.假设1Byte包括Key和Value).然后我的unordered_map键+条目的总大小是256B.我想在分配器中预先分配256B.
然后,当unordered_map将调用allocate()/时deallocate(),allocator将从已分配的内存中给它1B.
typedef boost::unordered::unordered_map<int, MyClass, boost::hash<int>, std::equal_to<MyClass>, ??? > > myMap
它是否存在于BOOST中?或者别的地方?
----编辑----
正如我所看到的(感谢此处的答案) - 我的问题有两个解决方案:
实现一个allocator,持有一个boost::pool<>.这pool是在allocator构造函数中构建的.当allocate()被调用时unordered_map,它实际上调用pool.malloc(),并且当deallocate()调用unordered_map它时,它实际调用pool.free().
使用已经实现的allocator,pool_allocator如下所示:
typedef pool_allocator<std::pair<MyKey, MyClass>, boost::default_user_allocator_new_delete, boost::mutex, 1024 >) MyAllocator;
typedef unordered_map<MyKey, MyClass, hash, eq, MyAllocator> MyUnorderedMap;
秒选项对我来说仍然不清楚,因为:
a.我只能声明一个MyUnorderedMap吗?
湾 我怎样才能申报使用不同的新MyUnorderedMap next_block大小比1024在运行时间?
您所描述的实际上只能通过诸如 Boost Intrusive“Maps”(实际上是设置)之类的东西来实现。
\n\n然而,要获得真正的 1B 分配元素,您需要定义自定义有状态值 Traits,以便您可以将节点索引元数据与元素有效负载分开存储。
\n\n然而,从您声称元素类型为 1B 的事实来看(对于具体的键和值类型来说,这显然永远不会成立),我不会假设您实际上出于“某种原因”想要这个人为的解决方案。
\n\n相反,让我建议三种更普通的方法:
\n\nflat_mapflat_map如果哈希查找不是强制性的,您可以通过预先保留连续元素存储并存储有序映射来简化很多工作:
\n\n\n\n#include <boost/container/flat_map.hpp>\n#include <iostream>\n\nusing Elements = boost::container::flat_map<std::string, std::string>;\n\nint main() {\n Elements map;\n map.reserve(256); // pre-allocate 256 "nodes"!\n\n map.insert({\n { "one", "Eins" },\n { "two", "Zwei" },\n { "three", "Drei" },\n { "four", "Vier" },\n { "five", "Fuenf" },\n });\n\n for (auto& e : map) {\n std::cout << "Entry: " << e.first << " -> " << e.second << "\\n";\n }\n\n std::cout << "map[\\"three\\"] -> " << map["three"] << "\\n";\n}\nRun Code Online (Sandbox Code Playgroud)\n\n印刷
\n\nEntry: five -> Fuenf\nEntry: four -> Vier\nEntry: one -> Eins\nEntry: three -> Drei\nEntry: two -> Zwei\nmap["three"] -> Drei\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n\n\n注意事项侵入式容器有其自身的一系列权衡。管理元素的底层存储可能容易出错。挂钩的自动链接行为会抑制 和 类似的恒定时间实现
\nsize()(empty()在某些无序集配置上),因此这可能不适合您。
#include <boost/intrusive/unordered_set.hpp>\n#include <boost/intrusive/unordered_set_hook.hpp>\n#include <iostream>\n\nnamespace bi = boost::intrusive;\n\nstruct Element;\n\nnamespace boost {\n template <> struct hash<Element> {\n size_t operator()(Element const& e) const;\n };\n}\n\nstruct Element : bi::unordered_set_base_hook<> {\n std::string key;\n mutable std::string value;\n\n Element(std::string k = "", std::string v = "") \n : key(std::move(k)), value(std::move(v)) { }\n\n bool operator==(Element const& other) const { return key == other.key; }\n};\n\nsize_t boost::hash<Element>::operator()(Element const& e) const {\n return hash_value(e.key); \n}\n\nusing Elements = bi::unordered_set<Element>;\n\nint main() {\n std::array<Element, 256> storage; // reserved 256 entries\n std::array<Elements::bucket_type, 100> buckets; // buckets for the hashtable\n\n Elements hashtable(Elements::bucket_traits(buckets.data(), buckets.size()));\n\n storage[0] = { "one", "Eins" };\n storage[1] = { "two", "Zwei" };\n storage[2] = { "three", "Drei" };\n storage[3] = { "four", "Vier" };\n storage[4] = { "five", "Fuenf" };\n\n hashtable.insert(storage.data(), storage.data() + 5);\n\n for (auto& e : hashtable) {\n std::cout << "Hash entry: " << e.key << " -> " << e.value << "\\n";\n }\n\n std::cout << "hashtable[\\"three\\"] -> " << hashtable.find({"three"})->value << "\\n";\n}\nRun Code Online (Sandbox Code Playgroud)\n\n印刷
\n\nHash entry: two -> Zwei\nHash entry: four -> Vier\nHash entry: five -> Fuenf\nHash entry: three -> Drei\nHash entry: one -> Eins\nhashtable["three"] -> Drei\nRun Code Online (Sandbox Code Playgroud)\n\n如果您绝对需要基于节点的存储,请考虑使用自定义分配器。
\n\n\n\n\n\n\n\xc2\xb9 您会注意到(至少对于 Boost 的 unordered_map 实现)分配器用于两种类型(桶指针和值节点),因此可能有两种固定大小的分配。
\n\n(请参阅示例底部的清理调用)
\n
#include <boost/pool/pool_alloc.hpp>\n#include <boost/unordered/unordered_map.hpp>\n#include <iostream>\n\nusing RawMap = boost::unordered_map<std::string, std::string>;\nusing Elements = boost::unordered_map<\n std::string, std::string,\n RawMap::hasher, RawMap::key_equal,\n boost::fast_pool_allocator<RawMap::value_type>\n >;\n\nint main() {\n {\n Elements hashtable;\n\n hashtable.insert({\n { "one", "Eins" },\n { "two", "Zwei" },\n { "three", "Drei" },\n { "four", "Vier" },\n { "five", "Fuenf" },\n });\n\n for (auto& e : hashtable) {\n std::cout << "Hash entry: " << e.first << " -> " << e.second << "\\n";\n }\n\n std::cout << "hashtable[\\"three\\"] -> " << hashtable.find("three")->second << "\\n";\n }\n\n // OPTIONALLY: free up system allocations in fixed size pools\n // Two sizes, are implementation specific. My 64 system has the following:\n boost::singleton_pool<boost::fast_pool_allocator_tag, 8>::release_memory(); // the bucket pointer allocation\n boost::singleton_pool<boost::fast_pool_allocator_tag, 32>::release_memory(); // the ptr_node<std::pair<std::string const, std::string> >\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
1258 次 |
| 最近记录: |