爱笑的小姐姐 · 2023年03月23日 · 北京市

AIOT时代的编程语言、编译器与指令集架构:机遇、挑战与技术分享

本次分享来自遇见未来系列讲座——与曾建江老师探讨AIOT时代的编程语言、编译器与指令集架构:机遇、挑战与展望。编译器、编程语言以及指令集架构都是一个软件生态的根基,此次给大家介绍软件生态根基上的语言编译器以及指令集架构,有哪些机遇挑战以及一些最新的技术课题。

趋势与挑战

1 处理器发展趋势

软件都是在处理器上执行的,首先我们看下处理器的发展。下图[1]统计了从70年代中期开始到2018年,执行软件的微处理器的发展趋势。它从几个维度统计了这些处理器的发展:

image.png

1. 晶体管的数量(橙色所示):依据40多年前提出的摩尔定律,晶体管数量一直在提升。此外2018年业界发布了一个很有意思的芯片——Cerebras的芯片,该芯片晶体管数量远远超出这个趋势图里面的范畴,是一个非常惊人的数字:1.2万亿个晶体管(当然这不是商用上非常经济的设计)。但是可以看到在用来运行软件的处理器中,所包含晶体管的数量还是持续追随着摩尔定律在增长。

2. 单线程(单核)的性能(蓝色所示):这里的单核性能指的是当前单核能够提供的整数计算性能。从40年前开始,性能几乎还是能够沿着摩尔定律的发展而持续地提升。但是从21世纪特别是21世纪10年代开始,单核性能的发展几乎停滞了,或者说是发展缓慢。发展缓慢意味着用来运行软件的单个处理器的性能提升,从10年前开始就是非常有限的。

3. 频率(绿色所示):频率的趋势更加平缓,从2000年开始,就没有跟随摩尔定律,这里有工艺限制的因素,很大原因是物理实现上的限制。频率的走缓几乎是更早于性能的走缓。这里蓝色性能和绿色频率的差别意味着芯片开发者或者架构开发者做出了非常大的努力,让处理器在频率不增长的情况下,能够持续地为软件性能提升提供贡献,这是非常不容易的一件事情。

4. 处理器的功耗(红色所示):几乎从2000年开始,处理器功耗就不再大规模增长了。这里有个非常重要的原因是芯片的物理分装有相应的物理限制,从单位的物理分装里能够散发出来的热量是有限的。据统计,按照能量密度来算,处理器上运行软件所耗费的能量,能量密度已经超过了核反应堆。这是一个非常惊人的情况,所以从功耗上来说,微处理器能够耗散的功耗,已经达到了目前工艺或者说现在生产的极限。明显从很早开始,电池以及功耗就开始限制我们微处理器的发展。

5. 处理器核数(黑色所示):处理器核数的增长从05年左右开始,跟随着摩尔定律中晶体管数量的逐步增长,单个芯片上所集成的处理器核数变得越来越多,几乎是和晶体管数量同步的发展趋势,意味着未来所使用的芯片里集成的核会更多。那这些核是不是都在做一个有意义的事情?下面我们来看下这些核本身的形态是怎样发展的。

有个论断[2]是通用计算的时代结束了,回顾我们刚才讲的趋势,从2000年初开始,性能提升已经开始逐步走缓。如何获取更多的性能,这里有一个非常重要的趋势,就是处理器在变得越来越专用,专用是指如何进行处理器的定制化以及专用化的设计,通过对计算本身并行的特征,以及它的访存内存使用的特征,来发掘计算的模式里是否有利用定制化的硬件,来提升特定模式计算的性能,或者是降低所使用的功耗的手段,这种叫做定制化。

最典型的例子是现在非常热的AI处理器,比如现在华为手机里集成的达芬奇 AI芯片,就是定制化的设计。为了让应用跑得更快,现在采取了更多的手段。如下图所示,蓝色这块区域就是用定制化的设计来提升应用的性能,降低完成计算所需要的功耗。

image.png

2 指令集架构的演进

