第一部分: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 技术文档,查询 SIMDListString 等具体类型。
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 | sh
pixi init my_project && cd my_project
pixi 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 配置

  1. 安装 “Mojo for Visual Studio Code” 插件。

  2. 打开 .mojo 或 .🔥 文件,即可自动激活语法高亮、代码补全、调试等功能。

  3. 如需调试,按 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)或全面的引用计数,而是通过一系列编译时规则,确保每个值在任何时刻都只有一个可变“所有者”,当所有者生命周期结束时,值被自动销毁。

所有权的核心规则有三条:

  1. 单一所有者:每个值在任何时刻只有一个所有者变量。

  2. 作用域即生命周期:当所有者超出其作用域,所拥有的值立即被销毁。

  3. 引用延寿:如果存在指向某个值的引用,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 widthvectorize 会自动将循环分块,确保主体部分以给定的向量宽度执行。

编写高性能 SIMD 代码时的最佳实践包括:

  • 宽度选择:应当结合目标硬件的物理寄存器宽度(例如 AVX2 是 256 位),避免因寄存器溢出导致性能回退。

  • 对齐考量:尽量确保数据在内存中是对齐的(Aligned),这能显著提升 load/store 的性能。

  • 显示转换:在不同长度的 SIMD 向量之间赋值时,推荐使用 rebind 方法,避免隐式转换带来的长度不匹配陷阱。

7. GPU 编程:从芯片到内核的直接通道

Mojo 的硬件抽象能力在 GPU 编程中体现得最为淋漓尽致。它的目标不是通过封装好的库间接调用 GPU,而是允许你直接编写 GPU 内核(Kernel),并直接在 Mojo 代码中启动它们。

编写一个向量加法的 GPU 内核的基本步骤包括:

  1. 使用 @kernel 标注一个函数,这意味着该函数将在 GPU 的众多线程上并行运行。

  2. 获取 GPU 设备的句柄,并根据设备属性(如多处理器数量)来设定网格(grid)和线程块(block)的尺寸。

  3. 通过 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 不可用,跳过此示例")

 

 

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