Halide 循环嵌套解读:用 Func::print_loop_nest() 读懂调度产物
编译器图像处理编程语言高性能计算【免费下载链接】Halidea language for fast, portable>项目地址https://gitcode.com/gh_mirrors/ha/Halide点击查看免费下载Func::print_loop_nest()是 Halide 开发者在写调度schedule时最常用的验证工具它以伪代码形式打印一条已调度管线最终生成的循环结构用于确认调度是否实现了你的意图。本文以 Halide 官方调度指南第 12 章.claude/skills/scheduling/references/guide/12-reading-a-loop-nest.md为核心结合仓库源码src/PrintLoopNest.cpp深入讲解输出记号的五种行形状、缩进语义、单个 Func 的循环生成规则以及更新阶段update stage以兄弟嵌套打印的原理读完你就能熟练读懂并核对任意 Halide 调度的循环结构。什么是 print_loop_nest()在 Halide 中程序被拆分为**算法algorithm与调度schedule**两部分算法定义每个值是什么调度决定每个值何时、何地计算与存储。调度不改变计算结果只改变循环的顺序、嵌套与类型。问题在于一个包含split、reorder、compute_at、vectorize等指令的调度最终会组合出什么样的循环结构Func::print_loop_nest()正是回答这个问题的最直接方式。它把调度后的管线输出为一段可读的伪代码是调度指南.claude/skills/scheduling/references/guide/README.md第三部分调度指令所有章节的共同基准每一章展示的循环嵌套就是print_loop_nest()打印出来的样子。从源码看这个功能是一条完整但简化了的编译链路。在src/PrintLoopNest.cpp的print_loop_nest(const vectorFunction output_funcs)中Halide 先对整张 Func 图做深拷贝、把输出 Func 固定为compute_root().store_root()、锁定所有 LoopLevel然后依次执行调度函数schedule_functions、边界推断bounds_inference、滑窗sliding_window、分配边界推断allocation_bounds_inference等 lowering 前段管线最后用一个PrintLoopNest访问器把 IR 语句转成伪代码字符串返回。换言之它打印的是真正会执行的循环结构与 lowering 后段之前的形态一致而不是对调度的猜测。五种行形状输出记号print_loop_nest()的输出由五种行形状构成通过两个空格的缩进分层produce f: # 一个区域计算并写入Func f consume f: # 一个区域读取 f 已存储的值 for var: # 对某一维的循环 f(...) ... # 叶子计算 f 的一个点 store f: # f 的存储作用域仅当与计算作用域不同时打印对应的源码实现见src/PrintLoopNest.cppPrintLoopNest继承IRVisitor重写visit(const ProducerConsumer*)打印produce/consume重写visit(const For*)打印循环重写visit(const Provide*)打印叶子赋值行重写visit(const Realize*)在存储与计算层级不同时额外打印store。缩进即包含关系这是整套记号的核心语义produce f包含计算 f 的循环结束于与之匹配的consume或退格缩进所有读取 f 的内容都位于consume f之下for包含其循环体叶子f(...) ...位于最内层是真正发生计算的位置。consume与store只有在调度把多个 Func 组合起来、或将存储与计算拆分开时才会出现因此它们会随compute_at、store_at等指令见 Placement: compute_root 与 compute_at 和 Storage Levels在后续章节登场。一个未经调度的 Func 只需要produce、for和叶子三类即可完整表达。输出里被省略的两类信息print_loop_nest还会打印两类不影响结构的信息本指南的示例一律将其省略因为它们既不影响循环结构也不可手工复现精确的循环变量名Halide 的变量名携带内部split/rfactor谱系信息外加一个全局计数器如x.split.1.outer$1。源码中simplify_var_name/simplify_func_name专门负责裁掉$n唯一性后缀和函数名、阶段号只保留用户可读的部分——这从侧面印证了名称本身对理解结构没有意义。常量循环边界如for x in [0, 7]。这类边界来自边界推断Bounds Inference属于运行时才确定的信息。PrintLoopNest的visit(const For*)实现里确实有打印min/max的逻辑src/PrintLoopNest.cpp但只有在两者都是常量时才输出in [min, max]否则留空。这两类信息都不改变结构但它们带来一个实用的推论交换两个纯串行serial循环的reorder在输出中不留任何痕迹。因为本指南忽略变量名与常量边界两个普通for交换后结构完全相同。只有当循环携带了类型vectorize/parallel/unroll之后reorder才会以可见的方式体现详见 Reshaping Loops 与 Loop Types。循环省略结构不完全由调度决定调度结构并非总是完全由调度本身决定最主要的例外是循环省略loop elision当一个循环的迭代范围塌缩为单点时它会被从输出中删除。是否发生省略取决于边界推断作用于真实索引数学的结果而不是调度指令本身详见 Placement: compute_root 与 compute_at。因此调度隐含的循环是图中显示的这些但其中哪些会塌缩为单点是一个边界推断层面的问题在涉及之处会单独标注。例如一个范围恰好为 1 的纯串行循环不会打印for行——而 GPU 循环除外1 次迭代的 GPU 循环会保留见 Loop Types。单个 Func 的循环维度列表与行主序在不做任何调度的情况下一个 Func 的循环直接来自它的定义。这正是输出中produce块内部的内容也是任何独立构建的 Func 的形态。每个阶段stage都携带一个有序的维度列表最内层在前。对于纯定义pure definition维度列表初始化为参数Var的顺序因此第一个参数就是最内层维度。阶段打印时为每个维度输出一个for循环最外层在前即列表的逆序叶子在中间。所以f(x, y, c) ...的维度列表是[x, y, c]打印结果为produce f: for c: for y: for x: f(...) ...这就是行主序row-major第一个维度变化最快c是最外层最慢x是最内层最快。reorder改变顺序split/fuse/tile改变循环数量见 Reshaping Loops。split把一个维度变成内层运行0..factor-1加外层两个循环fuse相反tile等价于两次split加一次reorder都会直接体现在打印的for行数与嵌套上。更新阶段打印为兄弟嵌套一个 Func 的所有阶段都打印在同一个produce f块内表现为背靠背的兄弟循环嵌套而不是独立的 produce/consume 块——阶段之间没有consume。读者看到的是 Func 更新完成后的最终值因此它的consume如果有包裹的是整块内容。以编程模型一章The Programming Model中的直方图为例Var x(x); ImageParam in(type_ofint(), 1, in); Func hist(hist); hist(x) 0; RDom r(0, 256, r); hist(clamp(in(r), 0, 255)) 1; hist.print_loop_nest();打印结果produce hist: for x: # stage 0: initialize hist(x) 0 hist(...) ... for r: # stage 1: the scatter update hist(...) ...两个阶段初始化与累加散射同处一个produce hist块内第二个阶段的for r直接缩进在第一个阶段的叶子之后说明它们顺序执行、共享同一个存储缓冲。这种散射更新正是 Halide 处理直方图、邻域累加等归约计算的典型形态。每个阶段的维度列表如何构成每个阶段都有自己的维度列表由**该阶段自己的左侧LHS**决定左侧的自由Var加上它使用的那一个RDom的RVar。RVar排在最内层按RDom声明顺序排列r.x最内层自由纯Var在它们外层。若某个纯维度的 LHS 槽位被RVar或一般表达式占据则该阶段不为其打印循环。几个关键示例f(x, y) in(x r.x, y r.y)使用 2-DRDom的更新阶段给出for y: for x: for r.y: for r.x:——自由变量y、x在外归约变量r.y、r.x在内纯阶段f(x, y) 0只给出for y: for x:像直方图这样没有自由 LHS 变量的散射其阶段只有归约循环for r:。理解这一点对判断更新阶段的计算代价与内存访问模式至关重要归约维度总在最内层意味着每个输出点都要遍历整个归约域。源码视角调用链与实现细节print_loop_nest()的完整调用链在仓库中清晰可循公共 APIFunc::print_loop_nest()定义于src/Func.cpp声明于src/Func.h直接委托给pipeline().print_loop_nest()Pipeline 层Pipeline::print_loop_nest()在src/Pipeline.cpp中调用内部实现Halide::Internal::print_loop_nest(contents-outputs)并输出到调试流内部实现std::string print_loop_nest(const vectorFunction output_funcs)位于src/PrintLoopNest.cpp其头文件src/PrintLoopNest.h注释明确指出其职责是emit simple pseudocode that shows the structure of the loop nest specified by this pipelines schedulePython 绑定pybind11绑定同样暴露了该方法见python_bindings/halide/src/halide_/PyFunc.cpp因此 C 指南中的示例在 Python 中等价可用f.print_loop_nest()作为halide.Func的方法。实现细节上值得注意两点其一PrintLoopNest打印循环时会带上for_type即serial、parallel、vectorized、unrolled、gpu_block等类型标记以及 GPU 的device_api后缀src/PrintLoopNest.cpp这正是调度指南所说的类型标记属于结构的一部分其二整个打印过程在 lowering 前段完成、且将目标平台的所有设备特性全部启用src/PrintLoopNest.cpp所以它展示的是调度决定的结构本身不掺杂具体代码生成细节。实战何时用、怎么用写完调度立即核对在print_loop_nest()前后各调一次对比调度前后循环数量、嵌套顺序与类型标记的变化这是确认compute_at/store_at/reorder是否落在预期循环层级上的最可靠手段。调试并行/向量化问题检查parallel、vectorized、unrolled标记是否出现在预期维度上注意vectorize(v, n)会先生成split并给内层打上vectorized标记而parallel(v, n)给外层打标记见 Loop Types。评估 GPU 调度print_loop_nest原样展示 GPU 循环带Default_GPU等设备后缀可用于检查 block/thread 嵌套是否符合 GPU 合法性要求。与相关工具配合更精细的验证可结合HL_DEBUG_CODEGEN1查看 lowering 各阶段 IR以及.stmt文件见 Reading the .stmt File确认矢量化形态。小结print_loop_nest()用五种行形状与缩进把一条管线的循环结构变成可读、可讨论、可验证的伪代码。掌握它的记号就掌握了 Halide 调度的透视镜你能看出维度顺序行主序、阶段组织兄弟嵌套、归约循环位置最内层也能识别哪些信息被省略变量名、常量边界、哪些循环会被消掉单点省略。它是调度指南后续所有指令章节Reshaping Loops、Loop Types、Placement 等共同依赖的解读基础——先学会读循环嵌套再谈如何塑造它。赞分享编译器图像处理编程语言高性能计算【免费下载链接】Halidea language for fast, portable>项目地址https://gitcode.com/gh_mirrors/ha/Halide点击查看免费下载相关推荐使用 MDM 命令恢复被删除的 fleetd agentFleet 系统管理员实战指南使用 MDM 命令恢复被删除的 fleetd agentFleet 系统管理员实战指南 本指南以 Fleet 开源仓库中的系统管理员系列文章《Sysadmin编译器图像处理编程语言高性能计算BrewUI Configuration界面完整指南5分钟快速读懂Homebrew环境配置BrewUI Configuration界面完整指南5分钟快速读懂Homebrew环境配置 BrewUI 是 Homebrew 官方的 macOS 图形界面编译器图像处理编程语言高性能计算把微信公众号变成RSS一份可私有化的完整自托管笔记把微信公众号变成RSS一份可私有化的完整自托管笔记 早上翻再看列表我发现有 23 个微信公众号超过十天没打开过。我不想在微信里天天打卡希望这些号的编译器图像处理编程语言高性能计算上一篇ComfyUI性能优化终极指南让AI绘图速度提升3倍的10个技巧下一篇Koodo Reader智能推荐基于阅读历史的书籍推荐创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Rust 通用和类型 Either 完全指南:Left/Right 变体、迭代器集成与序列化 —— 基于 makepad 仓库 vendored either crate 的源码解析