实现定制化,这里又回到处理器,用来实现软件或者运行软件非常重要的软件和硬件的接口,叫做指令集。如下图所示,这是一个比较传统的指令集的分类。指令集从60年代的复杂指令集(Complex Instruction Set Computer, CISC)开始发展,到70年代有了精简指令集(reduced instruction set computer, RISC)的分类。一直到80年代开始,业界开始探索一种称为超长指令集(Very Long Instruction Word,VLIW)的指令级并行架构。90年代时还有非常多不同种类的指令集存在。

image.png

但随着时间的演变,到今天为止,市面上现在主流用到的指令集已经不多了,非常多指令集已停止发展。留在市面上的还有一些特定领域的大型机的指令集。通用指令集领域的话,有Intel X86指令集、IBM power指令集和SPARC指令集。但是手机上主要是用ARM 指令集,还有最近比较热的RISC-V 指令集,可数的就这几种。指令集在处理器发展上所起到的最重要的作用,就是让软件和硬件实现他们的界面以及交互。现存的通用指令集有这样的趋势:这些不同的指令集,会相互借鉴、相互汲取各自设计上的优点。举个例子,Intel X86指令集,虽然是一个复杂指令集的设计,但是一些具体指令汲取了很多RISC的设计概念,包括它内部的实现,借用了一些 RISC指令集的设计理念;IBM Power指令集,照说它应该是一个精简指令集的架构,但随着 Power指令集的逐步发展,内部也引入了指令组合的概念。指令组合从逻辑上来看,其设计思想与超长指令集VLIW有些接近,思路上是相通的。一直到今天为止,现在市面上能够用到的指令集,虽然还是各自有多样化,但是种类已经减少了,此外它的设计也不再严格区分复杂指令集、精简指令集以及超长指令集,有相互借鉴发展的趋势。

3 处理器架构与编译技术的演进

为了让软件能够变成用指令集描述的指令序列,编译器在此过程中起到了非常关键的作用。随着架构的发展,我们来看下编译器和架构是怎样的演进路径。

image.png

2000年以前,大部分处理器都是单核的,所以当时单核优化是编译器以及编译技术的重点。面向不同的指令集,编译技术也在不停演进及发展,比如说循环优化、指针分析、数据重组,面向单核的编译优化等是在该时期发展的。可以看到,编译器本身的优化,是和处理器的实现紧密相关的。

随着多核处理器的发展(如果大家还记得前面多核处理器的发展趋势是从2000年到2010年中开始的),编译优化逐渐转向了多核优化的方向。多核处理器中,芯片的性价比(performance/dollar)是一个非常重要的衡量指标。也就是说当单核性能提升到了一定程度时,不得不通过多核来提升整个芯片的性能,然后让软件通过多核架构来获取更进一步的性能提升。到10年代中期,多核的优化又变成了重点。随着技术的持续发展,2010年以后性能提升逐步走向异构的优化(或者叫做超异构的优化)。和多核不同,异构的多核就是处理器的形态从通用的CPU转向了GPU以及现在的AI芯片这样专用的设计。前面也提到了一个趋势是说通用计算的时代已经结束了,现在已经处于异构计算(或者定制化计算)的时代。在这个时代,处理器的形态非常多:DSP、GPU、AI, 甚至于FPGA,像这样不同种类的核在一个系统里协同工作,对整个系统开发或者系统的架构也产生了非常大的挑战。

4 超异构时代软件开发趋势

对于编译优化,问题是这么多不同指令的软件,如何在一个系统里进行协作,让它们能够把整个系统的晶体管利用起来,来做有意义的(或者说是有效的)计算。进一步来看,在现在的异构以及超异构架构时代(或者说是后摩尔时代)整个芯片架构走向异构,快速演进的芯片和高复杂度的应用,对软件开发效率以及兼容性提出了前所未有的挑战。业界提到现在是软件灾难(software disaster)的时代:因为有这么多核,怎样让一份软件能够在不同芯片上运行起来。David Patterson与John Hennessy指出“The easy ride of software is over”:在异构计算时代,想要完全释放出异构芯片的计算能力,程序员必须既懂上层应用算法,又懂底层硬件模型,才能写出高效高质量代码,未来的编程工作会比现在更复杂。

