MAX 文档代码示例仓库解析:docs/code/ 的 Bazel 测试体系与 DOC 同步机制
【免费下载链接】mojoThe Modular Platform (includes MAX & Mojo)项目地址: https://gitcode.com/GitHub_Trending/mo/mojo
本文聚焦 Modular Platform 仓库(含 MAX 与 Mojo)中 docs/code/ 目录的设计与工程实践:它为 MAX 开发者文档中的每一段代码示例提供可独立运行、由 CI 持续测试的"活代码",并通过# DOC:头部与文档页面建立双向同步约束。读完本文,你将掌握如何用 Bazel(bt/br)运行单个或全量示例、理解示例在不同平台与 GPU 环境下的兼容性限制、弄清docs/code/与max/examples/的分工,以及如何安全地为文档示例贡献代码。
一、docs/code/ 是什么:为文档而生、可独立测试的代码片段库
MAX 开发者文档(如 docs/max/ 下的各.mdx页面)中嵌入了大量 Python / Mojo 代码块。如果这些代码块只以"文本"形式存在于文档中,它们会随着 API 演进逐渐失效——也就是文档领域常说的 snippet "腐烂"(rot)。
docs/code/README.md 开篇即点明该目录的设计初衷:
This directory holds the code examples embedded in the MAX developer documentation, kept here as standalone, tested files so those snippets don't rot.
也就是说,docs/code/是文档内嵌代码块的源头文件库:每个文件对应某个 MAX 文档页面中的一个代码块,且每个文件都配套一个 Bazel 测试目标,由 CI 持续执行,确保示例永远可运行。仓库中该目录的实际结构如下(节选自真实目录树):
docs/code/ ├── README.md ├── develop/ # Python 为主的示例(对应 max/develop/* 文档) │ ├── basic-ops/ # 算术、张量运算、激活函数等(13 个 .py + BUILD.bazel) │ ├── broadcasting/ # 自动/显式广播、mask 广播 │ ├── dtypes/ # 数据类型、dtype 转换、DLPack、PyTorch 互操作 │ ├── index/ # eager / graph 模式对比与工作流 │ ├── indexing/ # gather / scatter / where │ ├── layer-comparison/ # 逐层对比 │ ├── layers/ # 模块定义、RMSNorm 子类化、组合运行 │ ├── logit-comparison/ # 需 GPU 与大模型权重的手动测试 │ └── tensors/ # 张量创建与属性(shape/rank/dtype/device) ├── gpu/ # Mojo 示例(对应 max/gpu/* 文档) │ ├── fundamentals/ # GPU 检测、设备信息、线程打印、标量加法 │ └── intro-tutorial/ # GPU 入门 └── tile-tensor/ # Mojo + Pixi 示例(对应 max/tile-tensor/* 文档) ├── layouts/ # 布局示例 basic_layouts / tiled_layouts └── tensors/ # TileTensor 使用示例(CPU 与 GPU)每个子目录都遵循同一套约定:示例源码(.py/.mojo)旁边放一个 BUILD.bazel,为每个示例定义"可执行目标 + 同名_test测试目标"。
二、用 Bazel 运行与测试示例:bt 与 br
示例的测试与运行统一走 Bazel。仓库根目录的 bazelw 以及 Bazel 封装脚本bt/br(测试/运行的缩写)提供了便捷入口,docs/code/README.md 给出了三类典型用法。
2.1 运行单个示例的测试
bt //oss/modular/docs/code/develop/basic-ops:arithmetic_testbt会构建并运行basic-ops目录下arithmetic示例对应的测试。_test后缀的目标是一个 modular_run_binary_test,它把示例当作二进制程序执行并检查其能正常退出。
2.2 按主题目录或全量运行
bt //oss/modular/docs/code/develop/basic-ops/... bt //oss/modular/docs/code/...Bazel 的...通配符会匹配该包及其所有子包下的全部目标:第一条命令验证"基础运算"整个主题,第二条命令跑遍docs/code/下所有示例测试,相当于文档代码的完整回归门禁。
2.3 直接运行示例(不走测试包装)
br //oss/modular/docs/code/develop/basic-ops:arithmeticbr直接构建并运行二进制目标,适合本地手动观察示例输出,例如验证张量加法打印结果是否符合文档描述。
路径说明:
//oss/modular/docs/code/...是 README 中使用的完整标签形态,对应 MAX 文档站点发布时仓库的挂载位置;在本仓库独立检出场景下,内部 BUILD 文件(如 docs/code/develop/basic-ops/BUILD.bazel)本身以//docs/code/...定义包、并以//max/python/max:tensor等相对根路径引用内部依赖,因此两种前缀在语义上指向同一组目标。
三、示例背后的 Bazel 构建结构:源码印证
文档只给出了命令用法,深入 BUILD 文件可以看清这套体系的具体实现方式。
3.1 Python 示例:modular_py_binary + modular_run_binary_test
以 docs/code/develop/basic-ops/BUILD.bazel 为例,每个.py文件被声明为一个modular_py_binary目标,并配一个同名_test目标:
# arithmetic.py modular_py_binary( name = "arithmetic", srcs = ["arithmetic.py"], imports = ["."], deps = [ "//max/python/max:tensor", ], ) modular_run_binary_test( name = "arithmetic_test", size = "large", binary = "arithmetic", # Incompatible with macOS: these doc-example tests time out on remote macOS CI workers; Linux CI provides equivalent coverage. target_compatible_with = select({ "@platforms//os:macos": ["@platforms//:incompatible"], "//conditions:default": [], }), )要点:
deps指向 MAX 的 Python 前端库,例如//max/python/max:tensor(张量 API)、//max/python/max/nn与//max/python/max/graph(layers 示例)、//max/python/max/driver(编译运行管线),见 docs/code/develop/layers/BUILD.bazel。modular_run_binary_test通过binary字段挂接可执行目标,size = "large"声明该测试资源占用较大。target_compatible_with用select把 macOS 标记为不兼容,这是平台约束的落地方式。
示例本体也很直白,arithmetic.py 展示了 MAX 张量 API 的四则运算:
# DOC: max/develop/basic-ops.mdx from max.experimental.tensor import Tensor a = Tensor([1.0, 2.0, 3.0]) b = Tensor([4.0, 5.0, 6.0]) addition = a + b subtraction = a - b multiplication = a * b division = a / b print(addition) print(multiplication)3.2 Mojo 示例:mojo_binary 与 glob 批量生成
GPU 与 TileTensor 示例是 Mojo 程序,使用mojo_binary目标。以 docs/code/gpu/fundamentals/BUILD.bazel 为例,它用glob扫描全部.mojo文件并批量生成二进制与测试目标:
MOJO_SRCS = glob(["*.mojo"]) [ mojo_binary( name = src.split(".")[0], srcs = [src], target_compatible_with = ["//:has_gpu"] + _EXTRA_CONSTRAINTS.get( src.split(".")[0], [], ), deps = [ "//max:max_mojo", "@mojo//:std", ], ) for src in MOJO_SRCS ] [ modular_run_binary_test( name = src.split(".")[0] + "_test", size = "small", binary = src.split(".")[0], tags = ["gpu"], ) for src in MOJO_SRCS ]值得注意的两个细节:
- 所有 GPU 示例都被
target_compatible_with = ["//:has_gpu"]约束,只有机器满足 GPU 条件才参与构建/测试; - 测试目标带有
tags = ["gpu"],可在 CI 中通过标签过滤单独挑选 GPU 测试集。
对应的 Mojo 示例代码(detect_gpu.mojo)展示了运行时 GPU 探测的惯用写法:
from std.sys import has_accelerator def main(): comptime if has_accelerator(): print("GPU detected") # Enable GPU processing else: print("No GPU detected") # Print error or fall back to CPU-only execution3.3 TileTensor 示例:Pixi 任务封装
docs/code/tile-tensor/下的示例除了 Bazel 目标,还提供 pixi.toml 任务,方便未接入 Bazel 的场景直接运行:
[tasks] tile_tensor = "mojo run tile_tensor_examples.mojo" tile_tensor_gpu = "mojo run tile_tensor_gpu_examples.mojo" tile_tensor_all = "mojo run tile_tensor_examples.mojo && mojo run tile_tensor_gpu_examples.mojo"安装 Pixi 后即可执行(见 docs/code/tile-tensor/tensors/README.md):
pixi run tile_tensor pixi run tile_tensor_gpu pixi run tile_tensor_all # 同时运行两组示例布局示例同理(见 docs/code/tile-tensor/layouts/README.md):
pixi run mojo basic_layouts pixi run mojo tiled_layouts四、平台与资源限制:什么环境能跑哪些示例
docs/code/README.md 明确提醒:"Not every example runs on every platform." 结合 BUILD 文件中的约束与注释,可归纳为以下四类限制。
4.1 macOS 不兼容:远程 macOS CI 超时
绝大多数示例测试被标记为与 macOS 不兼容(@platforms//os:macos→ incompatible),只在 Linux 上运行。BUILD 注释给出的原因是:
Incompatible with macOS: these doc-example tests time out on remote macOS CI workers; Linux CI provides equivalent coverage.
即远程 macOS CI worker 上这些示例测试会超时,而 Linux CI 已提供等价覆盖,因此在 Apple Silicon 上这些测试被直接跳过,docs/code/develop/basic-ops/BUILD.bazel 中所有modular_run_binary_test目标都带此约束。
4.2 Apple GPU 与 bf16:Metal 编译器限制
部分basic-ops测试在 Apple GPU 上额外被跳过,注释统一标注为:
FIXME: MOCO-3605 — Metal AIR compiler doesn't support bf16 ...
具体涉及:
tensor_math_ops:Metal 不支持 bf16 sqrt;tensor_reductions:不支持 bf16 convert;functional_activations与compose_linear_layer:不支持 bf16 fmax。
这些示例使用了 bf16 数学内建函数,而 Apple 的 Metal AIR 编译器尚未支持,因此在 Apple GPU 上无法编译运行。
4.3 GPU 门槛与 Apple Silicon 构建机问题
GPU 主题的 Mojo 示例全部要求//:has_gpu平台约束。若本机没有兼容 GPU,docs/code/gpu/fundamentals/README.md 说明:程序可以编译,但运行时只会看到:
No GPU detected另外,print_threads示例还额外加了//:apple_gpu不兼容约束,注释记录了原因:
TODO(MSTDL-2569): MTLCompilerService crashes / "Compute function exceeds available stack space" compiling GPU kernels that call
print()in multi-block grids on Apple Silicon BuildBuddy workers.
即 Apple Silicon BuildBuddy worker 上,编译多 block grid 中调用print()的 GPU kernel 时会发生 MTLCompilerService 崩溃或栈空间超限。
4.4 logit-comparison:需要 GPU 与大模型权重的手动测试
docs/code/develop/logit-comparison/BUILD.bazel 中,logit_comparison_test被标记为tags = ["manual"],不会进入常规 CI:
modular_run_binary_test( name = "logit_comparison_test", size = "enormous", binary = "logit_comparison", # This test downloads ~1.2GB of Qwen3-0.6B-Base weights from Hugging Face # and requires a GPU. Run manually with `bt-b200 //oss/modular/docs/code/develop/logit-comparison:logit_comparison_test`. tags = ["manual"], target_compatible_with = select({ "@platforms//os:macos": ["@platforms//:incompatible"], "//conditions:default": [], }), )原因在注释中写得很清楚:该测试需要 GPU,并会从 Hugging Face 下载约1.2GB 的 Qwen3-0.6B-Base 权重(依赖torch、transformers、numpy以及 MAX 的pipelines模块),因此声明为size = "enormous"且仅在有人工在带 GPU 的机器上显式触发时才运行(如bt-b200命令)。
五、文档与示例如何保持同步:DOC 头与同步检查
示例文件与文档页面之间不是松散对应,而是有机械化的同步约束机制。
5.1# DOC:头部:示例指向文档页
每个示例文件的第一行注释(License 块之后)都带一个# DOC:头,指明它被哪个文档页面引用。例如 arithmetic.py 的第 13 行:
# DOC: max/develop/basic-ops.mdxGPU 示例同理,detect_gpu.mojo 携带:
# DOC: max/gpu/fundamentals.mdx这些头指向的文档页面对应仓库中的docs/max/目录(如docs/max/gpu/fundamentals.mdx、docs/max/tile-tensor/layouts.mdx、docs/max/tile-tensor/tensors.mdx)。
5.2 同步检查工作流与 DOCS_SYNC_SKIP
按 docs/code/README.md 的描述,仓库通过checkExampleDocSync工作流读取该头部:当一个 PR 修改了docs/code/下的示例、却没有同步修改其指向的文档页面时,检查会失败,提醒作者补上文档改动。
如果代码改动确实不影响文档文字(例如仅重构、格式调整),可以在 PR 描述中加入DOCS_SYNC_SKIP来跳过该检查。
5.3 代码不会自动注入文档
README 特别强调了一个容易误解的点:
The code in this directory isnotautomatically injected into the documentation. The docs page keeps its own copy of the snippet inline.
即docs/code/中的代码不会在文档构建时自动注入到.mdx页面——文档页面内联保留着自己的一份代码副本。因此当你修改这里的示例时,必须同时更新.mdx页面中对应的代码块以及周边的解释文字。这也正是checkExampleDocSync存在的原因:它只负责"提醒",不负责"替你做"。
说明:本文撰写时,当前仓库快照的 .github/workflows/ 目录下并未包含
checkExampleDocSync工作流文件本身(仅见 auto-labeler、build_and_test、check_pr_target、check_pr_title、cla、test_pre_commit 等),上述行为描述以 docs/code/README.md 的文档说明为准。
六、docs/code/ 与 max/examples/ 的分工
两个目录都承载经过测试的 MAX 代码,但服务对象与组织方式不同,README 给出了清晰的对比:
| 维度 | docs/code/ | max/examples/ |
|---|---|---|
| 归属方 | 文档团队(docs-owned) | 工程师(engineer-owned) |
| 形态 | 与所依附的文档页同置的短小片段,聚焦阐释单一概念 | 可独立运行的完整示例项目,自成体系 |
| 目的 | 配合文档讲解,随文档一起维护 | 作为可运行的应用程序示范 |
| 引用方式 | 通过# DOC:头与文档页双向绑定 | 部分项目在被文档页引用时也带# DOC:反向引用 |
一个很实用的判断标准:如果你想表达"一段文档中的代码如何工作",看docs/code/;如果你想找一个能直接跑起来的完整应用或工程模板,去max/examples/(该目录下包含 custom_ops、diffusion、gpu-intro、pytorch_custom_ops 等 13 个以上独立示例项目)。
七、如何为文档示例做贡献
docs/code/README.md 的 Contributing 一节欢迎社区修正文档或示例中的错误。结合前文,贡献时需要遵循的核心流程是:
- 修改
docs/code/下对应的示例文件(保持# DOC:头不变或同步更新); - 同时更新对应
.mdx文档页面中内联的代码块与说明文字,否则checkExampleDocSync会拦下 PR; - 若改动纯粹是代码层面、不影响文档文字,在 PR 描述中添加
DOCS_SYNC_SKIP; - 本地用
bt //oss/modular/docs/code/...跑通相关测试后再提交; - 如果涉及 GPU 示例,确认目标机器的
//:has_gpu约束与 Apple GPU 兼容性(bf16 / print_threads 等已知限制)。
八、小结
docs/code/是 MAX 文档工程化的一个缩影:它把"文档里的代码"提升为一等公民,通过Bazel 测试目标 +# DOC:同步头 + CI 检查三层机制,确保文档示例在 API 演进中始终保持可编译、可运行、与文档一致。理解这套体系后,你既能用bt/br快速验证任意示例,也能在撰写 MAX/Mojo 文档时遵循同样的工程纪律——让每一段示例代码都成为经得起测试的"活文档"。
延伸阅读:docs/code/README.md(本体系的总纲)、docs/code/develop/basic-ops/BUILD.bazel(Python 示例构建范式)、docs/code/gpu/fundamentals/BUILD.bazel(Mojo 示例与 GPU 约束)、docs/code/tile-tensor/tensors/pixi.toml(Pixi 运行入口)。
【免费下载链接】mojoThe Modular Platform (includes MAX & Mojo)项目地址: https://gitcode.com/GitHub_Trending/mo/mojo
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考