mold 项目第三方依赖 TBB 指南:make_edges 函数模板实现流图一对多/多对一建边

发布时间:2026/11/7 14:43:25

mold 项目第三方依赖 TBB 指南:make_edges 函数模板实现流图一对多/多对一建边 mold 项目第三方依赖 TBB 指南make_edges 函数模板实现流图一对多/多对一建边【免费下载链接】moldmold: A Modern Linker 项目地址: https://gitcode.com/GitHub_Trending/mo/mold导读make_edges是 oneAPI Threading Building BlocksoneTBBFlow Graph 库中用于批量建边的函数模板它可以在一个节点与一组节点之间一次性创建全部边从而把 N 次make_edge调用压缩为一行代码。本文以 mold 仓库中 vendored 的 TBB 源码third-party/tbb为对象完整讲解make_edges的启用条件、两种连接方向、配套的make_node_set/follows/precedes工具、官方示例并深入到_flow_graph_node_set_impl.h的模板实现细节与测试用例帮助读者在编写 flow graph 时写出更简洁、可读性更高的建边代码。说明mold 作为一个现代化链接器将 oneTBB 作为第三方库整体随仓库分发见 third-party/tbb本文所讲内容即来自该目录下的 TBB 源码与官方文档可在本仓库内直接查阅验证。功能概述批量创建边make_edges函数模板的职责是在单个节点与一组节点之间创建边edge。它的使用前提是先通过make_node_set把多个节点打包成一个节点集合node_set再调用make_edges一次性完成批量连接。官方文档make_edges_function.rst明确指出使用make_edges有两种连接方式make_edges(node_set, node)节点集合中的每个节点都向单个目标节点连一条边多对一make_edges(node, node_set)单个源节点向节点集合中的每个节点各连一条边一对多。两种方式的效果如下图所示图片来源仓库内官方文档配图 make_edges_usage.png启用条件预览特性宏该功能属于 TBB 的预览preview特性。使用前必须在包含头文件之前定义宏#define TBB_PREVIEW_FLOW_GRAPH_FEATURES 1官方文档make_edges_function.rst 开头的 note以及配套示例 make_edges_function_example.cpp 都强调了这个前提。从源码看整个node_set/make_edges实现都包裹在#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET条件编译块中见 flow_graph.h 中 150、671、917 等多处以及 _flow_graph_node_set_impl.h 的#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET未定义该宏时相关 API 不会被编译。API 语法与头文件头文件make_edges与make_node_set都通过公开头文件暴露#include oneapi/tbb/flow_graph.h在 flow_graph.h 中可以看到它们被显式导入到oneapi::tbb::flow命名空间using detail::d2::make_node_set; using detail::d2::make_edges;函数签名官方文档给出的两个重载签名如下其中node_set是make_node_set返回类型的说明性名称实际类型为模板node_setNode, Nodes...template typename NodeType, typename Node, typename... Nodes void make_edges(node_setNode, Nodes... set, NodeType node); template typename NodeType, typename Node, typename... Nodes void make_edges(NodeType node, node_setNode, Nodes... set);对应的实际声明位于 _flow_graph_node_set_impl.h参数为const node_setOrderFlagType, Args...。源码中还有一条 TODO 注释consider adding an overload for making edges between node sets说明目前make_edges只支持单节点 × 节点集合的组合尚不支持在两个集合之间直接建边。配套工具make_node_set / follows / precedesmake_edges依赖make_node_set构造的节点集合。文档 make_node_set_function.rst 说明make_node_set函数模板创建一组节点可将其作为参数传给make_edges、follows和precedes函数。其语法为template typename Node, typename... Nodes /*unspecified*/ make_node_set( Node node, Nodes... nodes );从实现看_flow_graph_node_set_impl.hmake_node_set返回类型为node_setorder::undefined, Node, Nodes...其中order::undefined表示尚未确定边的方向。节点集合内部用std::tupleNodes...以引用方式持有各节点_flow_graph_node_set_impl.h因此不会发生拷贝。与order::undefined对应源码还定义了另外两种方向标记_flow_graph_node_set_impl.hnamespace order { struct undefined {}; struct following {}; // 节点集合作为前驱predecessors struct preceding {}; // 节点集合作为后继successors }follows与precedes用于在构造节点尤其是join_node时声明前驱/后继集合follows(predecessors...)返回node_setorder::following, ...要求集合内所有节点都是sender具有output_typeprecedes(successors...)返回node_setorder::preceding, ...要求集合内所有节点都是receiver具有input_type。两种函数在实现中都通过static_assert对节点类型做了编译期检查_flow_graph_node_set_impl.h一旦传入不满足条件的节点编译即报错从而把类型错误提前到编译期。此外node_set之间还支持从order::undefined集合拷贝构造为带方向标记的集合第 67-68 行的转换构造函数便于先收集节点、后声明方向。完整示例扇出 扇入的流图官方示例 make_edges_function_example.cpp 构建了这样一个流图一个broadcast_nodeint作为输入源input三个function_nodeint,intdoubler×2、squarer平方、cuber立方——三者并行消费输入一个buffer_nodeint作为汇聚缓冲buffer。建边部分只有两行auto handlers make_node_set(doubler, squarer, cuber); make_edges(input, handlers); // 一对多input → doubler/squarer/cuber make_edges(handlers, buffer); // 多对一doubler/squarer/cuber → buffer完整可运行代码需 C17 及以上示例源码中通过#if __cplusplus 201703L做了版本守卫#define TBB_PREVIEW_FLOW_GRAPH_FEATURES 1 #include oneapi/tbb/flow_graph.h int main() { using namespace oneapi::tbb::flow; graph g; broadcast_nodeint input(g); function_node doubler(g, unlimited, [](const int i) { return 2 * i; }); function_node squarer(g, unlimited, [](const int i) { return i * i; }); function_node cuber(g, unlimited, [](const int i) { return i * i * i; }); buffer_nodeint buffer(g); auto handlers make_node_set(doubler, squarer, cuber); make_edges(input, handlers); make_edges(handlers, buffer); for (int i 1; i 10; i) { input.try_put(i); } g.wait_for_all(); }该图的结构如下图片来源仓库内官方文档配图 make_edges_example.png作为对比若使用底层make_edge上述建边需要手写 6 次调用而make_edges把扇出与扇入各压缩成一行且集合的构成一目了然。node_set内部按参数顺序保存节点引用因此节点在集合中的排列顺序是确定的。源码级原理模板递归建边make_edges的底层实现位于 _flow_graph_node_set_impl.h核心是编译期递归的make_edges_helper模板第 211-238 行templatesize_t I class make_edges_helper { public: templatetypename PredecessorsTuple, typename NodeType static void connect_predecessors(PredecessorsTuple predecessors, NodeType node) { make_edge(std::getI(predecessors), successor_selectorI::get(node)); make_edges_helperI - 1::connect_predecessors(predecessors, node); } templatetypename SuccessorsTuple, typename NodeType static void connect_successors(NodeType node, SuccessorsTuple successors) { make_edge(predecessor_selectorI::get(node), std::getI(successors)); make_edges_helperI - 1::connect_successors(node, successors); } }; template struct make_edges_helper0 { /* 递归终止只处理索引 0 的元素 */ };make_edges的两个重载分别调用它们make_edges(const node_set s, NodeType node)SetSize tuple_size调用make_edges_helperSetSize-1::connect_predecessors(s.nodes, node)即把集合中每个节点当作前驱、与目标节点的输入端口相连_flow_graph_node_set_impl.hmake_edges(NodeType node, const node_set s)调用connect_successors(node, s.nodes)即把集合中每个节点当作后继、与源节点的输出端口相连第 247-251 行。最终每个连接都归结为一次标准的make_edge调用因此make_edges只是make_edge的批量语法糖语义完全一致。端口选择多端口节点与 async_node 特化节点并不总是单端口。successor_selector与predecessor_selector第 154-209 行负责处理多端口情况对具有input_ports_type的节点successor_selectorI::get(node)会返回input_portI(node)即取第 I 个输入端口对具有output_ports_type的节点predecessor_selectorI::get(node)会返回output_portI(node)对单端口节点则直接返回节点自身引用。选择逻辑通过std::true_type/std::false_type标签分派和decltype尾置返回类型在编译期完成MSVC 因对尾置 decltype 支持问题源码中还有专门的__TBB_MSVC_DISABLE_TRAILING_DECLTYPE兼容分支见第 27-30 行。此外predecessor_selector对async_node有专门特化is_async_node第 100-104、196-197 行确保async_node作为前驱时直接连接其本身而非内部端口。图引用获取node_set::graph_reference()通过get_graph_helper第 38-58 行获取节点所属的graph若节点继承自graph_node直接读取其my_graph成员否则调用节点的graph_reference()方法。这使得node_set可以统一地从任意成员节点回溯到所属图。测试验证与 follows/precedes 的组合使用仓库测试代码印证了make_node_set与follows/precedes的组合用法。在 test_join_node_multiple_predecessors.h 中TBB_PREVIEW_FLOW_GRAPH_FEATURES开启时提供了两种等价的join_node连接方式// 方式一make_node_set follows将三个 buffer_node 作为 join_node 的前驱 auto bn_set make_node_set(bn1, bn2, bn3); std::unique_ptrjoin_node_t jn( new join_node_t(follows(bn_set)) ); // 方式二make_node_set precedes将 queue_node 声明为 join_node 的后继 auto qn_set make_node_set(qn); auto qn_copy_set qn_set; std::unique_ptrjoin_node_t jn( new join_node_t(precedes(qn_copy_set)) );该测试与上文make_edges的两种调用方向一一对应验证了make_node_set构建的order::undefined集合既能被follows转成order::following集合做前驱对应make_edges(set, node)也能被precedes转成order::preceding集合做后继对应make_edges(node, set)。使用注意事项必须开启预览宏TBB_PREVIEW_FLOW_GRAPH_FEATURES 1要在包含flow_graph.h之前定义否则make_node_set/make_edges不存在源码中整个功能块由__TBB_PREVIEW_FLOW_GRAPH_NODE_SET条件编译控制。C17 及以上官方示例用#if __cplusplus 201703L守卫低于 C17 时示例会被跳过提示该功能依赖较新的标准特性。只支持一 × 多组合从源码 TODO 注释看make_edges目前不支持在两个node_set之间建边follows/precedes的static_assert也会在节点类型不满足sender/receiver要求时直接编译失败。节点以引用保存node_set内部是std::tupleNodes...不会拷贝节点但要保证传入节点的生命周期覆盖建边及图执行期间。接口仍在预览演进中make_edges/make_node_set是 preview 特性其 API 形态可能随 TBB 版本演进调整本文所述以本仓库 vendored 的 third-party/tbb 版本为准。延伸阅读配套函数文档make_node_set_function.rstmake_node_set、follows、precedes的说明与 See Also 交叉引用官方示例源码make_edges_function_example.cpp核心实现_flow_graph_node_set_impl.h公开头文件与命名空间导入flow_graph.h相关测试test_join_node_multiple_predecessors.h【免费下载链接】moldmold: A Modern Linker 项目地址: https://gitcode.com/GitHub_Trending/mo/mold创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/10/28 13:12:35

