Mojo中低水平的IR介绍

devtools/2024/10/18 8:23:47/

Mojo是一种具有广泛现代功能的高级编程语言。Mojo还为程序员提供了访问所有底层原语的机会,以便编写强大而零成本的抽象。

这些原语用MLIR实现,MLIR是一种用于编译器设计的可扩展中间表示格式。许多不同的编程语言和编译器将它们的源程序翻译成MLIR,因为Mojo提供了直接访问MLIR特性的途径,这意味着Mojo程序可以享受这些工具带来的好处。

更进一步,Mojo独特的零成本抽象与MLIR互操作性的组合意味着Mojo程序可以充分利用任何与MLIR接口的东西。虽然这不是普通的Mojo程序员可能需要做的事情,但当扩展系统以与新数据类型接口或深奥的新加速器功能时,这是一个非常强大的功能。

为了说明这些想法,我们将在下面的Mojo中实现一个布尔类型,我们称之为OurBool。我们将广泛使用MLIR,所以让我们从一个简短的入门介绍开始。

What is MLIR?


MLIR是一种程序的中间表示,与汇编语言类似,在汇编语言中,一组顺序的指令操作于内存中的值。

更重要的是,MLIR是模块化和可扩展的。MLIR由越来越多的“方言”组成。每个方言都定义了操作和优化:例如,math方言提供了数学操作,如正弦和余弦,amdgpu方言提供了特定于AMD处理器的操作,等等。

MLIR的每种方言都可以与其他方言互操作。这就是为什么说MLIR可以解锁异构计算:随着更新、更快的处理器和体系结构的开发,新的MLIR方言被实现,以为这些环境生成最佳代码。任何新的MLIR方言都可以无缝翻译为其他方言,因此随着更多的添加,所有现有的MLIR变得更加强大。

这意味着我们自己的自定义类型,例如我们将在下面创建的OurBool类型,可以用来为程序员提供一个高级的、类似python的接口。但在“表面之下”,Mojo和MLIR将为未来出现的每个新处理器优化我们的方便、高级类型。

关于为什么MLIR是一项革命性的技术还有很多可以写,但让我们回到Mojo和定义OurBool类型。在这个过程中,我们将有机会了解更多关于MLIR的知识。

Defining the OurBool type


我们可以使用Mojo的struct关键字来定义一个新类型OurBool:

struct OurBool:var value: __mlir_type.i1

布尔值可以表示0或1,“true”或“false”。为了存储这些信息,OurBool有一个成员,称为value。它的类型直接在MLIR中表示,使用MLIR内置类型i1。事实上,在Mojo中可以使用任何MLIR类型,只要在类型名称前加上__mlir_type即可。

正如我们将在下面看到的,用i1表示我们的布尔值将允许我们利用与i1类型接口的所有MLIR操作和优化——它们有很多!

定义了OurBool之后,我们现在可以声明这种类型的变量:

fn uninitialized_our_bool():var a: OurBool

Leveraging MLIR


当然,我们接下来可能会尝试创建一个OurBool实例。然而,此时尝试这样做会导致错误:

var a = OurBool() # error: 'OurBool' does not implement an '__init__' method

与在Python中一样,__init__是一个特殊方法,可以定义它来自定义类型的行为。我们可以实现一个没有参数的__init__方法,并返回一个带有“false”值的OurBool。

struct OurBool:var value: __mlir_type.i1fn __init__(inout self):self.value = __mlir_op.`index.bool.constant`[value=__mlir_attr.false,]()

为了初始化基础的i1值,我们使用来自其index方言的MLIR操作,称为index. boolean .constant。

MLIR的index方言为我们提供了操作内置MLIR类型的操作,例如我们用来存储OurBool值的i1。index. boolean .constant操作接受一个编译时常量true或false作为输入,并在运行时生成一个i1类型的输出。

因此,如上所示,除了任何MLIR类型之外,Mojo还通过__mlir_op前缀直接访问任何MLIR操作,通过__mlir_attr前缀直接访问任何属性。MLIR属性用于表示编译时常量。

正如你在上面看到的,与MLIR交互的语法并不总是那么漂亮:MLIR属性在方括号之间传递[…],操作通过后缀(…)的括号执行,它可以接受运行时参数值。然而,大多数Mojo程序员不需要直接访问MLIR,对于少数需要访问的人来说,这种“丑陋”的语法给了他们超能力:他们可以定义易于使用的高级类型,但在内部插入MLIR及其强大的方言系统。

我们认为这非常令人兴奋,但让我们回到现实:定义了__init__方法后,我们现在可以创建OurBool类型的实例:

var b = OurBool(

http://www.ppmy.cn/devtools/93966.html

相关文章

高性能并行计算面试-核心概念-问题理解

目录 1.什么是并行计算?高性能从哪些方面体现? 2.CPU常见的并行技术 3.GPU并行 4.并发与并行 5.常见的并行计算模型 6.如何评估并行程序的性能? 7.描述Am达尔定律和Gustafson定律,并解释它们对并行计算性能的影响 8.并行计…

设计模式(1)创建型模式和结构型模式

1、目标 本文的主要目标是学习创建型模式和结构型模式,并分别代码实现每种设计模式 2、创建型模式 2.1 单例模式(singleton) 单例模式是创建一个对象保证只有这个类的唯一实例,单例模式分为饿汉式和懒汉式,饿汉式是…

Linux下 vim的用法

目录 前言 一、初始Vim 二、使用Vim 1.1命令模式 2.1底行模式 3.1插入模式 前言 提示:这里可以添加本文要记录的大概内容: 本篇文章会介绍vim的基本用法和为什么我们要学习vim。 提示:以下是本篇文章正文内容,下面案例可供…

【JAVA】LinkedList 详解

LinkedList LinkedList 是一种常见的数据结构,它由一组节点组成,每个节点包含一个数据元素和一个指向下一个节点的指针。与数组不同,LinkedList 中的元素在内存中并不是连续存储的,而是通过指针链接在一起的。这使得 LinkedList …

redis面试(十三)公平锁排队代码剖析

我们来看一下第二种redis分布式锁 第一种锁是可重入锁,非公平可重入锁,所谓的非公平可重入锁是什么意思呢?胡乱的争抢,根本没有任何公平性和顺序性可言 第二种锁,可重入锁,公平锁 通过公平锁&#xff0c…

一篇文章教会你如何使用Haproxy,内含大量实战案例

1. Haproxy 介绍 HAProxy是法国开发者 威利塔罗(Willy Tarreau) 使用C语言编写的自由及开放源代码软件,是一款具备高并发(万级以上)、高性能的TCP和HTTP应用程序代理. HAProxy运行在当前的硬件上,可以支持…

使用Cisco软件进行模拟万维网配置访问服务器过程

万维网(www)实验 文章目录 万维网(www)实验1.实验目的2.实验流程3.实验步骤 1.实验目的 1)理解www站点 2)理解上层应用和下层通信网络的关系 2.实验流程 开始 → 布置拓扑 → 配置路由及IP地址 → 配置web服务器→ 访问服务器 →结束 3.实验步骤 1&…

【K8S】K8S架构及相关组件

文章目录 1 K8S总体架构2 相关组件2.1 控制面板组件2.2 节点组件2.3 附加组件 写在最后 1 K8S总体架构 K8S,全称Kubernetes,是一个开源的容器部署和管理平台,由Google开发,后捐献给云原生计算基金会(CNCF)…