业界趋势

下图[3]显示了过去40年来的处理器性能。按照目前的速度,标准处理器基准测试的性能在2038年之前不会翻一番。

image.png

1. 不同领域的计算需要越来越多的异构资源。我们举个例子,现在的天河-2(这是一个大型机的例子)里面集成了intel Phi 芯片,也有通用的处理器。此外还有GPU的集群,在GPU集群里也集成了大量GPU核,但CPU的软件是不能够运行在GPU上的,如何让这两者协同起来,就是一个非常巨大的挑战。

2. 出现面向特定领域定制的体系结构(DSA)。这里再给大家介绍下TPU,TPU是谷歌推出的针对AI计算的处理器,该处理单元于2015年首次部署,目前为超过10亿人提供服务。它运行深度神经网络(DNN)的速度是类似技术中当代CPU和GPU的15到30倍,能效是当代CPU和GPU的30到80倍,该处理器使用的是自己的指令集。我们现在所在的超异构时代是针对领域定制的架构,也就是说在超异构时代,异构走向了根据领域定制的趋势,不再是仅有CPU和GPU甚至于以后的XPU(X PU指该处理器定制设计用途未知)。

image.png

开发者痛点

从软件开发者角度来看,软件如何为这么多的处理器架构开发,有几个问题是容易遇到的。

1. 开发效率问题

不同的处理器其实是有自己的开发技巧的,比如DSP有DSP的优化技巧,GPU有GPU的优化套路,FPGA有自己专用的开发语言。普通开发者在上层应用算法和底层硬件模型无法做到两者皆懂,无法利用芯片能力实现程序性能的提升。如何让这些软件高效地为不同处理器架构进行开发,这是软件开发者需要解决或面对的问题。此外,目前缺乏有效的轻量化实时编译方案,无法做到运行时代码生成。

2. 兼容性问题

a) 异构处理器核之间的兼容性:怎么理解呢?就是我写一份软件,这款软件是否可以跑在其他不同的处理器上。如果这个程序下载了或完成开发以后,可以不经过任何修改,直接一份可执行的程序就可以在不同的处理器上运行,这就是二进制的兼容。二进制的兼容性在异构处理器时代非常难,芯片快速演进,开发者针对多芯片需要多次开发,代码移植成本很高。

b) 源代码的兼容性:在当前时代里,源码兼容性是一个非常大的挑战。体系结构层出不穷,开发者无法通过DSL语言,快速适配多形态芯片进行迭代式开发。举个例子,英伟达GPU的开发,通用GPU的计算开发是使用专用的OpenCL编程语言来进行的。针对不同的GPU,虽然能够用同一种编程语言完成针对不同GPU的软件开发,但是并不能够保证在不同的GPU上性能都是一致的、都是最高的。

这就导致了软件在进行移植时,在不能保证二进制兼容性的情况下,能够保证代码的兼容性。但是如果保证了代码的兼容性,对性能的可移植性又不能够满足,所以在这个过程当中,软件移植的成本是非常高的。这也是当前超异构时代软件编程一个非常重要的问题。

这里总结一下就是产能Productivity、性能Performance、可移植性Portability的3P问题。

超异构时代软件开发趋势

如何解决3P问题(Productivity、Performance、Portability),支撑快速演进的芯片可编程性和解决软件兼容性问题,助力开发者实现高质量快速编程,降低代码迁移成本,下面介绍从开发者视角看到的如何对现在超异构时代软件进行开发的趋势(并不是解决方案)。

1. 声明式开发:所见即所得的交互式编程。

