[特殊字符] Mojo 语言:为 AI 硬件而生的“Python 升级版” —— 完整指南
摘要:Mojo是一种专为AI硬件优化的高性能编程语言,兼具Python的易用性和系统级编程能力。作为Python的超集,Mojo完全兼容Python生态,同时通过静态类型、所有权系统等特性实现高效内存管理。其核心优势包括:基于MLIR的深度优化、编译时元编程、自动硬件调优,官方测试显示比Python快数万倍。Mojo支持SIMD向量化计算、GPU内核编程,并可与NumPy、PyTorch等Pyth
第一部分:Mojo 语言详解
1. 背景:为什么需要 Mojo?
Mojo 是由 Modular 公司开发的一门全新编程语言,专门为解决 AI 硬件(CPU、GPU、TPU等)编程中的痛点而设计。
-
Python 的性能瓶颈:Python 开发效率高,但作为解释型语言,计算密集任务慢,且受全局解释器锁(GIL)限制,难以并行。
-
AI 硬件的编程门槛高:要发挥硬件极致性能,通常需要学习 C++、CUDA 等复杂语言。
-
“N 语言问题”:AI 开发常需要多种语言拼接,增加复杂度。
Mojo 的核心目标是 统一:用一门语言编写从高级 AI 逻辑到底层硬件内核的所有代码,无需在多语言间切换。
2. 核心优势:Python 的超集 + 系统级能力
-
完全兼容 Python 生态:Mojo 语法与 Python 高度相似,可无缝调用 Python 库(如 NumPy、PyTorch 等),Python 开发者几乎零门槛上手。
-
增加系统级编程能力:在 Python 之上引入了静态类型、值语义、自动内存管理、所有权系统、编译时元编程等特性,为高性能和硬件控制打下基础。
3. 高性能秘诀:革新的技术栈
-
MLIR 编译器基础设施:Mojo 基于 MLIR(Multi-Level Intermediate Representation),能深度优化针对各类 AI 硬件的代码,生成高效机器码。
-
强大的编译时元编程:通过
comptime等特性在编译时执行代码,实现零运行时开销的泛型和静态多态。 -
自动调优与直接硬件访问:内置自动调优(Autotuning),根据硬件自动选择最优计算方式;不依赖特定硬件库,直接生成底层指令,无隐藏开销。
-
惊人的性能理论值:官方宣称,在某些数学任务上,Mojo 比 Python 快 35000 倍 甚至 68000 倍。
4. 硬件控制能力
Mojo 提供精细的硬件抽象。一个实例:一支团队曾将一个约 3000 行的 NVIDIA CUTLASS 卷积内核(CUDA C++)移植为约 770 行 Mojo 代码,复用 90% 的基础设施,最终在 B200 GPU 上取得完全匹配的吞吐量(130.7 TFLOPS)。
5. 开发现状与生态
-
版本:目前已发布多个稳定迭代版本(最新为 2026 年的 26.2),1.0 稳定版计划在 2026 年夏末发布,届时将提供稳定 API。
-
社区:Modular 已开源超过 75 万行 Mojo GPU 内核代码,核心标准库遵循 Apache 2 协议开源。已吸引超过 17.5 万开发者 和 5 万个组织 关注。
-
挑战:语言较新,生态尚在建设中,库和框架不如 Python 丰富;部分平台(如 Windows 原生)支持仍在完善。官方明确指出,Mojo 的目标是提升 AI 基础设施和生成部署,并非替代 Python 在 AI 研究中的地位。
第二部分:超详细学习与开发资源
📖 官方文档
| 资源 | 说明 |
|---|---|
| Mojo 手册 | 权威入门指南,覆盖所有核心特性(Python 交互、结构体、所有权、元编程等)。 |
| Mojo API 参考 | 标准库的完整 API 技术文档,查询 SIMD、List、String 等具体类型。 |
| Mojo 变更日志 | 语言、标准库、工具的详细更新记录(如 v0.26.2 增加条件 trait 实现等)。 |
| Mojo 语言提案 | 设计文档,适合高级用户深入了解语法的决策背景。 |
🤝 社区与学习资料
-
中文社区
-
极客大学中文文档 — 完整的中文版官方文档
-
社区整理的中文学习资料汇总(博客、入门指南、标准库文档翻译)
-
英文资源
-
Modular 官方论坛 — 官方公告与技术交流
-
Mojo Miji 开源书籍 — 从 Python 开发者视角讲解 Mojo,附内存图与代码对比
-
《Mojo By Example》 — 通过大量实例系统介绍 Mojo 编程
-
DeepWiki 核心概念解析 — 详细阐释类型系统、内存管理等
-
Awesome Mojo (GitHub) — 社区维护的工具、库、示例列表
-
💻 代码与示例项目
-
官方社区示例:Modular 论坛“社区展示”板块包含 分形 Julia 集、LeNet-5 模型、游戏引擎、HyperLogLog 算法 等实现。
-
Mojo-raylib:官方的 raylib 游戏开发库,提供音频、着色器、纹理等多个示例。
-
MAX AI 内核库:编写高性能计算内核及自定义 AI 算子的 API,充分发挥硬件潜力。
🛠️ 开发工具
-
Mojo for VS Code:官方插件,支持语法高亮、代码补全、跳转到定义、调试等,是目前最推荐的集成开发环境。
-
magic工具:Mojo 官方提供的环境管理和项目初始化工具,支持 Nightly 版本体验最新特性。
第三部分:安装与使用完整指南
1. 系统与环境要求
-
操作系统:Linux(推荐 Ubuntu 22.04 LTS 或更新)、macOS(Sequoia 15 或更新,Apple Silicon)、Windows(通过 WSL,推荐 Ubuntu 22.04)。
-
处理器:x86-64(支持 SSE4.2)或 ARM64(如 AWS Graviton2)。
-
内存:最低 8 GB RAM。
-
显卡(可选):支持 NVIDIA(驱动 580+)、AMD 及 Apple GPU 编程。
-
软件依赖:Python 3.10 ~ 3.14、Git、C++ 编译器(Linux 需 g++ 或 clang++)。
2. 四种安装方式对比
| 方法 | 核心命令/步骤 | 适用场景 | 注意事项 |
|---|---|---|---|
magic (官方推荐) |
curl https://get.modular.com | sh -modular auth (输入 Token)modular install mojo |
通用推荐,新手首选 | 自动处理依赖和环境变量,更新方便 |
pixi (项目隔离) |
curl -fsSL https://pixi.sh/install.sh | shpixi init my_project && cd my_projectpixi add mojo |
为每个项目独立环境,避免版本冲突 | 适合多项目并行开发 |
| 源码编译 | git clone https://github.com/modularml/mojo.git参照 README.md 安装 LLVM 及构建依赖 |
深度开发、贡献代码 | 编译时间长,对开发者要求高 |
| 容器(Docker) | docker run -it modular/mojo:latest |
快速体验、CI/CD 环境 | 适合测试和临时使用 |
注意:安装前需要先在 Modular 官网 注册账号并获取个人访问 Token(执行
modular auth时使用)。
3. 验证安装
打开终端,运行:
mojo --version
如果成功显示版本号(如 mojo 26.2 (9a4d5b2)),则安装成功。
4. 第一个 Mojo 程序
创建一个文件 hello.🔥(Mojo 源文件扩展名为 .mojo 或 .🔥),写入:
# hello.🔥
fn main():
print("Hello, Mojo!")
5. 与 Python 交互
Mojo 可以无缝导入 Python 模块。例如:
mojo
from python import Python
let np = Python.import_module("numpy")
let arr = np.array([1, 2, 3], dtype=np.float64)
print(arr)
6. VS Code 配置
-
安装 “Mojo for Visual Studio Code” 插件。
-
打开
.mojo或.🔥文件,即可自动激活语法高亮、代码补全、调试等功能。 -
如需调试,按 F5 配置调试会话,选择 “Mojo” 环境。
附:常见问题
-
Q:Mojo 能替代 Python 吗?
A:不完全是。Mojo 旨在增强 AI 基础设施和生产部署,Python 依然在快速原型和大量生态库上占有优势。 -
Q:Windows 原生支持?
A:目前官方推荐通过 WSL 使用,原生 Windows 版正在积极开发中。 -
Q:如何更新 Mojo?
A:如果使用magic安装,执行modular update mojo即可。pixi则运行pixi update mojo。 -
Q:学习 Mojo 需要先懂 C++ 吗?
A:不需要。有 Python 基础即可学习,不过了解系统编程概念(指针、内存布局)会有帮助。
第四部分:深入了解 Mojo —— 核心语义与系统编程
如果说前面的内容让你能用 Mojo 写出能跑的代码,那么这一部分将带你进入 Mojo 设计的灵魂深处。要写出真正高性能、零 bug 的系统级代码,你无法绕过这三个核心命题:谁拥有内存、如何塑造行为、以及在什么时机完成计算。下面将逐一展开。
1. 所有权系统:无 GC 的内存安全基石
Mojo 采用了基于 所有权(Ownership) 的内存管理模型。它没有传统的垃圾回收(GC)或全面的引用计数,而是通过一系列编译时规则,确保每个值在任何时刻都只有一个可变“所有者”,当所有者生命周期结束时,值被自动销毁。
所有权的核心规则有三条:
-
单一所有者:每个值在任何时刻只有一个所有者变量。
-
作用域即生命周期:当所有者超出其作用域,所拥有的值立即被销毁。
-
引用延寿:如果存在指向某个值的引用,Mojo 会自动延长该值所有者的生命周期,防止悬空引用。
为了在“安全”和“系统级控制”之间取得平衡,Mojo 引入了以下参数约定,让你在函数调用时精准控制值如何被传递:
-
owned(默认):调用者将值的所有权转移给被调用函数,原变量无法再使用。 -
borrowed:被调用函数以只读方式借用值,不影响原变量的所有权。 -
inout:被调用函数获得值的可变引用,可以在函数内部修改原值。 -
^转移操作符:强制转移所有权,是owned行为的显式表达。
通过这些约定,Mojo 既避免了 C++ 中常见的悬垂指针和数据竞争,又没有像 Rust 那样对开发者施加严苛的约束。
2. 值语义 vs. 引用语义
Mojo 默认采用 值语义(Value Semantics),这意味着赋值或传递时,如果类型的复制成本低(如整型),编译器会创建一份独立的副本,它们互不影响。这种一致性带来的好处是:函数的内部修改不会意外泄漏到外部,代码行为更容易预测。
当然,对于大数组、张量等复杂类型,复制成本太高。此时你可以通过 inout(可变引用)或 borrowed(只读引用)来获得引用语义,从而避免昂贵的拷贝。Mojo 的灵活之处在于,它同时支持两种语义,并把决定权交给开发者,针对每种类型你都可以自定义其复制和移动的行为。
3. 生命周期:尽快销毁(ASAP)策略
Mojo 的生命周期管理遵循一个激进的策略:“尽快销毁” (ASAP)。一旦一个值在代码中不再被需要,Mojo 会立即销毁它,精确控制在每个子表达式执行完毕之后。
这与 Python 的引用计数(慢且易有循环引用)和 Go 的 GC (停顿时长不可控)完全不同。ASAP 策略意味着内存不会被无谓地占用,缓存友好度高。但同时它也对开发者提出了要求:你不能假设一个值能活到函数末尾,尤其是在涉及所有权转移操作时。
4. 深入理解 Trait:零成本的类型契约
Trait 是 Mojo 实现结构化类型的关键,它为 struct 定义了一套必须遵守的“行为契约”。你可以把它想象成 Java 的接口、Rust 的 Trait 或 Swift 的 Protocol。只有实现了某个 Trait 的类型,才能被相应的泛型函数接受。
Mojo 中的 trait 系统是 零成本的。编译器在编译时就会根据 trait 约束来检查和特化泛型代码,所以运行时不会有任何动态派发的开销,这点与 C++ 的模板概念类似。
标准库中预定义了两个基础 trait:
-
AnyType:所有类型的的顶级 trait。仅实现了AnyType的类型不会获得自动化的生命周期管理,可能需要显式调用析构逻辑。 -
CollectionElement与Movable:这是更具体的 trait,分别表示“可以作为集合元素”以及“可以被移动”。如果你在编写一个高性能容器,就必须约束元素类型满足Movable。
如果要约束一个类型具备多种 trait 的要求,需要使用命名组合的方式,例如定义一个 ComparableCollectionElement trait 来组合 CollectionElement 和 Comparable(当前版本不支持匿名组合)。此外,trait 的定义中也可以包含关联类型(Associated Types),供实现者在实现时绑定具体的类型。
5. 编译时元编程:comptime 的超能力
如果你想让程序在 编译时 就完成计算,而不是等到运行时挨个消耗 CPU 核心,就需要用到 Mojo 的编译时元编程。它的核心是 comptime 关键字,用于指明特定的变量或代码块应当在编译期求值。
你可以用 comptime 定义常数,或定义一个 comptime fn:这样的函数既可以用于编译期参数的计算,也可以生成运行时代码。它的典型应用包括:
-
编译时断言:如果检测到配置错误(比如
comptime assert size > 0),直接编译失败。 -
零成本抽象:利用 comptime 生成针对硬件特性的高度优化代码,而运行时没有任何分支或虚函数调用的开销。
这种设计将性能门槛留给了编译器,让运行时的二进制文件变得极致高效,且利用了 MLIR 的底层优化能力。
6. SIMD:显式向量化与数据级并行
单指令多数据流(SIMD)是现代 CPU 提升数据并行性能的核心机制。Mojo 通过内置的 SIMD 类型和 vectorize 高阶函数,让你能用高级语法直接调用底层的向量寄存器(如 AVX、SVE)。
SIMD[type, width] 是一个参数化类型,例如 SIMD[DType.float32, 8] 表示一个包含 8 个 f32 的向量。你可以直接对这些向量进行数学运算(如加法、乘法),编译器会径直生成对应的 SIMD 机器指令。
Mojo 提供的 vectorize 函数可以帮你简化 SIMD 循环的编写。你传入一个标量函数和一个 SIMD width,vectorize 会自动将循环分块,确保主体部分以给定的向量宽度执行。
编写高性能 SIMD 代码时的最佳实践包括:
-
宽度选择:应当结合目标硬件的物理寄存器宽度(例如 AVX2 是 256 位),避免因寄存器溢出导致性能回退。
-
对齐考量:尽量确保数据在内存中是对齐的(Aligned),这能显著提升
load/store的性能。 -
显示转换:在不同长度的 SIMD 向量之间赋值时,推荐使用
rebind方法,避免隐式转换带来的长度不匹配陷阱。
7. GPU 编程:从芯片到内核的直接通道
Mojo 的硬件抽象能力在 GPU 编程中体现得最为淋漓尽致。它的目标不是通过封装好的库间接调用 GPU,而是允许你直接编写 GPU 内核(Kernel),并直接在 Mojo 代码中启动它们。
编写一个向量加法的 GPU 内核的基本步骤包括:
-
使用
@kernel标注一个函数,这意味着该函数将在 GPU 的众多线程上并行运行。 -
获取 GPU 设备的句柄,并根据设备属性(如多处理器数量)来设定网格(grid)和线程块(block)的尺寸。
-
通过
launch_kernel()函数将内核调度到 GPU 上执行。
Mojo 的 GPU 编程有两大突出优势:
-
性能可移植性:Mojo 的编译器后端基于 MLIR 和 LLVM,同样的内核代码经过编译,可以高效运行在 NVIDIA、AMD 乃至 Apple Silicon 的 GPU 上。这使得 Mojo 成为构建高性能可移植科学计算内核的理想语言。
-
指令级精细控制:对于 NVIDIA GPU,你甚至可以突破标准库的限制,在 Mojo 代码中直接内联 PTX 汇编指令,以便利用最新的硬件特性。另一项发布于 2025 年 9 月 的研究更证实,Mojo 编写的科学计算内核在 H100 和 AMD MI300A GPU 上都取得了极具竞争力的性能表现。
8. 模型训练:MAX Engine 与 Vision Transformer (ViT) 实战案例
Mojo 通过 MAX Engine 体系为模型推理和训练提供了强大的性能支撑,下面就以 在 CIFAR-10 上训练 Vision Transformer (ViT) 为例,说明典型的生产级流程:
-
环境准备:使用
magic管理依赖,通过magic add max-engine添加 MAX 引擎。 -
数据加载:利用 Mojo 的 Python 互操作性导入
torchvision.datasets.CIFAR10,并将数据转换为 Mojo 张量。 -
模型定义:使用
max.tensor.Tensor定义张量,利用@parameter实现编译时形状特化的 Transformer Block 定义,避免运行时动态形状带来的开销。 -
训练图编译:构建
Pipeline,将前向传播、损失计算、反向传播全部封装,调用graph.compile()触发 MLIR 的全图优化和并行化,生成高度优化的二进制内核。 -
执行与调度:调用
execute(train_images, train_labels),MAX Engine 直接将数据并行分发到 GPU 核心,模型在此步骤完成参数更新。
第五部分:从零开始的实战代码示例
为了让前面的理论落地,这里为你准备了从入门到进阶的完整示例。每个例子都可以直接运行,建议你动手试试。
示例 0:前置准备与运行
创建文件: 使用 .mojo 或 .🔥 作为扩展名,推荐使用 .mojo(打字方便)。
运行命令:
mojo 文件名.mojo
REPL 交互式环境:
mojo
# 进入后输入代码,按 Ctrl+D 退出
如果你看到 print 报错: Mojo 的 print 函数需要导入,或使用内置的 print_no_newline()。示例中使用的 print() 是标准写法,新版本已支持。
示例 1:Hello Mojo 与基础语法
mojo
# hello_basic.mojo
# 1. 最简单的程序
fn main():
print("Hello, Mojo!")
# 2. 变量声明:let 不可变,var 可变
fn variable_demo():
let x: Int = 10 # 类型标注可选,通常自动推断
# x = 20 # 编译错误!let 变量不可重新赋值
var y = 20 # 类型自动推断为 Int
y = 30 # 可以修改
print("x =", x, "y =", y)
# 3. 字符串插值
fn string_interpolation():
let name = "Mojo"
let version = 26.2
print("Welcome to \(name) version \(version)")
# 4. 函数定义与返回值
fn add(a: Int, b: Int) -> Int:
return a + b
fn test_function():
let result = add(5, 7)
print("5 + 7 =", result)
# 5. 运行所有示例
fn main():
variable_demo()
string_interpolation()
test_function()
示例 2:控制流
mojo
# control_flow.mojo
# 1. if-elif-else
fn check_age(age: Int):
if age < 18:
print("未成年")
elif age < 60:
print("成年人")
else:
print("老年")
# 2. while 循环
fn while_demo():
var i = 0
while i < 5:
print("while 计数:", i)
i += 1
# 3. for 循环与 range
fn for_demo():
for i in range(5): # 0,1,2,3,4
print("for 计数:", i)
for i in range(2, 8, 2): # start=2, stop=8, step=2 → 2,4,6
print("步长 2:", i)
# 4. break 与 continue
fn break_continue_demo():
for i in range(10):
if i == 3:
continue # 跳过 3
if i == 7:
break # 到 7 结束
print("i =", i)
fn main():
check_age(25)
while_demo()
for_demo()
break_continue_demo()
示例 3:Struct —— 超越 class 的性能利器
Mojo 中没有 class,而是使用 struct。struct 默认是值语义(复制行为由你控制)。
mojo
# struct_demo.mojo
# 1. 简单 struct
struct Point:
var x: Int
var y: Int
# 构造函数(方法名固定为 __init__)
fn __init__(inout self, x: Int, y: Int):
self.x = x
self.y = y
# 方法
fn distance_to_origin(self) -> Float64:
return ((self.x * self.x + self.y * self.y) as Float64).sqrt()
fn __str__(self) -> String:
return "Point(\(self.x), \(self.y))"
# 2. struct 定义后使用
fn test_point():
let p = Point(3, 4)
print(p) # 输出: Point(3, 4)
print("到原点距离:", p.distance_to_origin()) # 输出: 5.0
# 3. 包含多个方法的复杂 struct
struct BankAccount:
var owner: String
var _balance: Int # 私有(约定)
fn __init__(inout self, owner: String, initial_balance: Int):
self.owner = owner
self._balance = initial_balance
fn deposit(inout self, amount: Int):
if amount > 0:
self._balance += amount
print("存入 \(amount),余额: \(self._balance)")
fn withdraw(inout self, amount: Int) -> Bool:
if amount > 0 and amount <= self._balance:
self._balance -= amount
print("取出 \(amount),余额: \(self._balance)")
return True
print("余额不足!")
return False
fn balance(self) -> Int:
return self._balance
fn test_bank():
var account = BankAccount("Alice", 1000)
account.deposit(500) # 存入 500,余额: 1500
account.withdraw(200) # 取出 200,余额: 1300
print("最终余额:", account.balance())
fn main():
test_point()
test_bank()
示例 4:所有权与参数约定
这是 Mojo 内存管理的核心。理解它,就能理解 Mojo 的精髓。
mojo
# ownership.mojo
# 1. 基础所有权:值只能有一个所有者
fn ownership_basic():
let a = 42 # a 拥有这个值
let b = a # 对于 Int 这种简单类型,会复制(值语义)
# a 仍然有效
print("a =", a, "b =", b)
# 2. ^ 操作符:转移所有权
struct Data:
var value: Int
fn __init__(inout self, v: Int):
self.value = v
fn __str__(self) -> String:
return "Data(\(self.value))"
fn take_ownership(arg: Data): # owned 是默认行为
print("接收所有权:", arg)
# 函数结束时 arg 被销毁
fn ownership_transfer():
let d = Data(100)
# take_ownership(d ^) # 使用 ^ 转移所有权
# print(d) # 编译错误!d 已经失去所有权
# 3. borrowed:只读借用
fn borrow_data(arg: borrowed Data):
print("借用并读取 value =", arg.value)
# 不能修改 arg,因为是只读借用
fn test_borrow():
let d = Data(200)
borrow_data(d) # 直接传递,自动 borrowed
print(d) # d 仍然可用
# 4. inout:可变借用(可修改原值)
fn modify_data(inout data: Data):
data.value += 50
fn test_inout():
var d = Data(300)
print("修改前:", d)
modify_data(d) # 传递可变引用
print("修改后:", d)
# 5. 参数约定速查表
#
# 约定关键字 | 所有权变化 | 能否修改 | 调用后原值是否可用
# -----------|--------------------------|---------|----------------
# (默认 owned)| 转移给函数 | 可以 | 否(除非用 ^ 显式转移)
# borrowed | 保持不变(只读借用) | 否 | 是
# inout | 保持不变(可变借用) | 可以 | 是(内容被修改)
fn main():
ownership_basic()
# ownership_transfer() # 取消注释会报错,请单独测试
test_borrow()
test_inout()
示例 5:Trait —— 让泛型更强大
Trait 用于定义类型必须实现的行为。
mojo
# trait_demo.mojo
# 1. 定义一个 Trait
trait Animal:
fn speak(self)
# 2. 实现 Trait
struct Dog:
var name: String
fn __init__(inout self, name: String):
self.name = name
fn speak(self):
print(self.name, "说: 汪汪!")
# 关键:让 Dog 实现 Animal trait
impl Animal for Dog:
fn speak(self):
print(self.name, "说: 汪汪!")
struct Cat:
var name: String
fn __init__(inout self, name: String):
self.name = name
fn speak(self):
print(self.name, "说: 喵喵~")
impl Animal for Cat:
fn speak(self):
print(self.name, "说: 喵喵~")
# 3. 泛型函数:接受任何实现了 Animal 的类型
fn animal_sound[T: Animal](animal: T):
animal.speak()
# 4. 使用泛型函数
fn test_trait():
let dog = Dog("旺财")
let cat = Cat("咪咪")
animal_sound(dog) # 输出: 旺财 说: 汪汪!
animal_sound(cat) # 输出: 咪咪 说: 喵喵~
fn main():
test_trait()
示例 6:SIMD 与向量化计算
SIMD(单指令多数据流)是 CPU 并行计算的利器。
mojo
# simd_demo.mojo
from math import sqrt
# 1. 基本 SIMD 向量操作
fn basic_simd():
# 创建 SIMD 向量:4 个 f32 元素
let a = SIMD[DType.float32, 4](1.5, 2.5, 3.5, 4.5)
let b = SIMD[DType.float32, 4](0.5, 1.5, 2.5, 3.5)
let c = a + b # 逐元素加法
print("a + b =", c)
let d = a * b # 逐元素乘法
print("a * b =", d)
let e = a.reduce_add() # 求和: 1.5+2.5+3.5+4.5 = 12
print("a 的和:", e)
# 2. 使用 splat 创建相同值的 SIMD
fn simd_splat():
let vec = SIMD[DType.int32, 8].splat(42) # 8 个 42
print("splat:", vec)
# 3. 手动 vectorize 循环
fn vectorized_add(dst: DTypePointer[DType.float32], src: DTypePointer[DType.float32], n: Int):
# 向量宽度:8 个 f32(对应 AVX-256)
alias vlen = 8
# 向量化部分
for i in range(0, n - n % vlen, vlen):
let vec_src = src.simd_load[DType.float32, vlen](i)
let result = vec_src + 1.0
dst.simd_store[DType.float32, vlen](i, result)
# 尾部标量处理
for i in range(n - n % vlen, n):
dst.store(i, src.load(i) + 1.0)
# 4. 性能对比:向量化 vs 标量
fn performance_comparison():
let n = 1024
var src = DTypePointer[DType.float32].alloc(n)
var dst_vec = DTypePointer[DType.float32].alloc(n)
var dst_scalar = DTypePointer[DType.float32].alloc(n)
# 初始化数据
for i in range(n):
src.store(i, i as Float32)
# 向量化版本
let vec_start = now()
vectorized_add(dst_vec, src, n)
let vec_time = (now() - vec_start) * 1e6 # 微秒
# 标量版本
let scalar_start = now()
for i in range(n):
dst_scalar.store(i, src.load(i) + 1.0)
let scalar_time = (now() - scalar_start) * 1e6
print("向量化耗时: \(vec_time) µs")
print("标量耗时: \(scalar_time) µs")
if scalar_time > 0:
print("加速比: \(scalar_time / vec_time)x")
src.free()
dst_vec.free()
dst_scalar.free()
fn main():
basic_simd()
simd_splat()
performance_comparison()
示例 7:Python 互操作 —— 调用 NumPy 和 PyTorch
这是 Mojo 的杀手级特性:无缝使用 Python 生态。
mojo
# python_interop.mojo
from python import Python
# 1. 初始化 Python 解释器
fn init_python():
Python.add_to_path(".")
# 导入 Python 模块
let np = Python.import_module("numpy")
let plt = Python.import_module("matplotlib.pyplot")
# 创建 NumPy 数组
let arr = np.array([1, 2, 3, 4, 5])
print("NumPy 数组:", arr)
print("数组形状:", arr.shape)
print("平均值:", np.mean(arr))
# 创建随机矩阵并计算矩阵乘法
let a = np.random.randn(3, 4)
let b = np.random.randn(4, 5)
let c = np.dot(a, b)
print("矩阵乘法结果形状:", c.shape)
# 2. 在 Mojo 和 Python 之间传递数据
fn data_exchange():
let np = Python.import_module("numpy")
# Python → Mojo
let python_array = np.array([1.5, 2.5, 3.5])
# 读取 Python 数组中的值
let first = python_array[0].to_float64()
print("第一个元素:", first)
# Mojo → Python: 需要将 Mojo 数据转为 Python 对象
var mojo_list = Python.eval("[10.0, 20.0, 30.0]")
let mojo_array = np.array(mojo_list)
print("从 Mojo 列表创建的 NumPy 数组:", mojo_array)
# 3. 使用 PyTorch
fn pytorch_example():
let torch = Python.import_module("torch")
# 在 GPU 上创建张量
let device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
let x = torch.randn(100, 100, device=device)
let y = torch.randn(100, 100, device=device)
let z = torch.matmul(x, y)
print(f"矩阵乘法结果设备: {z.device}, 形状: {z.shape}")
fn main():
init_python()
data_exchange()
try:
pytorch_example()
except:
print("PyTorch 未安装或 CUDA 不可用,跳过此示例")
更多推荐



所有评论(0)