Py学习  »  Python

Python 现在可以运行 Mojo 了?

程序员好物馆 • 2 天前 • 25 次点击  


图片
作者 | Vincent      编译 | 苏宓
出品 | CSDN(ID:CSDNnews)

两年前,Swift 之父、编译器大神 Chris Lattner 和 Google 前员工 Tim Davis 组队创立了初创公司 Modular,推出了高性能编程语言 Mojo。凭借“比 Python 快 90000 倍”的惊人宣传语,Mojo 成为整个开发者社区关注的焦点,被认为是“可能彻底改变 Python 命运”的新语言。

Chris Lattner 曾这样描述 Mojo:“ 它是 Python 家族的一员,汲取了所有这些酷炫的语言、编译器和其他技术,让 Python 向前迈进了一大步。我们认为它增强了 Python 的能力,赋予 Python 程序员超能力,让熟悉 Python 的人能够学习新知识,探索并征服新领域,而无需转用 C++。”

而如今,Chris Lattner 低调放出了一个意味深长的新变化:Python 现在可以直接调用 Mojo 代码了。

Mojo 正在被 Python 调用

据开发者 Vincent D. Warmerdam 的实测,Python 调用 Mojo 现在变得非常简单,详细步骤如下。

首先,可以直接用 uv 安装:

uv pip install modular --index-url https://dl.modular.com/public/nightly/python/simple/

然后你可以创建一个 .mojo 文件,导出一个计算阶乘的函数 factorial(),内容如下:

# mojo_module.mojofrom python import PythonObjectfrom python.bindings import PythonModuleBuilderimport mathfrom os import abort@exportfn PyInit_mojo_module() -> PythonObject:    try:        var m = PythonModuleBuilder("mojo_module")        m.def_function[factorial]("factorial", docstring="Compute n!")        return m.finalize()    except e:        return abort[PythonObject](String("error creating Python Mojo module:", e))fn factorial(py_obj: PythonObject) raises -> PythonObject:    var n = Int(py_obj)    var result = 1    for i in range(1, n + 1):        result *= i    return result

然后你就可以在 Python 中加载它:

# main.pyimport max.mojo.importerimport osimport sysimport time import mathsys.path.insert(0"")import mojo_modulestart = time.time()print(mojo_module.factorial(10))end = time.time()print(f"Time taken: {end - start} seconds for mojo")start = time.time()print(math.factorial(10))end = time.time()print(f"Time taken: {end - start} seconds for python")

运行结果如下:

3628800Time taken: 3.0279159545898438e-05 seconds for mojo3628800Time taken: 5.0067901611328125e-06 seconds for python

一切运行正常。

问题显现

不过,在实测时,Vincent 也注意到了一些问题,对于 factorial(10) 这样的轻量计算,Mojo 与 Python 本身速度相差无几。但当输入扩大到 factorial(100) 时,Mojo 返回的结果却是错误的(输出为 0),而 Python 的结果则是正确的。

0


    
Time taken: 2.7894973754882812e-05 seconds for mojo188267717688892609974376770249160085759540364871492425887598231508353156331613598866882932889495923133646405445930057740630161919341380597818883457558547055524326375565007131770880000000000000000000000000000000Time taken: 9.298324584960938e-06 seconds for python

这可能是 Mojo 侧溢出的结果。文档也提到这整套系统还处于早期阶段,说明其数值系统尚不成熟。

另一个例子

考虑到上面的问题可能是溢出引起的,Vincent 又试了一个例子来看看能不能测出加速效果。这次是一个朴素的素数统计实现。Mojo 代码如下:

from python import PythonObjectfrom python.bindings import PythonModuleBuilderimport mathfrom os import abort@exportfn PyInit_mojo_module() -> PythonObject:    try:        var m = PythonModuleBuilder("mojo_module")        m.def_function[count_primes]("count_primes", docstring="Count primes up to n")        return m.finalize()    except e:        return abort[PythonObject](String("error creating Python Mojo module:", e))fn count_primes(py_obj: PythonObject) raises -> PythonObject:    var n = Int(py_obj)    var count: Int = 0    for i in range(2, n + 1):        var is_prime: Bool = True        for j in range(2, i):            if i % j == 0:                is_prime = False                break        if is_prime:            count += 1    return count

对应的 Python 测试代码如下,此外 Vincent 还加了一个 NumPy 实现做对比:

import numpy as npimport max.mojo.importerimport osimport sysimport time import mathsys.path.insert(0"")import mojo_moduledef count_primes(n):    count = 0    for i in range(2, n + 1):        is_prime = True        for j in range(2, i):            if i % j == 0:                is_prime = False                break        if is_prime:            count += 1    return countdef count_primes_numpy(n):    if n 2:        return 0    candidates = np.arange(2, n + 1)    is_prime_mask = np.ones(len(candidates), dtype=bool)


    
    for idx, candidate in enumerate(candidates):        if candidate == 2:            continue        divisors = np.arange(2, candidate)        has_divisor = np.any(candidate % divisors == 0)        if has_divisor:            is_prime_mask[idx] = False    return np.sum(is_prime_mask)n = 20_000start = time.time()print(count_primes(n))end = time.time()print(f"Time taken: {end - start} seconds for python")start = time.time()print(count_primes_numpy(n))end = time.time()print(f"Time taken: {end - start} seconds for numpy")start = time.time()print(mojo_module.count_primes(n))end = time.time()print(f"Time taken: {end - start} seconds for mojo")

运行结果如下:

  • Python 原生实现耗时:约 0.45 秒

  • NumPy 实现耗时:约 0.26 秒

  • Mojo 实现耗时:仅 0.01 秒

2262Time taken: 0.44585609436035156 seconds for python2262Time taken: 0.25995898246765137 seconds for numpy2262Time taken: 0.011101961135864258 seconds for mojo

尽管这一 benchmark 并非最优算法,但结果仍然具备参考价值:在这种纯 CPU 密集型的计算任务中,Mojo 的性能提升确实相当明显,尤其是与 NumPy 相比也有数量级上的优势。

写在最后

整体而言,通过实测,Vincent 发现,Mojo 的语法风格延续了 Python 的简洁性,同时具备编译语言的性能与类型系统。

不过,Mojo 当前仍处于早期阶段。文档覆盖不全、标准库功能有限、整套开发体验尚不稳定……这也意味着距离“生产可用”还有距离。

但从 Modular 的近期动作可以看出,该团队正在有意识地为 Python 社区打造“融合路径”——不是简单地“替代 Python”,而是围绕其生态做加速和增强。这种“拥抱兼容”的姿态或许更务实,也更容易获得社区的接纳。

对此,Vincent 评价道,「现在还不能称得上“生产可用”,但我已经更有信心了 —— 梦想确实正在靠近。

原文:https://koaning.io/posts/giving-mojo-a-spin/

图片
好啦,今天的内容分享就到这,感觉不错的同学记得分享点赞哦!
PS:程序员好物馆 持续分享程序员学习、面试相关干货,不见不散!
图片
点分享
图片
点收藏
图片
点点赞
图片
点在看

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/183647
 
25 次点击