针对普通的应用开发,比如现在手机上比较热门的APP开发,有声明式开发的趋势,那这里的趋势是什么样的?针对手机这种界面型的开发,有一种称为所见即所得的交互式编程。所见即所得这个词原来是用在文本编辑里面的,大家经常使用Word的话,应该知道Word中你在屏幕上打出来是什么样的字,在打印机上打印出来就是什么样。这就叫做所见即所得的文本编辑。这里所见即所得的交互式编程是指:手机终端的应用开发者,在写代码的时候就能够在当前环境内直接看到它未来应用所呈现的样子。比如苹果公司基于SwiftUI开发的AppKit、UIKit、TVUIKit、WatchKit。“UI即代码、代码即UI”的可视化编程理念一直是一种趋势,提供新UI开发机制,所见即所得的实时预览、多端预览、提升UI开发体验和效率是声明式开发的关键挑战。

image.png

2. 协同式开发:多人协作/端云协同编程。

我们认为未来这会是一个比较重要的趋势,所谓协同式开发是和现在软件工程规模非常相关的一个问题。在一个小的软件项目里,可能有5-10位开发者,但是大规模的软件开发,经常有上百个开发者在同一个项目里开发,这时对软件开发提出非常大的挑战:如何让这么大规模的团队同时高效地开发,避免冲突?不同于结对编程,协同式开发使开发者能一起工作,同时保留多人信息,并与他人实时协作编辑和调试,提供新开发模式,即时安全共享项目,联合调试,实现多设备体验一致是协同式开发的关键挑战。

image.png

3. 智慧化开发:AI辅助编程/AI可视化编程。

把重复的劳动交给工具,让开发者专注于逻辑、业务的编写,智能化编程应用而生。智慧化开发的意思是在写代码时会有一些代码提示。原来传统的IDE所实现的代码提示是一种代码逻辑的提示。未来在异构时代,有一个很重要的问题:我们所写的代码对性能会有什么样的影响?传统的开发过程是很难在写代码的时候界面就给出一些性能的预估。未来通过智慧化编程,开发者在代码开发过程当中就能够看到代码的性能预估以及潜力。此外在安全方面,如果代码有一些安全漏洞,在软件开发前期就能解决。面向新创新场景,解决软件工程效率问题和AI编程领域可视化调试和性能分析问题是智慧化编程的关键挑战。

image.png

产业案例

接下来通过编译器和编程语言在昇腾产品里的应用案例给大家介绍下,现在编译器和编程语言技术是如何在产品中发挥作用。

2019年9月18日HC2019,副董事长胡厚崑宣布,AI基础软件59.8s完成ResNet-50@imageNet模型训练,超越原世界纪录10s,并现场展示基于MindSpore实现10.02s内20万天体识别,成功发布全球最快的AI训练集群Atlas 900。为了实现这样的世界纪录,编译器在其中贡献了一些非常关键的技术。

image.png

1. Super Kernel优化技术:在二进制层面实现算子Kernel融合调度,最大化减少TS调度Kernel开销,Resnet50训练E2E性能提升2~3s,助力整体性能突破60s。该技术所解决的是编译性能(应用软件最终编译出来的软件的性能)问题。这对于编译(最终的软件)来说是非常关键的。如果没有该技术,软件所运行的速度突破60秒还是一个非常大的问题。

2. 并行编译、ccache优化(Compiler cache的优化):库上CCE算子构建时间从15min+降到4min,提升构建速度3倍。该技术从编译的角度来看,解决的是编译时间的问题:如何把需要编译构建的软件尽快编译出来。从开发的视角来看,大家都不愿意写了一行代码然后要花一小时进行编译。但有时候因为软件上的依赖关系,如果是在非常底层的代码里进行了一次改动,有可能会需要把整个工程进行重构。这个时候,全工程的全量重构的时间就会非常影响开发效率,上述提到的技术就是用于解决这样的开发效率问题。

3. 算子优化编译和代码生成:突破循环优化、同步算法、内存复用、多核多batch等优化技术,数量级提升TBE算子性能,TBE成为D算子开发的统一框架。这也是用于解决性能问题。

