Mojo之Mojo VS Python

本文比较了Python、numpy和Mojo在计算欧式距离上的性能,发现Mojo显著优于Python,甚至比numpy更高效,对于深度学习中的矩阵运算具有重要影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

  语言千千万,谁是你的最爱?我推Mojo(咒语),因为Mojo可以让Python(蟒蛇)变成龙。本章就来比一比Mojo和Python谁更快。使用的Mojo版本是0.4.0。


一、什么是欧式距离

  图中两个点,一个蓝色,一个红色,他们之间的欧式距离为多少?答案非常简单。
d i s t a n c e = ( x 2 − x 1 ) 2 + ( y 2 − y 1 ) 2 distance = \sqrt{(x_2-x_1)^2 + (y_2-y_1)^2} distance=(x2x1)2+(y2y1)2
  很简单的吧。

  上面的只是二维空间的计算方式,如果是三维,或者有n个维度的空间该怎么计算呢?还是一样的计算方法。
d i s t a n c e = ( x 1 − y 1 ) 2 + ( x 2 − y 2 ) 2 + ⋯ + ( x n − y n ) 2 = ∑ i = 1 n ( x i − y i ) 2 distance = \sqrt{(x_1-y_1)^2+(x_2-y_2)^2+\cdots+(x_n-y_n)^2}=\sqrt{\sum_{i=1}^n(x_i-y_i)^2} distance=(x1y1)2+(x2y2)2++(xnyn)2 =i=1n(xiyi)2

二、测试代码

  1. 纯Python计算欧式距离。
%%python
import numpy as np
from timeit import timeit
np.random.seed(100)#给个随机种子,使得每次随机结果不变
def naive_euclidean_distance(a, b):
    distance = 0
    for i in range(len(a)):
        distance += (a[i] - b[i])**2
    return np.sqrt(distance)
points = 1000000#大一点,比较好测试时间
a = np.random.randn(points).tolist()#申请array,转成列表
b = np.random.randn(points).tolist()#申请array,转成列表
distance = naive_euclidean_distance(a,b)#计算欧式距离
secs = timeit(lambda: naive_euclidean_distance(a,b), number=10)/10#运行10次所用的平均时间,单位s
ms = secs * 1000#毫秒
print("The euclidean distance is {:.2f}, spent {:.2f} ms.".format(distance, ms))

  %%python表示,我们在选择Mojo核的jupyter中运行Python解释器解释的代码,使得代码运行效果和Python一样。这样就不需要我们有两个单独的环境来测试。

  1. 使用numpy计算欧式距离。

  在numpy中有专门计算欧式距离的函数linalg.norm()。

%%python
import numpy as np
from timeit import timeit
np.random.seed(100)#给个随机种子,使得每次随机结果不变
def numpy_euclidean_distance(a, b):
    return np.linalg.norm(a-b)
points = 1000000#大一点,比较好测试时间
a = np.random.randn(points)
b = np.random.randn(points)
distance = numpy_euclidean_distance(a,b)#计算欧式距离
secs = timeit(lambda: numpy_euclidean_distance(a,b), number=10)/10#运行10次所用的平均时间,单位s
ms = secs * 1000#毫秒
print("The euclidean distance is {} and spent {} ms.".format(distance, ms))
  1. Mojo计算欧式距离
from tensor import Tensor
from python import Python
from math import sqrt
from time import now
let np = Python.import_module("numpy")
np.random.seed(100)#给个随机种子,使得每次随机结果不变
def mojo_euclidean_distance(a: Tensor[DType.float64], b: Tensor[DType.float64]) -> Float64:
    var distance: Float64 = 0.0
    points = a.num_elements()
    for i in range(points):
        dist = (a[i] - b[i])
        distance += dist * dist
    return sqrt(distance)

let points: Int = 1000000
let a = np.random.randn(points)
let b = np.random.randn(points)

var alist = Tensor[DType.float64](points)
var blist = Tensor[DType.float64](points)
for i in range(points):
    alist[i] = a[i].to_float64()
    blist[i] = b[i].to_float64()
let start = now()#获取当前时间
let distance = mojo_euclidean_distance(alist, blist)
let end = now()
print("The euclidean distance is", distance, "and spent ", (end-start)/1e6, "ms")
  1. 优化后的Mojo计算欧式距离
from tensor import Tensor
from python import Python
from math import sqrt
from time import now
let np = Python.import_module("numpy")
np.random.seed(100)#给个随机种子,使得每次随机结果不变
fn mojo_euclidean_distance(a: Tensor[DType.float64], b: Tensor[DType.float64]) -> Float64:#此处改变
    var distance: Float64 = 0.0
    let points = a.num_elements()#此处改变
    for i in range(points):
        let dist = (a[i] - b[i])#此处改变
        distance += dist * dist
    return sqrt(distance)

let points: Int = 1000000
let a = np.random.randn(points)
let b = np.random.randn(points)

var alist = Tensor[DType.float64](points)
var blist = Tensor[DType.float64](points)
for i in range(points):
    alist[i] = a[i].to_float64()
    blist[i] = b[i].to_float64()
let start = now()
let distance = mojo_euclidean_distance(alist, blist)
let end = now()
print("The euclidean distance is", distance, "and spent ", (end-start)/1e6, "ms")

三、测试结果

  1. 纯Python测试结果

在这里插入图片描述

  1. numpy测试结果

在这里插入图片描述

  1. Mojo测试结果

在这里插入图片描述

  1. 优化过后的Mojo测试结果

在这里插入图片描述

  优化Mojo就把def改成fn。fn中Mojo会对类型进行检查,需要对变量进行显示声明。改变的地方已经在代码中标明#此处改变。更多fn与def特性请移步至Mojo官网,或者Mojo中文网。

总结

  测试结果很明显,Mojo要比Python快很多,比numpy也快,要知道numpy底层是c/c++实现。在深度学习中有大量的矩阵乘加运算,如果矩阵计算提升哪怕是一点点速度,也是可怕的。要想让你的AI起飞,选什么语言,相信你心中已经有了答案。

### 比较MojoPython的执行速度 为了比较两种编程语言之间的性能差异,通常会通过编写相同功能的小型程序并测量其运行时间来进行评估。对于MojoPython而言,可以从简单的计算密集型任务入手。 #### 测试环境设置 确保测试在同一硬件环境下进行,并且尽可能减少其他进程干扰。可以使用标准库中的计时器函数来记录代码片段的执行时间。 #### Python示例代码 ```python import time def python_test(): start_time = time.time() sum_result = 0 for i in range(1_000_000): sum_result += i * i end_time = time.time() print(f"Python Execution Time: {end_time - start_time} seconds") if __name__ == "__main__": python_test() ``` #### Mojo示例代码假设 由于目前关于Mojo的具体实现细节较少公开资料可查,在此仅提供一种可能的方式用于对比实验设计思路[^1]: ```mojo // 假设这是Mojo的一个简单版本 function mojoTest() { var startTime = System.currentTimeMillis(); let sumResult = 0; for (var i = 0; i < 1_000_000; ++i) { sumResult += i * i; } var endTime = System.currentTimeMillis(); println("Mojo Execution Time:", (endTime - startTime)/1000, "seconds"); } @EntryPoint fn main() { mojoTest(); } ``` 需要注意的是,上述例子中使用的算法非常基础,实际应用中不同语言特性会对最终结果有很大影响。此外,动态优化技术如多态方法调用可能会使某些静态类型的编译期优化失效而转为运行时期间完成。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值