并发编程高性能计算【免费下载链接】oneTBBoneAPI Threading Building Blocks (oneTBB)项目地址https://gitcode.com/gh_mirrors/on/oneTBB点击查看免费下载oneTBBoneAPI Threading Building Blocks提供的oneapi::tbb::concurrent_unordered_map是支持并发插入、查找与遍历的无序关联容器其观察者Observers成员函数用于查询容器的底层配置get_allocator()返回内存分配器、hash_function()返回哈希函数、key_eq()返回键相等性判定谓词。本文以官方参考文档 Observers 为骨架结合仓库中 concurrent_unordered_map.h 及底层实现 _concurrent_unordered_base.h 的源码系统讲解这三个观察者的签名、返回值语义、透明哈希transparent hash机制与典型使用场景帮助你写出语义准确、可维护的并发容器代码。一、观察者方法在类模板中的地位oneapi::tbb::concurrent_unordered_map的完整类模板定义位于头文件oneapi/tbb/concurrent_unordered_map.h其声明骨架如下详见 concurrent_unordered_map_cls.rst// Defined in header oneapi/tbb/concurrent_unordered_map.h namespace oneapi { namespace tbb { template typename Key, typename T, typename Hash std::hashKey, typename KeyEqual std::equal_toKey, typename Allocator tbb_allocatorstd::pairconst Key, T class concurrent_unordered_map { public: using hasher Hash; using key_equal /*See below*/; using allocator_type Allocator; // ... // Observers allocator_type get_allocator() const; hasher hash_function() const; key_equal key_eq() const; // ... }; } }观察者方法与构造、析构、复制、迭代器、容量、并发安全/非安全修改、元素访问、查找、桶接口、哈希策略load factor、rehash、reserve以及并行区间迭代共同构成该容器的完整成员函数集合。它们的作用是读取容器在构造时被配置的三大件——分配器、哈希函数、键相等谓词供调用方在容器外部复现相同的配置逻辑例如复制构造另一个同配置容器、做内存统计、调试键冲突。从源码结构看concurrent_unordered_map本体include/oneapi/tbb/concurrent_unordered_map.h继承自concurrent_unordered_baseconcurrent_unordered_map_traitsKey, T, Hash, KeyEqual, Allocator, false其观察者接口实际由基类concurrent_unordered_base实现而concurrent_unordered_multimap则使用allow_multimapping true的同一套 traits因此两个容器共享相同的观察者语义。二、get_allocator()获取分配器副本2.1 接口语义observers.rst给出的签名与返回语义为allocator_type get_allocator() const;Returns返回与*this相关联的分配器allocator的一个副本。该方法是const成员函数返回类型是allocator_type即模板参数Allocator默认tbb_allocatorstd::pairconst Key, T按值返回副本而非引用——这是 C 标准库无序容器观察者的通用约定避免暴露容器内部状态句柄。2.2 源码实现基类concurrent_unordered_base中的实现非常简洁include/oneapi/tbb/detail/_concurrent_unordered_base.hallocator_type get_allocator() const noexcept { return my_segments.get_allocator(); }容器内部通过分桶段segments管理内存my_segments是段表对象其持有真正的分配器实例。get_allocator()直接透传该分配器的副本并且被标记为noexcept——因为分配器的查询不涉及内存分配或可能抛异常的操作。2.3 典型使用场景复制构造语义官方文档 construction_destruction_copying.rst 明确规定复制构造函数未显式提供分配器时会通过std::allocator_traitsallocator_type::select_on_container_copy_construction(other.get_allocator())取得新容器的分配器移动构造则调用std::move(other.get_allocator())。也就是说get_allocator()是容器复制/移动操作内部配置传播的关键一环。外部复用配置当你需要创建一组配置一致的并发容器例如同一批线程各自持有同分配器的 map时可以直接取回分配器副本再传给构造函数using Map oneapi::tbb::concurrent_unordered_mapstd::string, int; Map m1(/* bucket_count */ 64, /* hash */ Map::hasher{}, /* equal */ Map::key_equal{}, MyAllocator{}); // 复用 m1 的分配器构造新容器 Map m2(m1.get_allocator()); // 或复制构造分配器由 select_on_container_copy_construction 决定 Map m3(m1);内存使用统计当Allocator是有状态的统计型分配器时通过get_allocator()取回实例可以读取累计分配/释放次数等状态。仓库测试 conformance_concurrent_vector.cpp 展示了类似的统计型分配器用法items_allocated、items_freed等计数。节点句柄校验node_type节点句柄也提供get_allocator()测试 node_handling_support.h 中通过nh.get_allocator() test_table.get_allocator()校验节点句柄与容器分配器一致这是使用unsafe_extract/insert(node_type)组合时保证内存来源正确的惯用检查。2.4 并发安全说明与查找Lookup、并发安全修改Concurrently safe modifiers不同observers.rst本身并未承诺观察者在并发写下的线程安全边界从语义上讲这些查询是只读的但按 oneTBB 文档惯例涉及容器整体结构的并发操作仍应遵循容器自身的线程安全模型并发插入/查找/遍历安全unsafe_前缀操作不并发安全。三、hash_function()获取哈希函数副本3.1 接口语义hasher hash_function() const;Returns返回与*this相关联的哈希函数hash function的一个副本。hasher即模板参数Hash默认std::hashKey。该函数返回的哈希函数与容器内部用于确定元素所属桶编号的函数完全一致。3.2 源码实现链路concurrent_unordered_map的 traits 中定义了hash_compare_type d1::hash_compareKey, Hash, KeyEqual见 concurrent_unordered_map.h。哈希与相等性被组合封装在hash_compare适配器中基类实现如下include/oneapi/tbb/detail/_concurrent_unordered_base.hhasher hash_function() const { return my_hash_compare.hash_function(); }而hash_compare内部include/oneapi/tbb/detail/_hash_compare.h保存成员my_hasher与my_equal并同样按值返回副本hasher hash_function() const { return my_hasher; } key_equal key_eq() const { return my_equal; }调用链可概括为concurrent_unordered_map::hash_function() └─ concurrent_unordered_base::hash_function() // 透传 └─ hash_compare::hash_function() // 返回 my_hasher 副本3.3 透明哈希与泛型重载hash_compare还提供了模板化重载include/oneapi/tbb/detail/_hash_compare.htemplate typename K, typename typename std::enable_ifis_transparent_hash::value, K::type std::size_t operator()( const K key ) const { return std::size_t(my_hasher(key)); }当Hash定义了嵌套类型transparent_key_equal且其内部声明is_transparent时is_transparent_hash为std::true_typehash_compare即可接受与Key不同类型的键——这就是find(literal)、contains(K)等透明查找操作无需构造临时Key对象的底层机制详见 lookup.rst 中关于hasher::transparent_key_equal的参与条件说明。该特质检测实现在 _containers_helpers.htemplate typename Key, typename Hasher, typename KeyEqual, typename void struct has_transparent_key_equal : std::false_type { using type KeyEqual; }; template typename Key, typename Hasher, typename KeyEqual, typename ... struct has_transparent_key_equalKey, Hasher, KeyEqual, tbb::detail::void_ttypename Hasher::transparent_key_equal : std::true_type { ... };3.4 使用场景复现桶分布自行对某个键计算hash_function()(key) % unsafe_bucket_count()可预测该键将落入哪个桶用于调试与桶接口unsafe_begin(n)/unsafe_bucket(key)见类文档中的 Bucket interface 小节配合分析冲突。一致性验证在测试或日志中确认容器确实使用了预期的哈希函数例如自定义了分片/加盐哈希后通过hash_function()返回的实例做抽检验证。四、key_eq()获取键相等性谓词副本4.1 接口语义key_equal key_eq() const;Returns返回与*this相关联的键相等性判定谓词key equality predicate的一个副本。注意这里的key_equal并不总是直接等于模板参数KeyEqual其解析规则在类文档 concurrent_unordered_map_cls.rst 中有明确规定若Hash::transparent_key_equal有效且表示一个类型则key_equal取该限定名指向的类型此时若模板参数KeyEqual不是std::equal_toKey或Hash::transparent_key_equal::is_transparent无效/不表示类型程序为 ill-formed编译错误。否则key_equal即模板参数KeyEqual默认std::equal_toKey。4.2 源码实现基类同样做一层透传include/oneapi/tbb/detail/_concurrent_unordered_base.hkey_equal key_eq() const { return my_hash_compare.key_eq(); }hash_compare的key_equal类型定义为typename is_transparent_hash::typeinclude/oneapi/tbb/detail/_hash_compare.h与上面第三节的透明哈希检测保持一致透明哈希启用时该类型为Hash::transparent_key_equal否则为KeyEqual。因此key_eq()返回的谓词与容器内部用于键等价判断的谓词是同一实现。4.3 使用场景using Map oneapi::tbb::concurrent_unordered_mapstd::string, int; Map m; auto eq m.key_eq(); // 判断两个键在容器语义下是否等价与容器内部判定一致 bool same eq(key, key);当使用自定义KeyEqual如大小写不敏感比较、近似比较时key_eq()可用于在容器外部复现按容器规则的两个键是否等价的判断避免手工重复实现比较逻辑。五、三个观察者的配套验证测试证据仓库测试 concurrent_unordered_common.h 明确覆盖了这两个哈希相关观察者// hasher hash_function() const; cont.hash_function(); // key_equal key_eq() const; cont.key_eq();该公共测试头被concurrent_unordered_map、concurrent_unordered_multimap、concurrent_unordered_set、concurrent_unordered_multiset的测试共用而get_allocator()则在 concurrent_associative_common.hauto alloc c.get_allocator();与 container_move_support.h移动构造/移动赋值场景下校验dst.get_allocator()与源容器分配器关系中反复使用。这些测试从侧面印证了三个观察者在并发容器家族中的一致性契约它们都返回与容器当前配置严格一致的副本。六、观察者在并发容器家族中的通用性观察者并非concurrent_unordered_map独有。搜索include/oneapi/tbb目录可以看到get_allocator、hash_function、key_eq同样出现在concurrent_hash_map.h、concurrent_set.h、concurrent_unordered_set.h、concurrent_priority_queue.h、concurrent_queue.h等多个容器中在参考文档目录doc/main/reference/source/containers/下concurrent_map_cls/observers.rst、concurrent_set_cls/observers.rst、concurrent_multimap_cls/observers.rst、concurrent_unordered_multiset_cls/observers.rst等与本文主题页面并列存在。因此理解concurrent_unordered_map的这三个观察者也就掌握了 oneTBB 大多数并发容器观察者接口的通用模式观察者返回类型返回内容实现要点concurrent_unordered_mapget_allocator()allocator_type分配器副本透传my_segments.get_allocator()noexcepthash_function()hasher哈希函数副本经my_hash_compare.hash_function()返回my_hasherkey_eq()key_equal键相等谓词副本经my_hash_compare.key_eq()返回my_equal透明哈希时类型变为Hash::transparent_key_equal七、小结concurrent_unordered_map的观察者方法虽然体量小却是容器配置可观测性的关键入口get_allocator()支撑复制/移动构造的分配器传播select_on_container_copy_construction、std::move(other.get_allocator())也可用于统计型分配器的状态读取hash_function()与key_eq()返回与容器内部完全一致的哈希与等价判定副本配合透明哈希transparent_key_equal机制可在容器外部精确复现桶分布与键等价语义。三者共享同一套实现链路类模板本身只定义 traits 与接口真正的状态保存在基类concurrent_unordered_base的段表与hash_compare适配器中分别见 _concurrent_unordered_base.h 与 _hash_compare.h这保证了观察者返回值的配置一致性。在使用中建议遵循只读查询、按值使用、必要时与查找/桶接口配合验证的原则即可安全高效地利用这三个接口。赞分享并发编程高性能计算【免费下载链接】oneTBBoneAPI Threading Building Blocks (oneTBB)项目地址https://gitcode.com/gh_mirrors/on/oneTBB点击查看免费下载相关推荐oneTBB concurrent_set 观察器ObserversAPI 详解get_allocator / key_comp / value_comp 的语义、实现与测试验证oneTBB concurrent_set 观察器ObserversAPI 详解get_allocator / key_comp / value_comp并发编程高性能计算告别在线教材卡顿tchMaterial-parser一键把电子课本预览页变成离线PDF只需2分钟告别在线教材卡顿tchMaterial parser一键把电子课本预览页变成离线PDF只需2分钟 面向新手的国家中小学智慧教育平台电子课本离线下载完整步骤附网页爬虫教育oneTBB concurrent_multiset Observers 成员函数详解get_allocator、key_comp 与 value_componeTBB concurrent_multiset Observers 成员函数详解get_allocator、key_comp 与 value_comp并发编程高性能计算上一篇零延迟游戏串流Sunshine自托管服务器完整配置指南下一篇一机多开Nucleus Co-Op带你轻松搞定本地多人游戏分屏创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考