Rust 通用和类型 Either 完全指南:Left/Right 变体、迭代器集成与序列化 —— 基于 makepad 仓库 vendored either crate 的源码解析

前端UI组件3D渲染跨平台游戏开发 【免费下载链接】makepad Makepad is a creative software development platform for Rust that compiles to wasm/webGL, osx/metal, windows/dx11 linux/opengl 项目地址: https://gitcode.com/gh_mirrors/ma/makepad 点击查看 免…

2026/10/10 15:17:21 阅读更多 →
OWASP MASTG 实战:在非 Root 安卓设备上进行动态分析(Frida Gadget 注入全流程指南)

OWASP MASTG 实战:在非 Root 安卓设备上进行动态分析(Frida Gadget 注入全流程指南)

文档教程网络安全 【免费下载链接】mastg The OWASP Mobile Application Security Testing Guide (MASTG) is a comprehensive manual for mobile app security testing and reverse engineering. It describes technical processes for verifying the OWASP Mobile Security W…

2026/10/10 15:12:47 阅读更多 →
Android Binder 通信机制深度解析:从设计动机到驱动原理与 AMS 实战

Android Binder 通信机制深度解析:从设计动机到驱动原理与 AMS 实战

教程技术博客文档 【免费下载链接】YCBlogs 技术博客笔记大汇总,包括Java基础,线程,并发,数据结构;Android技术博客等等;常用设计模式;常见的算法;网络协议知识点;部分fl…

