[toc]
前言
作为这俩年最火的行业,AI无出其右,AI编程的代表性语言主要使Python、C/C++。Python因其简单易学、丰富的库支持和强大的社区力量,在AI领域占据了主导地位。Python不仅能够作为“胶水”语言与其他语言互操作,还提供了大量的工具库,极大地扩展了其应用范围和能力。C/C++则因其高性能和对硬件的直接访问能力,在深度学习和科学计算等需要高性能计算的任务中被广泛应用。C/C++是许多底层算法库的实现语言。然而,随着AI技术的发展,传统的编程语言在满足现代AI应用的需求时显得力不从心。这些语言往往不原生支持张量操作和并行计算,也不容易适应多样化的硬件环境。Mojo 就是在这样的背景下,Mojo是Modular 创造的第一个专门为 MLIR设计的主要语言,主要是解决在构建平台来统一全球 ML/AI 基础设施时,整个堆栈的编程过于复杂的问题。创造出来的一种新的且可扩展的编程模型,可以针对人工智能领域普遍存在的加速器和其他异构系统,专门为 MLIR设计的主要语言,这使得 Mojo 在为 AI 工作负载编写系统级代码时具有独特的强大功能。
一、Mojo简介
Mojo 是第一个使用 MLIR(一种编译器基础设施,非常适合从 CPU 和 GPU 到各种 AI ASIC 的异构硬件)从头开始构建的编程语言。Modular 将 Mojo 设计为 Python 的超集,那么Mojo到底是一门什么样的语言呢?Mojo官网是这样介绍的,截图如下:
我给大家翻译过来就是:Mojo是一门专门为AI开发者提供的编程语言,将 Python 的可用性与 C 的性能相结合,解锁了 AI 硬件无与伦比的可编程性和 AI 模型的可扩展性。
Mojo指导文档是这样介绍的,截图如下:
翻译过来就是:Mojo 是一种新的编程语言,它通过将最好的 Python 语法与系统编程和元编程相结合,弥合了研究和生产之间的差距。使用 Mojo,您可以编写比 C 更快的可移植代码,并与 Python 生态系统无缝互操作。
通过Mojo官网的介绍,我们大致可以了解到如下信息:
1.它可以编写比C更快的可移植代码,据称比Python快35000倍。
2.它可以与Python生态系统无缝互操作,支持Python的核心功能,如异步/等待、错误处理和可变参数。
简单来事,就是Python语言和C语言,不管在性能还是通用型方面,都可以完全碾压二者,从此开发人员再也不用频繁的学习各种各样的语言了,真正做到了Mojo在手,妈妈再也不用担心我的工作了。不过玩笑归玩笑,Mojo能说出这样的话,也是有其实力的,毕竟谁也不会搬起石头砸自己的脚,更何况他搬起的不是石头,二是Python和C这么俩座石山。下面让我们继续深入学习Mojo,解开心中的疑惑。
五、Mojo优势
1.兼容Python语法 :Mojo完全兼容 Python 语法,Python开发者可以轻松上手,不需要再花大力气学习一门新的语言。
2.兼容Python 库:兼容很多现有的Python科学计算库,比如。
3.卓越的性能:比 Python 快 35000 倍。
4.单一语言写作:无需单独掌握C++或Python;仅使用 Mojo 执行这两种功能,正真做到了一鱼俩吃。
5.并行处理:Mojo 使用 MLIR 在专用 AI 硬件单元上进行矢量化、线程化处理。
6.模型更容易扩展:升级模型比以往任何时候都容易。
六、Mojo功能介绍
1.函数
Mojo 支持两种类型的函数:def
和fn
函数。您可以将任一声明与任何函数(包括该main()
函数)一起使用,但它们具有不同的默认行为。
1)def功能
该def
函数提供与 Python def
函数相同的动态性和灵活性。例如,此函数在 Python 和 Mojo 中的工作方式相同:
def greet(name):
greeting = "Hello, " + name + "!"
return greeting
在 Mojo 中,您还可以选择指定参数类型和返回类型。您还可以使用var
、带或不带显式类型来声明变量。
def greet(name: String) -> String:
var greeting = "Hello, " + name + "!"
return greeting
这样,编译器可以确保它name
是一个字符串,并且返回类型也是一个字符串。
2)fn功能
该fn
函数提供严格的类型检查和额外的内存安全性。它基本上强制您在 中写入可选的内容def
,并确保您不会意外地改变收到的参数。例如,下面是与上面相同的函数,使用fn
:
fn greet(name: String) -> String:
var greeting = "Hello, " + name + "!"
return greeting
就函数调用者而言,def
函数fn
是可以互换的。也就是说,没有什么是def
可以做的fn
(反之亦然)。不同的是,与def
函数相比,fn
函数内部更加严格。
2.变量
变量是保存值或对象的名称。 Mojo 中的所有变量都是可变的——它们的值可以改变。
1)未声明的变量
在def
函数或 REPL 环境中,您可以创建仅包含名称和值的变量。例如:
name = "Sam"
声明的变量没有var
跟随 s
2)声明的变量
您可以使用关键字声明变量var
。例如:
var name = "Sam"
var user_id: Int
该name
变量被初始化为字符串“Sam”。该user_id
变量未初始化,但它具有声明的类型Int
(整数值)。所有声明的值都是类型化的——要么使用 类型注释显式地定义,要么在使用值初始化时隐式地定义。
由于声明的变量是强类型的,因此您不能为变量分配不同类型的值,除非这些类型可以 隐式转换。例如,以下代码将无法编译:
var user_id: Int = "Sam"
3.结构体
Mojo 结构是一种数据结构,允许您封装对抽象(例如数据类型或对象)进行操作的字段和方法。 字段是保存与结构相关的数据的变量,方法 是结构内部的函数,通常作用于字段数据。
例如,如果您正在构建图形程序,则可以使用结构体来定义 struct,Image
该结构体具有用于存储有关每个图像(例如像素)的信息的字段以及对其执行操作(例如旋转图像)的方法。
大多数情况下,Mojo 的结构格式旨在为程序中使用的高级数据类型提供静态、内存安全的数据结构。例如,Mojo 标准库中的所有数据类型(例如Int
、 Bool
、String
和Tuple
)都被定义为结构体。
1)结构体定义
您可以定义一个MyPair
带有两个字段的简单结构体,如下所示:
struct MyPair:
var first: Int
var second: Int
但是,您无法实例化此结构,因为它没有构造函数方法。所以这里用一个构造函数来初始化这两个字段:
struct MyPair:
var first: Int
var second: Int
fn __init__(inout self, first: Int, second: Int):
self.first = first
self.second = second
请注意,该方法中的第一个参数__init__()
是inout self
。现在,忽略inout
(这是一个参数约定,声明self
是一个可变引用);您现在需要知道的是这 self
必须是第一个参数。它引用当前的结构实例(它允许方法中的代码引用“自身”)。当你调用构造函数时,你永远不会传递一个值self
——Mojo会自动传递它。
2)结构体对象创建
一旦有了构造函数,您就可以创建一个实例MyPair
并设置字段:
var mine = MyPair(2,4)
print(mine.first)
4.模块和包
Mojo 提供了一个打包系统,允许您组织代码库并将其编译为可导入的文件。本页介绍了有关如何将代码组织成模块和包(这很像 Python)的必要概念,并向您展示如何使用命令创建打包的二进制文件mojo package
。
要了解 Mojo 包,您首先需要了解 Mojo 模块。 Mojo 模块是单个 Mojo 源文件,其中包含适合导入它的其他文件使用的代码。例如,您可以创建一个模块来定义如下所示的结构:
struct MyPair:
var first: Int
var second: Int
fn __init__(inout self, first: Int, second: Int):
self.first = first
self.second = second
fn dump(self):
print(self.first, self.second)
请注意,这段代码没有任何main()
功能,因此无法执行 mymodule.mojo
。但是,您可以将其导入到另一个具有函数的文件中 main()
并在那里使用它。
例如,以下是如何导入MyPair
名为 的文件,main.mojo
该文件与 位于同一目录中mymodule.mojo
:
from mymodule import MyPair
fn main():
var mine = MyPair(2, 4)
mine.dump()
或者,您可以导入整个模块,然后通过模块名称访问其成员。例如:
import mymodule
fn main():
var mine = mymodule.MyPair(2, 4)
mine.dump()
您还可以使用 为导入的成员创建别名as
,如下所示:
import mymodule as my
fn main():
var mine = my.MyPair(2, 4)
mine.dump()
在此示例中,仅当mymodule.mojo
与 位于同一目录中 时才有效main.mojo
。目前,.mojo
如果文件驻留在其他目录中,则无法将它们作为模块导入。
六、Mojo牛刀小试
1.Mojo安装
Mojo SDK 目前可用于在 Apple 芯片上运行的 Ubuntu Linux 系统和 macOS 系统。对 Windows 的支持即将推出。Mojo SDK 包含本地 Mojo 开发所需的一切,包括 Mojo 标准库和Mojo 命令行界面 (CLI)。 Mojo CLI可以启动REPL编程环境、编译和运行Mojo源文件、格式化源文件等。
我们还发布了Visual Studio Code 的 Mojo 扩展, 以提供一流的开发人员体验,包括代码完成、快速修复和 Mojo API 的悬停帮助等功能。
1.打开终端并安装modular
命令行工具:
curl -s https://get.modular.com | sh -
2.然后使用以下命令登录您的模块化帐户:
modular auth
3.现在您可以安装 Mojo SDK:
modular install mojo
4.设置环境变量以便您可以访问 mojo
CLI,如果您使用的是 Bash,请运行以下命令:
MOJO_PATH=$(modular config mojo.path) \
&& BASHRC=$( [ -f "$HOME/.bash_profile" ] && echo "$HOME/.bash_profile" || echo "$HOME/.bashrc" ) \
&& echo 'export MODULAR_HOME="'$HOME'/.modular"' >> "$BASHRC" \
&& echo 'export PATH="'$MOJO_PATH'/bin:$PATH"' >> "$BASHRC" \
&& source "$BASHRC"
2.Mojo使用
安装 MAX SDK或 Mojo SDK后,您可以使用 Mojo CLI来构建和运行 Mojo 程序。因此,让我们创建一个经典的入门程序,以三种不同的方式打印“Hello, world!”。
在开始之前,请确保按照安装过程中所述设置MODULAR_HOME
和环境变量,以便您可以运行以下 命令:PATH``mojo
mojo --version
首先,让我们使用 Mojo REPL,它允许您在命令提示符下编写和运行 Mojo 代码:
- 要启动 REPL 会话,请
mojo
在终端中输入并按Enter。 - 然后键入
print("Hello, world!")
并按Enter两次(需要一个空行来指示表达式的结尾)。
就是这样!例如:
$ mojo
Welcome to Mojo! 🔥
Expressions are delimited by a blank line.
Type `:quit` to exit the REPL and `:mojo help repl` for further assistance.
1> print("Hello, world!")
2.
Hello, world!
您可以在 REPL 中编写任意数量的代码。您可以按Enter开始新行并继续编写代码,当您希望 Mojo 评估代码时,按Enter两次。如果有需要打印的内容,Mojo 会打印它,然后将提示返回给您。
现在让我们在 Mojo 源文件中编写代码并使用以下 mojo
命令运行它:
1.hello.mojo
创建一个名为(或)的文件hello.🔥
并添加以下代码:
fn main():
print("Hello, world!")
这就是你所需要的。保存文件并返回到您的终端。
现在使用以下命令运行它mojo
:
mojo hello.mojo
它应该立即打印消息:
Hello, world!
小节
请注意,Mojo 仍然是一种非常年轻的语言,所以还有很多东西还没有建立起来。同样,还有很多文档还没有写出来。但我们很高兴能与您分享 Mojo 并获得您的反馈。
虽然Mojo作为一种为AI / ML量身定制的快速,与Python兼容的语言显示出前景,但它不太可能在不久的将来完全取代Python。Python 受益于庞大的生态系统、社区以及数据科学和 ML 领域的根深蒂固。充其量,Mojo可能会成为Python的补充语言,用于速度至关重要的地方。