在整个昇腾的案例里面,希望大家记住的是两点:编译在这里解决的,第一个是性能的问题,第二个是开发时间/编译时间的问题。

技术案例互动分享

到这里大家可能会好奇:像这样的编译技术是如何来实现的?接下来就通过一些技术的案例分享给大家讲解。

1 编译器和编程语言的设计和实现中关注的问题

深入到具体单点技术之前,先来看下编译器和编程语言的设计和实现中关注的问题。

设计中主要关注如下三点:

1. 表达力强

现在C的编译器可能很少,C语言应该是底层还在使用。我想本科有可能还会教授C语言编程这门课,但是 AI领域已经进入到大量使用Python语言的阶段。为什么呢?这里有一个很重要的问题,在上层语言中,Python语言对于AI领域的表达能力是比C语言更强的。也就是说在进行编程语言的设计或实现时,会想如何更加容易地描述计算或应用业务的逻辑。只有非常容易描述这些计算以及业务的逻辑,开发者才能够更加高效地把想实现的功能描述出来。

2. 容易使用

在语言层面,当你想用一个语言来进行表达的时候,语言好学与否,也是需要考虑的一个非常重要的问题。如何让语言变得更加容易使用:好学、好写、好读,还有不容易出错。

3. 不易出错、代码安全

不容易出错也是在语言设计上非常重要的一个考量,在设计一门语言时,需要注意这个语言是否会让开发者写出一个错误的逻辑,在这点上有可能一些早期的语言做的不是很好,但是新的这些语言在不易出错这个功能上会考虑的更多一些。因为在现在这个万物互联的时代有太多的程序要写,如果很容易出错,程序员会觉得用这个语言太麻烦。然后现在在很多设备的编程上,代码安全也是非常重要的考量,这等于说是在进行软件开发时,使用的语言会有很多的考量,那在实现的过程当中,编译器就是把语言实现,让芯片能够看懂并且执行的工具。

而在实现中,为了让芯片看懂并执行,需要关注如下三点:

首先是上述商用产品案例中关注的两个问题:一个是性能问题,如何通过编译,让软件运行时间尽可能短。另一个是占用资源少的问题,占用资源少的话可以省出空间资源,编译出来的软件不要太大,比如大家不希望自己下载一个小小的记事本软件,就要占用整个手机的存储空间。在这个过程当中编译器所要完成的目标就是让编译出来的程序越小越好,占用的资源越少越好。

其次是平台无关性,如何让我的软件可以在尽可能多的平台上能够运行。举个例子,做APK或者说做移动APP开发的同学,有可能写了一个程序,但是这个程序应用APP无法在所有型号手机上运行,这是非常现实的问题。现在谷歌的应用市场,以及华为的应用市场里,已经有非常多的应用程序了。这些应用开发者所面临的问题是开发一个程序以后,能否让这个应用程序在尽可能多的不同手机上运行,因为只有让程序在尽可能多的不同型号手机上运行,才可能获取更多的用户,这个手机应用才有可能去变现。平台无关性对于开发者来说是最现实的问题。

2 编译的基本过程

上述编译器和编程语言的设计和实现中关注的问题又是如何通过编译过程来解决的?下面给大家介绍下整个编译器编译的基本过程,看它是如何一步步把我们前面讲到的编程语言变成可执行代码的。语言的问题是由上层设计来解决的,和芯片相关的这部分实现就是通过编译器完成的。和芯片相关的部分有:一是怎么让编程语言编译到我们的执行环境上,二是怎么让编译出的代码尽可能跑得快,还要跨平台。(因为时间受限,我在这里做一些大致的介绍,不具体深入。)

首先大家知道,我们现在所写的源程序是字符串的形式,字符串本质上是一些文本,它是可以打印出来的,但编译器无法理解这些文本本身的意义是什么。举个简单的例子,像古埃及的文字,现在有许多语言学家正在研究它,对于语言学家而言,这些古埃及的文字也是一些符号构成的文本,我们不能一下就弄懂这些文本到底是什么意思,得需要仔细地翻译。类似的,编译器把源程序文本变成处理器可以理解的二进制格式的过程也是一个翻译的过程。