2026年实验室防潮升级:红外防潮箱如何实现温湿度双控与自动再生

前段时间帮一个做材料研发的朋友调试新实验室,聊到防潮设备时他抱怨说,传统防潮箱里的变色硅胶一到梅雨季就“撑不住”,三天两头要取出来烘烤,仪器间的湿度还总是忽高忽低。后来我们换了一台红外防潮箱,几个月用下来&a…

2026/11/7 14:39:47

湖南电工证多少钱报考条件与考试时间通过率揭秘

湖南电工证多少钱报考条件与考试时间通过率揭秘 之前考的证在外省能不能转过来?这个问题我听太多人问了,说实话,很多小伙伴因为不了解政策,结果白白浪费了时间和钱。今天就来聊聊【湖南电工证多少钱】这个大家最关心的问题,顺便揭秘一下考试通过率,让你…

2026/11/7 14:39:47

日本电工证报名网站怎么用?郑州报考避坑指南帮你搞定

日本电工证报名网站怎么用?郑州报考避坑指南帮你搞定 证书过期了不知道怎么复审延期?你不是一个人,信阳浉河区很多电工朋友都在为这个问题头疼。尤其是那些在日本电工证报名网站上报名,或者打算报名的人,面对流程繁琐、信息不透明、复审要求不明确,很容…