2026/10/8 1:26:16 阅读更多 →

最新新闻

Java面试翻车现场:HashMap、线程池、JVM深度拆解

Java面试翻车现场:HashMap、线程池、JVM深度拆解

“严肃面试官 vs 搞笑水货程序员谢飞机(本名王大瓜)——互联网大厂 Java 面试实录与技术拆解”,光看这个标题你可能觉得是个段子,但我在现场的感觉是:这简直就是一场喜剧外壳下的技术解剖课。谢飞机,简历上…

2026/10/11 3:58:54 阅读更多 →
RT-Thread—STM32—环境搭建

RT-Thread—STM32—环境搭建

RT-Thread——STM32——环境搭建 概述 本教程主要根据官方推荐的教程进行环境搭建,但是在打包方面按照自己的习惯进行了打包。 RT-Thread官网有特别详细的教程,这儿就不详细说明RT-Thread官网 软件准备 MDK528a (Keil5)CubeMx_v5-2-0STM32CubeMx的支持…

2026/10/11 3:58:54 阅读更多 →
智能工厂建设方案全解析:从ISA-95架构到MES/SCADA系统选型

智能工厂建设方案全解析:从ISA-95架构到MES/SCADA系统选型

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

2026/10/11 3:58:54 阅读更多 →
JavaScript核心考点索引:从原型链到事件循环的面试体系