image.png

翻译的第一步是词法语法解析的过程。程序的源代码通常是英文字母、数字和一些其它符号构成的文本。词法分析就是要识别出哪个或者哪几个连续的符号是一个词。多个词又构成了句子。检查句子是否通顺,就需要语法检查了。如果句子也通顺了,看句子表达的意思对不对,前后是否衔接连贯,就是语义检查了。如果经过语法检查,语义检查,句子通顺,意思也没有问题。那么编译器就对目前解析的结果生成一个中间的表示,我们叫它抽象语法树。

生成中间表示是一个非常重要的点,往后不同的编译器就会有不同的方式去执行。

下面进一步给大家介绍这三种执行方式的差别。

image.png

第一种是解释执行。所谓解释执行就是把程序告诉编译器所要执行的这些逻辑放到可以执行的工具上运行,该工具可以运行这些逻辑。好比同声翻译,你说一句,我翻译一句。解释执行就是你翻译一句,我理解这句意思后就去执行这一句。这样的方式比较灵活但不是很高效。

第二种是编译执行。这种方式下编译器会把源程序完整编译成机器能够直接执行的二进制代码,然后再由用户或者其它程序调用执行。在这种编译的过程中,编译器会进行各种性能,资源占用等方面的优化,使得生成的程序性能和大小更优。编译执行是一种静态的,我们称它为静态是因为它是一次性编译生成的。它的特点是程序跑得快,相比而言,解释执行这样的方式就显得非常低效。

第三种就是字节码虚拟机执行。字节码虚拟机执行是介于解释执行和编译执行之间的一种方式。Java实现了这样的运行方式。Java的编译器把程序源代码编译成了字节码的格式,然后通过虚拟机来执行(稍微澄清下,这里的虚拟机不是通常意义上的安装虚拟操作系统的虚拟机,而是用来运行字节码的虚拟机)。虚拟机执行还有另一种方式,就是把字节码实时编译成机器码,然后由硬件直接执行。这种方式会比通过虚拟机执行要快,但仍然没有直接在硬件上执行快。

3 编译优化案例

下面为大家介绍两个编译优化的案例。

1. Auto-Tuning

这里分析一个案例:在静态编译的过程中,如何改善已经编译出来的程序性能。该技术名为Auto-Tuning,也就是自动调优。

举个例子,有个优化技术是循环展开。编译器为生成的代码在循环体末尾加一个跳转指令跳转到循环体开始,从而再次进行循环体的执行。这种跳转不利于处理器高效运行。循环展开就是把循环体多复制几分,比如说循环体一共要运行4次,编译器就复制4份相同的代码,中间没有任何跳转,那么执行效率就会比原来的高。

通常的静态编译,通过一次编译,把源代码编译成二进制文件,在这个过程中软件要达到性能更优会有一些障碍。有统计数据显示,工业上用到的编译器有上百个参数,这些参数如何设置,如何互相组合,都有不同的策略,通过一次编译而获取更优的性能还是很难的。

另一方面,我们的软件要在不同的处理器上运行,不同的处理器指令集不同,各种指令执行效率都有差异,通过一次编译而获取在多个处理器上达到较优性能的效果也是很难的。

Auto-Tuning技术,是为了让整个编译策略更优、更友好地适配运行环境。它有3个组件:编译器,Search Driver, Profiler。下图是Auto-Tuning编译的流程图。

image.png

在左边的黄色源代码,经过中间绿色的词法、语法、语义分析和优化等步骤最终生成黄色的可执行文件,在开启Auto-Tuning后,过程中除了正常操作外还会把编译过程中应用到的需要调整的参数都完全暴露给外面的控制程序,就是前面提到的Search Driver。

