Python 代码直接在 Mojo 中运行
Mojo 是 Python 的超集
Mojo 最重要的设计决策之一:它是 Python 的严格超集。这意味着合法的 Python 代码在 Mojo 中也是合法的(绝大多数情况下)。你不需要重写现有的 Python 代码就可以在 Mojo 环境中运行。
# 这是合法的 Mojo 代码,也是合法的 Python 代码
def greet(name):
return f"Hello, {name}!"
# 列表推导式
squares = [x**2 for x in range(10)]
print(squares)
# 字典操作
data = {"model": "GPT-4", "tokens": 8192}
for key, value in data.items():
print(f"{key}: {value}")
# 类定义(Python 风格)
class Model:
def __init__(self, name: str):
self.name = name
def predict(self, x):
return x * 2
def main():
m = Model("my-model")
print(m.predict(5)) # 10
from python import:导入 Python 库
Mojo 内置了 Python 解释器集成,可以直接导入任何已安装的 Python 库。Mojo 使用 from python import 语法启动嵌入式 CPython 解释器,加载 Python 模块。
from python import Python
def main():
# 导入 NumPy
var np = Python.import_module("numpy")
# 创建 NumPy 数组
var arr = np.array([1.0, 2.0, 3.0, 4.0])
print(arr) # [1. 2. 3. 4.]
print(arr.mean()) # 2.5
# 矩阵运算
var mat = np.random.rand(3, 3)
var result = np.dot(mat, mat)
print(result)
PythonObject 类型
什么是 PythonObject?
当你在 Mojo 中使用 Python 对象时,它们被包装为 PythonObject 类型。这个类型是 Mojo 和 Python 运行时之间的桥梁,负责引用计数、类型转换和调用约定的适配。
from python import Python, PythonObject
def main():
# PythonObject 可以持有任何 Python 值
var py_int: PythonObject = 42
var py_str: PythonObject = "hello"
var py_list: PythonObject = [1, 2, 3]
# 调用 Python 方法
print(py_str.upper()) # HELLO
print(py_list.__len__()) # 3
# 从 Python 对象转换为 Mojo 原生类型
var mojo_int: Int = py_int.to_int()
var mojo_str: String = String(py_str)
print(mojo_int + 10) # 52(Mojo 原生 Int 运算)
PythonObject 的性能含义
使用 PythonObject 意味着你在走 Python 的动态类型路径,所有操作都经过 CPython 解释器,不能获得 Mojo 的编译期优化。这是设计取舍:互操作性 vs 性能。
用 PythonObject:调用 Python 库(NumPy/PyTorch/Pandas)、对接现有 Python 代码、处理动态数据结构。
用 Mojo 原生类型:热路径计算、SIMD 操作、性能敏感代码。
最佳实践:在 Python 生态中准备数据,交给 Mojo 原生代码进行高速计算,结果再传回 Python。
调用主流 Python 库
NumPy:数值计算
from python import Python
def numpy_demo():
var np = Python.import_module("numpy")
# 创建数组并做矩阵乘法
var A = np.random.rand(1000, 1000)
var B = np.random.rand(1000, 1000)
var C = np.dot(A, B) # NumPy 内部用 BLAS,已经很快
print("结果形状:", C.shape)
# 统计运算
print("均值:", C.mean())
print("标准差:", C.std())
def main():
numpy_demo()
Pandas:数据处理
from python import Python
def pandas_demo():
var pd = Python.import_module("pandas")
# 读取 CSV 文件
var df = pd.read_csv("data.csv")
print(df.head())
print(df.describe())
# 数据过滤
var filtered = df[df["score"] > 0.8]
print("高分样本数量:", len(filtered))
实战:在 Mojo 中调用 PyTorch
from python import Python
def pytorch_inference():
var torch = Python.import_module("torch")
var torchvision = Python.import_module("torchvision")
# 加载预训练 ResNet-50
var models = torchvision.import_module("models")
var model = models.resnet50(pretrained=True)
model.eval()
# 创建随机输入张量(batch_size=1, channels=3, 224x224)
var dummy_input = torch.randn(1, 3, 224, 224)
# 推理(不计算梯度)
with torch.no_grad():
var output = model(dummy_input)
# output.shape: [1, 1000](ImageNet 1000 类)
var predicted_class = output.argmax(dim=1)
print("预测类别 ID:", predicted_class)
def main():
pytorch_inference()
逐步迁移策略:Python → Mojo
迁移的四个阶段
不需要一次性重写所有代码。推荐的迁移路径是渐进式的,按性能影响从大到小排序:
直接运行 Python 代码(零迁移成本)
将 .py 改名为 .mojo,用 Mojo 解释器运行。性能与 Python 相同,但你已经在 Mojo 环境中了。
关键函数加类型注释(10-100x 加速)
将 def 改为 fn,添加参数类型和返回类型声明。Mojo 编译器可以立即做大量优化。
使用 var/let 声明变量(减少动态开销)
用 var 声明可变变量,用 let 声明不可变变量,帮助编译器做别名分析和优化。
SIMD + 并行化热路径(100-10000x 加速)
对计算密集的内循环使用 vectorize 和 parallelize,这是性能提升最大的阶段。
实际迁移示例
# 原始 Python 代码
def dot_product(a, b):
result = 0.0
for i in range(len(a)):
result += a[i] * b[i]
return result
# ~500ms for 10M elements
# 迁移后的 Mojo 代码
fn dot_product(
a: List[Float64],
b: List[Float64]
) -> Float64:
var result: Float64 = 0.0
for i in range(len(a)):
result += a[i] * b[i]
return result
# ~5ms for 10M elements (100x faster)
Python 互操作的性能影响
性能边界在哪里?
理解 Mojo 和 Python 的性能边界对于写出高效代码至关重要。每次从 Mojo 调用 Python 函数,都会经历以下开销:
不要在 Mojo 循环内逐个元素调用 Python 函数。应该:在 Mojo 侧准备好整个数据批次,一次性传给 NumPy/PyTorch,用向量化操作处理,结果一次性返回给 Mojo。
Python 超集:Python 代码可以直接在 Mojo 中运行,无需修改。
PythonObject:Mojo 中 Python 对象的包装类型,提供完整 Python 动态特性但不享受编译期优化。
from python import:通过嵌入式 CPython 解释器导入任意 Python 库。
性能影响:跨越 Mojo/Python 边界有开销,批量操作可以最小化这种影响。
迁移策略:def → fn → var/let → SIMD,渐进式提升性能,而非一次性重写。