JavaScript核心考点索引:从原型链到事件循环的面试体系

做前端面试辅导这几年,我收到最多的问题不是“这道题答案是什么”,而是“面对这么多考点,到底哪些才值得深学”。JavaScript知识体系太庞杂了,从语言基础到浏览器原理,从手写代码到性能优化,随便拉一个列表…

2026/10/11 3:58:53 阅读更多 →
第1章,[Win32 章节]:编程环境与 MSDN

第1章,[Win32 章节]:编程环境与 MSDN

专栏导航 上一篇:第1章,[Win32 章节]:编程语言与框架选择 回到目录 下一篇:第1章 :第一个 Win32 程序,头文件 本专栏课件 关于本专栏课件的获取方法,请参考下述课节。 参考课节&#xff1a…

2026/10/11 3:58:53 阅读更多 →
开源吐槽大会:开发者从项目吐槽中学到的避坑与成长之道

开源吐槽大会:开发者从项目吐槽中学到的避坑与成长之道

1. 这个标题是怎么“火”起来的:开源吐槽大会的由来与定位如果你混迹开发者社区有一阵子,大概率见过这类帖子:“某某开源项目到底能不能用”“维护者又跑路了”“README吹得天花乱坠,一跑就崩”。这些帖子往往评论区最热闹&#x…

2026/10/11 3:57:53 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/10 5:23:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/10 10:38:42 阅读更多 →