接下来为了解编译完成的程序的性能到底如何,我们需要把这个程序运行在执行平台上,可以是硬件平台,或者是仿真的平台。程序运行过程中会生成体现性能的一些指标,包括热点代码、指令的执行效率、内存访问是否高效等。这些指标会提供给第三个组件——Profiler。Profiler会评估当前这个程序执行是否高效,感知程序在执行过程中是否有瓶颈,是否还有更好的优化空间。

在Profiler给出进一步的优化建议后,开始再次编译、运行和评估。整个过程相当于在编译器的整个参数调优空间里进行搜索,这也是Search Driver组件名称的来由。从理论上来说这是一个NP完备的问题,计算量非常大。采用这个技术,我们认为可以达到一个相对优的编译的解,这就是Auto-Tuning技术。

2. 128比特位宽原子操作指令优化案例

另一种提升程序性能的手段是通过指令来对软件应用进行优化,该案例讲的是如何使用一个128比特位宽的原子操作指令来优化数据库的应用,举一反三,你也可以通过特定场景的问题驱动指令集的设计。

数据库有大量数据在多个核上运行,而现在的处理器有很多的核,比如鲲鹏有64-128个核,甚至以后会更多。现代数据库例如PostgreSQL等在高并发业务场景下,均采用预写日志系统(Write Ahead Logging)对事务进行提交和记录。总体思想为数据文件的修改必须发生在这些修改已经记录在日志文件中之后,因此在生成该事务提交的日志记录时 ,需要原子性的预留数据写入磁盘的全局位置信息,否则在并发情况下后台线程会将数据写到错误的地址上。通过原子锁完成位置信息的预留,会引入跨CPU访存延迟、Cache一致性代价等问题引起的性能瓶颈。全局位置信息包括一个64位起始地址和一个64位的结束地址,若想通过Lock-Free无锁操作完成位置信息的预留,则需引入双寄存器原子指令。

使用双寄存器原子指令原子性完成全局位置信息预留(示例代码如下),多个lock-free线程可以同时访问同一数据而不产生数据竞争或者损坏,同时某个线程在执行数据访问时挂起不会阻碍其他的线程继续执行。

cas:              
ldxp   x7, x6, [x8]          #   使用ldxp指令读取全局位置信息
eor     x7, x7, x2            #   判断Start Position x7是否等于期望值x2          
eor     x6, x6, x3            #   判断End Position x6是否等于期望值x3
orr      x6, x7, x6            #   判断Start & End Position是否均保留有效     
cbnz   x6, fail                 #  若无效,则其他线程已修改            
stxp   w7, x4, x5, [x8]    #   反之有效,stxp指令更新全局位置信息
cbnz  w7, cas                #   若写入失败,则重新尝试   
fail:
#   位置保留失败,根据程序逻辑执行指令             

这里的LDXP/STXP指令用以执行一对通用寄存器的原子存储操作,指令语义如下所示:


LDXP <Xt1>, <Xt2>, [<Xn|SP>]                // Load Exclusive Pair of Registers
STXP <Ws>, <Xt1>, <Xt2>, [<Xn|SP>]    // Store Exclusive Pair of registers

LDXP:从Memory中读取一对双字数据到目标寄存器Xt1,Xt2中,同时对Memory地址注册一个监控保留状态。

STXP:有条件的将Xt1,Xt2一对双字字数据写入到Memory中,仅当此地址的监控保留状态有效时才执行成功,如果STXP执行成功,将零值写入Ws。如果STXP执行失败,将非零值写入Ws。

在我们的实验中,上述优化为某数据库的Measured tpmTOTAL性能提升10%

挑战课题

接下来讲我们这个领域里有哪些挑战的课题,这些课题想解决的问题是什么样的。

1.通用语言扩展机制研究,以及新型AI编程语言的设计和实现

AI编程以及AI语言的研究一直是我们团队关注的重点,我们要解决如何提升AI编程的体验和效率,充分发挥硬件的潜力,最大化AI程序的性能。例如基于昇腾芯片,如何让AI编程更高效、性能更优。这方面的课题内容是构建一套面向AI算法开发的编程语言,实现语言原生自动微分、动静态图融合、稀疏矩阵编程等核心技术。

