文章目录
面向 AI 开发者的新型编程语言Mojo一、什么是mojoLLVMMLIR为什么选择Mojo? 二、Mojo安装系统要求安装步骤Mojo Visual Studio Code (VS Code) 扩展 安装 三、官方hello world交互式运行构建和运行Mojo源文件构建可执行的二进制 四、Mojo语言基础Mojo 语言基础知识语法和语义函数变量函数参数和返回值 Python集成 五、 探索GitHub 上的示例矩阵与矩阵乘积Mandelbrot集
面向 AI 开发者的新型编程语言Mojo
一、什么是mojo
官网:https://www.modular.com/
官方文档:https://docs.modular.com/mojo/
随着人工智能的发展,我们迫切需要一种性能非常好的专门针对AI的语言,因为Python的性能差,其余都是优点,当然Python也可以调用C++来弥补这个缺陷,就是在核心性能需求方面都需要求助于C和C++来处理。
Modular 公司由 LLVM 和 Swift 编程语言的联合创始人 Chris Lattner 创办,Modular AI公司针对这个问题设计了Mojo。
Mojo 是一种面向 AI 开发者的新型编程语言。随着时间推移,它将逐步成长为 Python 的超集。Mojo 已经支持与任意 Python 代码的无缝集成,并提供可扩展的编程模型以支撑各类关键性能系统,包括在 AI 场景中普遍存在的加速器(例如 GPU)。
Mojo 能够随时随地服务于 AI 开发者,将 Python 的可用性与以往强制开发者使用 C、C++ 或 CUDA 的系统编程功能结合起来。 开发者可以在公共代码库上工作,从而简化从研究到生产的整个工作流程。
Mojo 能够发挥 CPU 的性能潜力,并可良好支持 GPU 和 ASIC 等外部加速器,提供与 C++ 和 CUDA 相当的卓越性能。
Mojo ? — 面向所有 AI 开发人员的新编程语言
Mojo 是一种结合了 Python 的可用性和 C 的性能的编程语言,解锁了 AI 硬件无与伦比的可编程性和 AI 模型的可扩展性。
总结:专为AI而设计Mojo新编程语言。mojo可能更适合那些专门从事人工智能开发的python程序员
LLVM
LLVM是一个编译器框架。 LLVM项目始于2000年,是一个基于寄存器架构的编译器基础设施,可以编译C、C++、Objective-C、Python、Java等语言。LLVM项目包括一个运行时系统、一个代码分析和优化引擎,以及一个代码生成和执行引擎。LLVM框架可以编译C、C++、Objective-C、Python、Java等语言,也可以与C#、F#等语言进行交互。LLVM项目还包含一些单独的组件,如clang(一个基于LLVM框架的C/C++语言编译器)、clang-tools(一个基于clang的C/C++语言工具包)、libclang(一个基于LLVM的C/C++语言库)等。
在过去的十年里,LLVM极大地简化了强大的新编程语言的开发(比如Rust、Julia和Swift,它们都是基于LLVM的)一样,MLIR为基于它构建的语言提供了一个更强大的核心。
LLVM被广泛使用,如Apple的Swift编译器就是基于LLVM。其他使用LLVM的知名项目还有Rust,Julia语言等。总体来说,LLVM是一个非常先进和广泛使用的编译器框架。
MLIR
MLIR(Multi-Level Intermediate Representation)是一种由Google发起的中间表示(IR)框架,它作为LLVM项目的一部分被开发出来。
MLIR是一种新的IR表示,是LLVM项目的子项目。它参考了已有的编译器优点,规避了一些缺陷。包括了中间表示的定义、转换以及优化等功能,极大地方便了新型编译器的开发和调试工作。同时,MLIR也包含了很多现成的工具可直接使用(batteries included)。MLIR包揽了编译器设计中的通用部分,使得编译器的开发人员可以专注于核心的语义分析、中间表示的设计和变换,以此降低开发成本,提高开发效率和提高成品质量。
MLIR让编译器前端可以生成抽象的语言无关IR,然后由MLIR进行多层的转换和优化,并最终映射到不同的后端目标,使编译器的各阶段可以被模块化和重用。MLIR被看作是LLVM编译架构的未来发展方向。
在编译器中,前端(Frontend)和后端(Backend)是一个常见的概念,具体来说:
前端(Frontend):负责将源代码(源语言)转换成抽象的中间表示(Intermediate Representation, IR)的编译器组件。对源语言进行词法分析、语法分析、语义分析,生成IR。后端(Backend):负责将中间表示转换为目标平台的机器代码或 executable 文件的编译器组件。包含代码生成、优化和目标代码生成等步骤。举个例子:Clang 前端:将C/C++代码转换为LLVM IR。LLVM后端:将LLVM IR转为X86、ARM、RISC-V等平台的机器代码。
而在MLIR中:前端:生成高层抽象的MLIR。后端:将MLIR Lower/转换为LLVM IR或直接生成平台机器代码。
前端和后端的分工使编译器的不同阶段(源语言解析、IR转换、代码生成等)分割得很清晰,也使编译器可以重用各个组件,如用不同的前端连接同一个后端。
为什么选择Mojo?
官方文档:https://docs.modular.com/mojo/why-mojo.html
1、Python Like Syntax:与 Python 相似的语法,使开发人员可以轻松上手。
2、Compatibility with Python Libraries:兼容很多现有的Python科学计算库。
3、卓越的性能:比 Python 快 35000 倍。
4、单一语言写作:无需单独掌握C++或Python;仅使用 Mojo 执行这两种功能
5、并行处理:Mojo 使用 MLIR 在专用 AI 硬件单元上进行矢量化、线程化处理。
6、模型更容易扩展:升级模型比以往任何时候都容易。
二、Mojo安装
Mojo编译器和IDE工具已首次开放本地下载,覆盖Linux系统,未来还将支持Mac和Windows平台。
Modular 是一套集成的,可组合的工具套件,可简化您的AI基础架构,因此您的团队可以更快地开发,部署和创新。
系统要求
官方文档:https://developer.modular.com/download
Ubuntu 20.04 及更高版本x86-64 CPU 和最低 4 GiB RAMPython 3.8 - 3.10g++ 或 clang++ 编译器请注意:目前仅支持Ubuntu 20.04 及更高版本~
安装步骤
官方文档:https://developer.modular.com/download
1、以root权限执行以下命令:
apt-get install -y apt-transport-https && keyring_location=/usr/share/keyrings/modular-installer-archive-keyring.gpg && curl -1sLf 'https://dl.modular.com/bBNWiLZX5igwHXeu/installer/gpg.0E4925737A3895AD.key' | gpg --dearmor >> ${keyring_location} && curl -1sLf 'https://dl.modular.com/bBNWiLZX5igwHXeu/installer/config.deb.txt?distro=debian&codename=wheezy' > /etc/apt/sources.list.d/modular-installer.list && apt-get update && apt-get install -y modular
如果已手动安装软件包,您还需要手动进行身份验证,例如:
modular auth mut_50058c6b9aab473fb5857fd59fd6dd15 &&modular install mojo
安装成功:
? Mojo installed! ?Mojo's Python virtual environment created at /root/.modular/pkg/packages.modular.com_mojo/venvNow run the following commands if you are using bash:echo 'export MODULAR_HOME="/root/.modular"' >> ~/.bashrcecho 'export PATH="/root/.modular/pkg/packages.modular.com_mojo/bin:$PATH"' >> ~/.bashrcsource ~/.bashrcIf you are using ZSH, run the following commands:echo 'export MODULAR_HOME="/root/.modular"' >> ~/.zshrcecho 'export PATH="/root/.modular/pkg/packages.modular.com_mojo/bin:$PATH"' >> ~/.zshrcsource ~/.zshrcThen enter 'mojo' to start the Mojo REPL.For tool help, enter 'mojo --help'.For more docs, see https://docs.modular.com/mojo.
Mojo使用Python虚拟环境来隔离其依赖库,创建在/root/.modular/pkg/packages.modular.com_mojo/venv路径下。
export:通过export命令将相关环境变量导出,包括Mojo的home目录和可执行文件路径。
source命令:运行source命令可以在当前shell中立即生效已修改的环境变量,不用重启shell。
根据安装成功后提醒,我们执行如下命令:
echo 'export MODULAR_HOME="/root/.modular"' >> ~/.bashrcecho 'export PATH="/root/.modular/pkg/packages.modular.com_mojo/bin:$PATH"' >> ~/.bashrcsource ~/.bashrc
安装完成后需要更新shell配置,然后可以通过mojo命令启动Mojo来使用它提供的各种功能和命令,所有用法可以参考官方文档。
# mojo --versionmojo 0.4.0 (9e33b013)
Mojo Visual Studio Code (VS Code) 扩展 安装
Mojo 通过Visual Studio Marketplace 上的官方扩展直接支持它。这为 Mojo 提供了对许多开发人员生产力功能的支持:
语法高亮诊断和修复定义和参考文献悬停帮助格式化代码完成三、官方hello world
官方文档:https://docs.modular.com/mojo/manual/get-started/hello-world.html
安装Mojo后,您可以使用Mojo CLI来构建和编译Mojo程序。
交互式运行
$ mojoWelcome to Mojo! ?Expressions are delimited by a blank line.Type `:quit` to exit the REPL and `:mojo help` for further assistance.1> print("Hello, world!")2.Hello, world!
构建和运行Mojo源文件
创建一个名为hello.mojo(或hello.?)的文件,并添加以下代码:fn main(): print("Hello, world!")
运行命令 mojo hello.mojo
构建可执行的二进制
使用构建命令创建一个独立的可执行文件:mojo build hello.mojo
它可以创建与.mojo文件相同的名称的可执行文件,但是您可以使用-O选项更改它。
然后运行可执行文件./hello
四、Mojo语言基础
官方文档:https://docs.modular.com/mojo/manual/basics/
https://docs.modular.com/mojo/programming-manual.html
Mojo APIs: https://docs.modular.com/mojo/lib.html
Mojo的一个关键技巧是,作为开发人员,你可以随时选择更快的“模式”,通过使用“fn”而不是“def”来创建你的函数。在这种模式下,您必须声明每个变量的确切类型,因此Mojo可以创建优化的机器码来实现您的函数。此外,如果您使用“struct”而不是“class”,您的属性将被紧密地打包到内存中,这样它们甚至可以在数据结构中使用,而无需跟踪指针。正是这些特性使得像C语言这样的语言变得如此之快,现在它们已经触手可及MLIR是一个关键部分。
Mojo 语言基础知识
官方文档链接:https://docs.modular.com/mojo/manual/basics/
Mojo 是一种功能强大的编程语言,主要为高性能系统编程而设计,因此它与 Rust 和 C++ 等其他系统语言有很多共同点。然而,Mojo 也被设计为成为 Python 的超集,因此您可能从 Python 中了解的许多语言功能和概念都可以很好地转换为 Mojo。
Mojo 保留了 Python 的动态功能和语言语法,甚至允许您从 Python 包导入和运行代码。然而,重要的是,Mojo 是一种全新的语言,而不仅仅是带有语法糖的 Python 的新实现。Mojo 将 Python 语言提升到了一个全新的水平,具有系统编程功能、强大的类型检查、内存安全、下一代编译器技术等等。然而,它仍然被设计为一种对通用编程有用的简单语言。
与其他编译语言一样,Mojo 程序(.mojo或.?文件)需要一个main()函数作为程序的入口点。例如:
fn main(): var x: Int = 1 x += 1 print(x)
如果您了解 Python,您可能会期望函数名称是def main()
而不是fn main()
. 两者实际上都可以在 Mojo 中使用,但使用fn行为略有不同,我们将在下面讨论。
当然,如果您正在构建 Mojo 模块(一个 API 库),而不是 Mojo 程序,那么您的文件不需要函数main()(因为它将被其他具有函数的程序导入)。
现在我们来解释一下这个函数中的代码main()。
语法和语义
这很简单:Mojo 支持(或将支持)所有 Python 的语法和语义。如果您不熟悉 Python 语法,有大量在线资源可以教您。
例如,与 Python 一样,Mojo 使用换行符和缩进来定义代码块(不是大括号),并且 Mojo 支持所有 Python 的控制流语法,例如if
条件和for
循环。
然而,Mojo 仍在开发中,因此 Python 中的一些功能尚未在 Mojo 中实现(请参阅Mojo 路线图)。所有缺失的 Python 功能都会及时到来,但 Mojo 已经包含了许多 Python 之外的特性和功能。
因此,以下部分将重点介绍 Mojo 特有的一些语言功能(与 Python 相比)。
函数
Mojo 函数可以使用fn(如上所示)或def(如 Python 中所示)来声明。该fn声明强制执行强类型和内存安全行为,同时def提供 Python 风格的动态行为。
函数fn、def都有其价值,学习它们很重要。然而,出于本介绍的目的,我们将仅关注fn函数。有关两者的更多详细信息,请参阅编程手册。
在以下部分中,您将了解fn函数如何在代码中强制执行强类型和内存安全行为。
变量
您可以声明变量(例如x在上面的main()函数中)以var
创建可变值,或使用let
创建不可变值。
如果您在上面的函数中更改var
为并运行它,您将收到如下编译器错误:letmain()
error: Expression [15]:7:5: expression must be mutable for in-place operator destination x += 1 ^
这是因为let
使值不可变,因此您无法增加它。
如果完全删除var,则会收到错误,因为fn函数需要显式变量声明(与 Python 风格的def函数不同)。
最后,请注意该x变量具有显式Int类型。fn函数中的变量不需要声明类型,但有时是需要的。如果省略它,Mojo 会推断类型,如下所示:
fn do_math(): let x: Int = 1 let y = 2 print(x + y)do_math()
函数参数和返回值
尽管函数体中声明的变量不需要类型,fn函数的参数和返回值需要类型。
例如,以下是如何声明Int函数参数和返回值的类型:
fn add(x: Int, y: Int) -> Int: return x + yz = add(1, 2)print(z)
结果:
3
您还可以指定参数默认值(也称为可选参数),并使用关键字参数名称传递值。例如:
fn pow(base: Int, exp: Int = 2) -> Int: return base ** exp# Uses default value for `exp`z = pow(3)print(z)# Uses keyword argument names (with order reversed)z = pow(exp=3, base=2)print(z)
结果:
9
8
注意:目前,当函数返回值时,Mojo 总是创建一个副本。
Python集成
官方博客:将 Mojo? 与 Python 结合使用?: https://www.modular.com/blog/using-mojo-with-python
** Mojo 仍在开发中,并且还不是 Python 的完整超集,**但我们已经构建了一种按原样导入 Python 模块的机制,因此您可以立即利用现有的 Python 代码。在底层,该机制使用 CPython 解释器来运行 Python 代码,因此它可以与当今的所有 Python 模块无缝协作。
例如,以下是导入和使用 NumPy 的方法(您必须numpy安装 Python):
from python import Pythonlet np = Python.import_module("numpy")ar = np.arange(15).reshape(3, 5)print(ar)print(ar.shape)
结果:
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]]
(3, 5)
注意: Mojo 还不是功能完整的 Python 超集。因此,您不能总是复制 Python 代码并在 Mojo 中运行它。有关我们计划的更多详细信息,请参阅Mojo 路线图。
五、 探索GitHub 上的示例
官方示例:https://github.com/modularml/mojo/blob/main/examples/matmul.mojo
git clone https://github.com/modularml/mojo.git
cd examples/
官方examples,
其中一个是 矩阵乘法的吞吐量 matmul.mojo
:
# mojo matmul.mojo Throughput of a 128x128 matrix multiplication in Python: 0.001057032915423402 GFLOP/sThroughput of a 512x512 matrix multiplication in Mojo using a naive algorithm: 1.7577817471797681 GFLOP/s <> 1662 x speedup over PythonThroughput of a 512x512 matrix multiplication in Mojo using vectorization: 7.9374030964143198 GFLOP/s <> 7509 x speedup over PythonThroughput of a 512x512 matrix multiplication in Mojo using the stdlib `vectorize`: 8.3545374131911245 GFLOP/s <> 7903 x speedup over PythonThroughput of a 512x512 {vectorized + parallelized} matrix multiplication in Mojo: 11.990951333084553 GFLOP/s <> 11343 x speedup over PythonThroughput of a 512x512 {tiled + vectorized + parallelized} matrix multiplication in Mojo: 10.204954725486481 GFLOP/s <> 9654 x speedup over PythonThroughput of a 512x512 {tiled + unrolled + vectorized + parallelized} matrix multiplication in Mojo: 11.997816185285103 GFLOP/s <> 11350 x speedup over Python
GFLOP/s表示每秒可以执行的十亿次浮点运算数(Giga Floating Point Operations Per Second)。
它是衡量计算机、处理器等执行科学计算和数值计算的计算能力的一种指标。
GFLOP/s越高,表示处理器的计算能力越强,对浮点密集型运算任务(如科学计算、矩阵运算、深度学习等)的处理速度就越快。
这个结果展示了使用Mojo在矩阵乘法运算上相比Python能够获得的显著性能提升。
主要的结果有:
可以看出,Mojo通过语言级的向量化和并行化支持,以及Other optimizations如tiling,可以在矩阵乘法这类计算密集型运算上获得巨大的性能提升。
另外一个example是 Mandelbrot Set(曼徳勃罗特集) matmul.mojo
:
# mojo mandelbrot.mojoNumber of threads: 8Vectorized: 25861.774636999999 msParallelized: 3667.4949320000001 msParallel speedup: 7.0516183707162652
Mandelbrot集计算的结果我们可以做以下分析:
此代码使用了8个线程进行并行计算。仅向量化版本的计算时间是25861ms。添加并行化优化后,计算时间降低到3667ms。并行化使计算加速了7.05倍。从结果可见,仅使用向量化优化就可以明显提升Mandelbrot集的计算速度。
矩阵与矩阵乘积
AI性能优化: 矩阵乘法
参考URL: https://zhuanlan.zhihu.com/p/625016446?utm_id=0
机器学习中需要训练大量数据,涉及大量复杂运算,例如卷积、矩阵等。这些复杂运算不仅多,而且每次计算的数据量很大,如果能针对这些运算进行优化,可以大幅提高性能。
矩阵乘法GEMM(General matrix multiply)是一个被广泛使用的基础算法,也是神经网络的核心计算计算模块,所以矩阵乘法的效率优化是深度神经网络性能性能的关键,在现代CPU上最朴素的矩阵乘法实现和最优实现最高可以达到几十倍以上的性能差距。在CPU上针对矩阵的优化需要结合CPU体系结构特性,SIMD向量指令,Cache特性等特性以及多核并行计算进行针对性的设计和优化。
Mandelbrot集
Mandelbrot Set(曼德勃罗集),是由美国数学家Mandelbrot教授发现的。生成的方式来自于一个简单的迭代公式:z(n+1) = z(n)^2 + c。其中,z是一个复数(可表示为z = a + bi)。所有使得无限迭代后的结果能保持有限数值的复数z的集合(也称该迭代函数的Julia集)连通的c,构成曼德勃罗集。
最简单的生成曼德勃罗集图案的算法是“escape time”(逃逸时间)算法。其基本思路是:对于平面中的初始位置(x, y),不断进行迭代。每次结果作为下次迭代的初始值。当满足某种条件时,视为“逃逸”发生,并记录下迭代的次数。对处于Mandelbrot集中的点来说,永远不可能发生“逃逸”。所以需要设定一个最大迭代次数,当达到这个迭代次数还没有发生“逃逸”的点,我们就认为它是曼德勃罗集中的点。 作者:独孤嘌呤 https://www.bilibili.com/read/cv18823632/ 出处:bilibili