2026/11/7 14:39:47

漳州诏安县电工证有效期多久?真实经历告诉你别被中介坑

漳州诏安县电工证有效期多久?真实经历告诉你别被中介坑 不知道去哪报名怕被中介坑,是很多想考漳州诏安县电工证的朋友心头的疙瘩。特别是对于刚入行或者转行的人来说,连报名流程都不清楚,更别提怎么选靠谱的培训机构了。我认识不少同行,因为找错了机构,…

2026/11/7 14:39:47

_高压电工证难不难模拟考试题库

高压电工证难不难?全国通用吗?南阳电工亲测经验 之前考的证在外省能不能转过来?这是很多特种作业人员最头疼的问题,特别是像你这样在南阳做市政公用工程的电工,经常在不同项目间奔波,证书能不能全国通用直接影响你能不能顺利上岗。别急,今天我就从…

2026/11/7 14:39:47

底庄电工证有效期多久 一张全国通用的证书怎么考

底庄电工证有效期多久 一张全国通用的证书怎么考 怕考不过白交培训费?底庄电工证是特种作业操作证的一种,涉及低压和高压电工操作,是进入建筑、电力、市政等行业的“通行证”。特别是在许昌市,从事市政公用工程的电工,必须持证上岗,否则不仅会被限制作…