对于通用编程语言,如何扩充现有编程语言和编译器能力,如何构建嵌入式领域的相关语言(eDSL),还有快速满足各种应用场景的定制需求。这方面的课题内容是探索和构建通用编程语言各种可扩展机制的设计和实现:包括但不限于元编程、跨语言互操作、eDSL及其类型系统、可扩展编译器框架。

2.基于开放体系架构下的DSA设计与编译工具链技术研究

领域定制架构(Domain Specific Architecture DSA)是计算机架构的发展趋势,针对应用领域定制的软硬件架构,解决摩尔定律无法持续的危机,在硬件变化基本稳定的情况下通过领域定制架构持续提升软件性能。现在是超异构的时代,未来的架构,芯片的专用性会越来越强。在数据中心、AI&视觉计算等不同的场景下,随着业务性能的需要,例如数据库查询性能、HPC算法能力等需求下,专用架构、专用芯片的使用会越来越多。基于这样的趋势,如何设计与研发相对应的编译工具链也是一个挑战课题。

课题内容具体如下所示:

1)DSA设计:突破已有计算机架构的限制,利用RISC-V等开放架构,设计特定场景的软硬件系统,如视觉分析,AI计算,图形处理,HPC计算等;

2)DSA编译优化自动化:高级语言到汇编指令之间的转换需手工开发编译器翻译。当前大量DSA的出现,让编译优化的开发成为瓶颈,需要探索新的方法;

3)DSA高效建模:对DSA快速构建性能模型,通过仿真,FPGA原型等手段,快速评估DSA设计效果;

image.png

3. 对AI芯片编译器技术的研究

AI芯片支持全场景,包括不同的芯片规格,需要在端、边、云场景下发挥出极致算力,对编译技术有较高挑战。

面临不同场景下算法的侧重不同,芯片SOC级别的内存带宽不同,计算单元的算力不同以及上层框架的要求不同等问题,需要挑战编程语言表达完备性、优化技术如何实现、如何进行POLYHEDRAL循环优化、超轻量在线编译、多场景性能优化、融合算子最优切分策略求解、计算单元最优调度等业界难题。

4. 面向应用的统一IR(公共中间表示)的研究

多核和异构是未来计算系统的发展趋势,从应用角度看,多种业务融合、互相协同开发和调优的需求会逐渐增加。从硬件来看,如何协同多种算力高效执行是一个挑战课题,特别是在人工智能领域出现了越来越多的IR(编译器中间表示),彼此之间互相割裂无法统一优化和调试。

在新硬件架构下,如何利用整体算力来完成应用的高效执行已经成为一个挑战的课题。我们需要确定一个统一的异构编程语言、探索出一个方便易用的异构编程框架、开发相应的编译优化技术及运行时支持,给开发者提供易用性的同时充分挖掘硬件潜力。同时本课题瞄准支持多语言公共表示和抽象,支持多层 IR同时也支持其他IR和中间语言,实现跨语言高效互通,为全程序优化打下基础;提供一个可沉淀不同领域优化技术的公共基础设施、动静态各种优化技术模块化,并可按不同场景需要自适应自组合,如在昇腾AI领域,支持更好的算子融合优化。通过该课题研究,达成多编程语言支持,降低 “语言墙” 开销,构建业界领先的编译优化基础设施(含传统应用和AI模型算法),并支持更多功能(如程序分析、安全检测)。

今天的课题介绍就到这里了。

以上是我给初学者的建议和分享,谢谢。

作者: 曾建江
文章来源:毕昇编译

推荐阅读

欢迎大家点赞留言,更多Arm技术文章动态请关注极术社区嵌入式AI专栏欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。
推荐阅读
关注数
18808
内容数
1352
嵌入式端AI,包括AI算法在推理框架Tengine,MNN,NCNN,PaddlePaddle及相关芯片上的实现。欢迎加入微信交流群,微信号:aijishu20(备注:嵌入式)
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息