2026/11/7 14:34:47

林州做电工证真实经历:外省证怎么转?别踩这些坑

林州做电工证真实经历:外省证怎么转?别踩这些坑 之前考的证在外省能不能转过来?这是很多在林州打工的电工、或者打算在林州发展、但证书在别处的朋友最关心的问题。我认识一个郑州的劳务班组负责人老李,他就是在外地考的电工证,后来想在林州接项目,结果…

2026/11/5 15:39:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/6 10:49:01

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/7 0:03:08

郑州报考避坑指南:电工证和钳工证怎么选?实操考试心里没底怕挂科

郑州报考避坑指南:电工证和钳工证怎么选?实操考试心里没底怕挂科 实操考试心里没底怕挂科?你不是一个人。特别是在郑州这样的城市,很多施工企业负责人和一线作业人员在报考电工证和钳工证时都面临着同样的困惑。到底该考哪个证?哪个更适合自己?哪个证书…

2026/11/7 0:03:08

广西电工证办理流程全解析:外省证怎么转?在哪考最靠谱?

广西电工证办理流程全解析:外省证怎么转?在哪考最靠谱? 之前考的证在外省能不能转过来?这个问题我遇到太多了,今天就拿广西电工证办理流程来具体说说,别再走弯路了。广西电工证的报考、复审、继续教育这些环节,如果你不了解,真的会吃大亏,尤其对于从…

2026/11/7 0:03:08

电气电工证都有哪些保姆级教程

电气电工证都有哪些保姆级教程 你是不是正愁不知道去哪报名,怕被中介坑?别急,这篇保姆级教程专为河南初次报考人员准备,帮你搞清楚 电气电工证都有哪些 ,以及如何避开那些坑。 电气电工证都有哪些?别被五花八门的证书搞懵了…

2026/11/5 15:39:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/6 10:49:01

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