期货交易自动化论坛

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 20|回复: 0

是什么让华为攻城狮泪牛满面?首次全面深度解密华为方舟编译器 - 比特币今日价格

[复制链接] |主动推送

285万

主题

285万

帖子

855万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
8553710
发表于 2022-9-11 07:49:15 | 显示全部楼层 |阅读模式
2019-08-07 09:14:33栏目:默认栏目 4475 0 1
文章转载自公众号 菊厂搞机 , 作者:菊厂搞机专题组
本文由菊厂搞机MO编辑部出品,文字超1万,查阅的资料多达上百万文字,并且与华为方舟编译器的专家做过深度访谈。文章高度概括了波澜壮阔的软件产业发展史,解析了华为在编译器和手机系统方面做的多年准备。
2017年5月的一个凌晨,华为某实验室里,方舟编译器上第一个Java程序“Hello, World”跑通了。

当时项目组的一位工程师就哽咽了:“I never thought printing ‘Hello, World’ would be this hard .”(我从来没想到打出“Hello, World”会如此艰难。)
十年前华为启动编译组到这一刻,初见曙光。
2019年4月,华为方舟编译器正式面世!
今天我们聚焦华为新贵——方舟编译器,这个一发布就引起巨大响动的底层核心技术。
它为什么能拥有和世界对话的荣光?
它承载着怎样的使命?
它能否做到传说中的“出于安卓,胜于iOS”?
01
机器的“原力觉醒”
这个故事,先从计算机的语言说起。
事实上,人类文明中最早出现的文字就是数字,比完整表意的文字早500-1000年。
随着人类社会的发展,社会结构开始变得复杂,征税必须先收集国民收入、财产、付款、欠款、债务、罚款等数据,远远超过人脑的记忆系统。于是,数字诞生了。
5000年前,苏美尔人文明(今科威特及邻近地区)以6和10作为基数,用符号表达1、10、60、600、以及3600。今天,我们仍然常见以6为基数的数字,例如圆有360度,一天有24小时。
而另外一种叫安第斯文化(主要在今天的南美地区),则用“结绳语”记录数字,管理税收等财务数据长达数百年甚至数千年。就算西班牙人占领南美之后,还在相当一段时间内用结绳语来管理他们建立的新帝国。

这就是人类最早的语言,虽然不能完整传递口语,也无法写诗,但是记账收税效率一流。
公元8世纪,印度人发明了数字0-9,这种十进制的数学符号让数据存储和处理的效率一日千里,成为人类文明重要的里程碑,奠定了现代数学基础。后因阿拉伯人将其发扬光大并传入中东和欧洲,所以大家称之为“阿拉伯数字”。
还有一种文字系统——“0”和“1”的二进制,是人类文明另外一个重要的里程碑,被广泛应用在现代计算机领域中。此外,我们喜欢的音乐、我们热爱的电影、我们拍摄的照片,今天都是通过这种二进制的数字来进行“重现”,包括记录、存储、传播和分享。
人类通过0和1开启了机器“文明”,从此科学革命的进程就像安装上了“火箭”。
那为什么计算机使用的是二进制呢?
这个故事得回溯到大英帝国的航海时代。
早在17世纪,英国借助强大的经济实力和海军力量拥有了众多的殖民地,建立了全球霸主地位。舰队使用的航海表计算复杂,人工计算的数据经常有误,百年间导致大量的船只触礁沉没。
直到第一次工业革命爆发,英国政府找到了数学家巴贝奇(Charles Babbage)来修正航海表。巴贝奇通过十年的努力,研制成功了“差分机”。用蒸汽机时代的机械齿轮来存储计算过程中的数据,大大提升了航海表数据的计算速度和准确率。
同期,他开始了另外一种新机器——分析机的设计。在开发分析机的过程中,巴贝奇冥思苦想,发现乘法是加法的重复,除法是减法的重复,减法可以用加法来代替,这样就只要设计一个加法运算器即可。基于这种假设,计算机器只需要具备两个功能即可运作:
1)判断两个数的大小;
2)不断重复执行加法计算。
所有的运算转化为最简单的判断和计算,1表示Yes(开),0表示No(关),计算机用0和1不断重复计算。这就是计算机使用“0”和“1”二进制语言的理论基础。
值得一提的是,巴贝奇发明分析机不久之后,英国数学家乔治·布尔于1854年发表了“布尔代数学”,提出了逻辑学的二元运算,为现代电子计算机提供了另外一个重要的理论基础。
回到分析机,巴贝奇借鉴了法国纺织机上使用的穿孔卡片。卡片上的孔眼排列,控制纺织机的梭子,能够不断重复的织出各种各样美丽图案的布匹。巴贝奇在著名诗人拜伦之女Ada Lovelace的帮助下,发现穿孔卡片不仅可以用来记录数据,还能用来控制机器工作的指令。在卡片上打上不同排列的孔,机器便有不同的工作程序,这就是现代计算机的软件设计思想。
基础研究与基础教育是产业诞生和振兴的根本。这也是为什么今天的英国,仍然在数学和通信领域拥有非常广泛的影响力。
1884年,美国统计专家赫尔曼·何乐礼(Herman Hollerith)借鉴穿孔卡原理发明了电动制表机,用于美国人口统计,与巴贝奇的分析机具有异曲同工之妙。他把所有需要调查的项目依次固定在一张硬纸卡上,然后将统计的居民个人信息在相应位置打孔,用来表示“Yes”。当统计机器的探针撞到卡片上的“孔”,就会接通电流,计数装置往前进一个刻度。何乐礼博士正是采用了二进制的原理,来高效统计美国人口信息。
我们今天使用的答题卡,就采用了这种原理。

何乐礼博士随后创建了制表机公司,也就是赫赫有名的IBM公司的前身。
1935年,著名的现代计算机科学之父和人工智能之父,艾伦·图灵提出了著名的图灵机模型,为现代计算机的逻辑工作方式奠定了理论基础。
1937年,美国哈佛大学著名计算机专家霍德·艾肯在IBM公司的资助下,借鉴上面提到的英国数学家巴贝奇的分析机理论,于1944年研制成功世界第一台机电计算机——Mark-I型。IBM把这台计算机送给了哈佛大学,并一直使用到1959年,为培养早期的计算机科学家做出了巨大贡献。
另外一位学者就没有这样幸运了。美国爱荷华州立大学理论量子物理学的约翰·阿塔那索夫(John Atanasoff)副教授,苦于没有机器能够计算出量子物理中许多变量的求解。同样是在1937年,他寻求IBM公司的资助,但被断然拒绝,于是他横下决心一定要研制一台更好的计算机器。他利用当时正在发展的真空晶体管,用电子脉冲来表示“0”和“1”,并在电气工程专家克利福特·贝瑞(Clifford Berry)的帮助下,两人于1940年底研制成功了世界第一台电子计算机,并用两个人的名字将其命名为ABC(Atanasoff-Berry Computer)。
阿塔那索夫开辟了一种计算机的全新路径,为现代电子计算机的架构奠定了不可磨灭的基础。今天的华为在内部强调研发上要多路径突破,或许也曾受此启发。
1940年底,他结识了美国物理学家莫克利(JohnW.Mauchly)。莫克利在了解和参观了ABC计算机后,联合宾夕法尼亚大学莫尔学院的电气专家艾克特(J.PresperEckert),在国防部的资助下和冯·诺依曼博士的指导下,于1945年研制成功了世界第一台通用电子计算机ENIAC。虽然这台计算机采用的是十进制,但当时毫不影响它的计算能力,它大大缩短了美国“曼哈顿计划”的原子弹研发时间,加速了二战的结束。
1945年6月,冯·诺依曼将ENIAC电子计算机的十进制改回成二进制,并提出计算机内部存储器存储程序的概念,从而奠定了现代电子计算机理论的架构。
0和1这种极简的语言设计,像给计算机注入了永远在生长的“原力”,带来了无限的可能。与通信领域IP路由理念具有异曲同工,就像“看不见的蒸汽机”,用最简单的理论架构开启了一个全新的伟大产业。
02
软件王国的“四大明珠”
实际上,在电子计算机诞生之前,计算机这个角色是由女人来扮演的。这些女人被称为Computers,大多数计算都是她们手工完成的。
世界第一段程序,是上面提到的巴贝奇的师妹著名诗人拜伦之女Ada Lovelace在打孔卡上写出来的。程序设计人员都要把程序编排成010101这样的形式,在纸上打孔,再送到机器里去读。这减少了相当多的工作,写一个卡片能使用相当久,也避免了重复造轮子。
因此,当程序员开始在卡片上写这些程序时,人们开始构建程序库(libraries)。随着时间的推移,大部分的程序渐渐的有了一些规则手册来指导编写。但还是很繁琐,毕竟编写和记忆0和1的各种组合,对于很多人来说相当于是“天书”。
一个传奇的人物出现了。
美国海军的传奇天才格雷斯·霍珀(Grace Hopper),在海军服役时,曾被派到哈佛大学,与艾肯博士一起工作,负责为美国国防部资助的Mark-II型机电计算机编制程序。在二战结束后,她加入了发明ENAIC电子计算机的莫克利和艾克特创办的“电子控制公司”,开始了她改变世界的光辉旅程——打开编译器和编程语言的新世界。

Grace在加入莫克利和艾克特的公司,便产生了一种想法。她想设计一种程序,让人可以用类似英文的语法,把想做的事写下来,然后用这个程序把英文翻译成机器能执行的语言,交给机器去执行。
她把这个革命性的想法付诸实践,发明了世界上第一个编译器A-0。这是编译器的始祖,也是现代编程语言的始祖。
1952年,Grace和莫克利研究出了一种较为接近自然语言的计算机语言——汇编语言Flow-Matic。汇编语言本质上是使用助记符来代替机器语言01010101,进了一大步,但这种语言对计算机硬件依赖很大。不同的计算机,汇编语言不相通。
IBM公司在1946年后从制表机全面转型电子计算机市场,并投入巨资招揽了世界众多顶尖的计算机人才。其中一位叫约翰·贝克斯(John W. Backus),这位出身证券经纪人家庭的富二代,酷爱数学,加入IBM公司三年后,发明了一种快速编程的FORTRAN语言。同时,他深入研究了Grace发明的Flow-Matic的编译器,应用到FORTRAN的编译器中。
FORTRAN的问世,在计算机史上具有划时代的意义。它是世界第一个高级编程语言,使计算机语言从原始的低级汇编语言走到人人易懂的境界,计算机不再是科学家的专利。FORTRAN的诞生,孕育了软件产业。此后,计算机高级编程语言进入蓬勃发展的时代。
随后,IBM公司开发出了的ALGOL高级语言,人工智能之父约翰·麦卡锡(John McCarthy)发布了人工智能设计语言LISP,Grace奶奶也在Flow-Matic汇编语言的基础上开发了COBOL语言。
FORTRAN适合科学计算,ALOGOL适合事务处理,LISP适合人工智能计算,COBOL适合商业处理。这四种高级语言虽然比汇编语言更简单,但对于非计算机专业人员,编程仍难度较大。于是,Dartmouth学院的两位教授联手开发一种更简单的编程语言BASIC(初学者的全方位符式指令代码)。这是一种不需要编译的语言,只需要经过解释器执行即可,初期的Android智能手机软件借鉴了这种机制。BASIC语言也是目前被广泛使用的Visual Basic语言的鼻祖,目前在微软Excel的“宏”中可以直接使用。
美国编程语言的开发热潮你追我赶,其他国家也不甘示弱。
1963年,英国剑桥大学推出了CPL语言,后又推出了简化的BCPL语言。
1970年,美国贝尔实验室的肯·汤普逊(Ken Thompson)和丹尼斯·利奇(Dennis Ritchie)在BCPL语言的基础上,推出了更加简单的B语言(取BCPL第一个字母),后又简化出了C语言(取BCPL第二个字母)。这是目前世界上最常用的编程语言之一,甚至可以说是第一大编程语言。
C语言之后,诞生了很多著名的语言,包括:
C++:1983年正式发布。由贝尔实验室基于C语言改良,所以C++是完全兼容C语言的。
Objective-C:1980年代发明。1988年,斯蒂夫·乔布斯(Steve Jobs)在NeXT公司时买下了 Objective-C 语言的授权,后来成为苹果公司MAC电脑和iPhone手机的程序设计语言。
Java:1995年5月发布。SUN公司为了在电视机顶盒等电子产品智能化过程中抢占先机,解决跨平台的问题,所以开发了Java语言。但Java需要借助虚拟机机制来解释源代码并调度硬件资源。安卓系统使用的基础语言就是Java。
C#:2000年6月,由微软发布。C#与Java有着惊人的相似,也需要借助类似于虚拟机的Framework来运行;不同的是,Java支持所有平台,而C#只支持Windows和Linux系统。
GO:谷歌在2009年发布。GO语言主要用作服务器端和云计算开发。
Swift:2014年由苹果公司发布,可以和Objective-C语言混合使用。
其中,C/C++是编译语言,即在程序员写完程序后,通过编译器直接编译成机器码,安装到相应的硬件设备上即可直接运行。
Java/C#是预编译语言,就是需要先在开发者环境中将源代码(Source Code)转换成字节码(Byte Code),然后在设备上运行时再将字节码编译或解释成硬件能听得懂的机器码。将源代码转换成字节码的过程,就叫预编译。

软件王国还有两个很重要的成员,就是操作系统和数据库。
上个世纪60年代,计算机高级语言的发展为操作系统和数据库的诞生培育了沃土。
1970年,贝尔实验室B语言和C语言的开发者肯·汤普逊(Ken Thompson)和丹尼斯·利奇(Dennis Ritchie),开发出了世界第一个通用计算机系统——UNIX。现在大家熟悉的Linux和Mac OS就是类UNIX操作系统。
其中Linux可以运行在服务器和其他大型平台之上,如大型计算机和超级计算机,世界上最快的前10名超级计算机运行的都是基于Linux内核的操作系统。在移动设备上广泛使用的Android操作系统也是创建在Linux内核之上。
随着磁盘的发明,从磁盘随机存取数据成为可能。1961年,美国通用电气公司成功地开发出世界上第一个数据库管理系统(DBMS)——IDS(Integrated DataStore 集成数据存储)。1968年,IBM公司开发了IBM第一个数据库系统IMS(Information Management System)。IBM科学家的论文理论,成就了著名的Oracle数据库。IBM公司出品的DB2和微软公司的MS SQLServer数据库也成为当今数据库领域重要的角色,目前在全世界已经广泛应用。
高级编程语言、编译器、操作系统和数据库,被称为软件王国的“四大明珠”。

从上图可以看出,为软件底层贡献核心技术的公司主要来自于欧美。华为通过多年持续的研发投入,让我们终于看到了美国巨头的背影。
03
编译器的前世今生
如果说计算机是汽车,那么软件就像汽车的操控系统一样,是计算机的血液。
编译器则是汽车发动机里最核心的汽油燃烧技术,将软件变成计算机的动力,其编译性能和效率,直接决定了用户的使用体验。
如上文所述,最早的编译器是Grace奶奶发明的A-0编译器。
第二个被大规模应用的编译器,则是和FORTRAN编程语言配套的FORTRAN编译器。
目前主流使用的编译器主要有下面几种:
Windows系统
使用CL编译器。它直接集成在Visual Studio或Visual C++的开发者环境中,一般不单独使用。
Linux系统
使用开源的GCC编译器。GCC,由自由软件运动的精神领袖理查德·马修·斯托曼(Richard Matthew Stallman, RMS)在上个世纪80年代创立。它原本只处理C语言,后续扩展可以处理C++、Objective-C、Java等其他语言。GCC被认为是跨平台软件的编译器首选。
苹果Mac和iOS系统
最初使用GCC编译器,现已替代为Clang + LLVM。
为什么苹果公司要换编译器呢?
因为苹果发现开源的GCC开发者根本使唤不动,他们不愿意专门为了苹果公司的要求优化和改进GCC代码,所以苹果将编译器后端直接替换为LLVM(Low Level Virtual Machine,底层虚拟机),并且将读研时(2003年)发明LLVM的天才少年克里斯·拉特纳(Chris Lattner)招入麾下。克里斯进入了苹果之后,大幅度优化和改进LLVM以适应Objective-C的语法变革和性能要求,同时发起了CLang项目来完全替代GCC。
今天,GCC + LLVM 已经被替换成了 Clang +LLVM。LLVM负责编译器后端,用来处理代码优化和跨平台,而Clang负责前端,只需将程序源代码转换成LLVM可以看得懂的IR(Intermediate Representation,中间语言)即可。
另外,上文提到的Swift语言,则是这位天才少年克里斯为苹果公司贡献的第三个重要作品。
安卓系统
安卓主要使用预编译的Java语言开发,最初版本通过虚拟机运行,不需要编译器,后续版本加入了JIT和AOT编译机制(下一部分将详细展开)。
除了上述编译器之外,还有两个著名的编译器值得一提。
Intel的ICC编译器
ICC编译器,全称Intel C++ Compiler,是Intel开发的C/C++/Fortran编译器套装,适用于Linux、Microsoft和Mac OS X操作系统,广泛应用于高性能计算、分布式计算等商业计算领域。
SGI等公司推出的Open64编译器
SGI(S代表超级计算机,G代表图形工作站,I代表具有突破性的洞察力)生产的超级计算机,主要应用于巨大的实验室,采用Open64编译器。
04
安卓的四大命门
交待完计算机和软件的发展历程,终于说到正题。
安卓系统从2008年1.0到今天的9.0,十来年间安卓系统大小版本超过15个,从2016年开始也在不断融入了华为等手机公司发起的文件系统、人工智能学习、智能硬件调度和内存管理等底层创新技术,安卓手机的体验已经今非昔比。
为什么仍然还有很多人诟病安卓手机没有iPhone流畅?安卓系统的程序是怎样运行的?下面展开阐述一下安卓的四大命门。
解决安卓这四大命门,也是华为方舟编译器的使命!
第一个命门
Java的“虚拟机”
前面提到,Java为了能够实现跨平台操作,便借助虚拟机来调度硬件平台资源。在虚拟机里,还需要集成翻译器或者编译器,来将Java的字节码(即中间代码)解释成机器听得懂的机器语言,或者直接编译成机器直接执行的010101的机器码。
2008年,Android 1.0刚发布的时候,使用的是一个叫Dalvik的虚拟机,里面集成了一个解释器,每次用户在安卓手机上运行APP时,就会叫醒这个解释器,来给安卓的硬件解释APP想要干嘛。这就相当于新闻发布会,发言人讲一句自己的母语,然后再由专业翻译将其翻译成外国记者听得懂的语言,效率非常低下,一个小时可能也问不了几个问题。
谷歌意识到这个问题严重拖了安卓手机的后腿,所以通过一年多的努力,在2010年中发布了2.2版本,引入了JIT(Just in Time,即时编译)机制。JIT比较聪明,当用户在安卓手机运行APP时,会同时将用户经常使用的功能编译为机器能直接执行的010101机器码,不用每一句每一句的去翻译。当出现不常用的功能时,再把解释器叫起来翻译。
JIT虽然变聪明了一点,但是每次启动APP都要先编译一次,不能一劳永逸。加上Dalvik虚拟机性能比较落后,所以谷歌在2014年10月推出了Android 5.0版本,将虚拟机从Dalvik替代成ART(Android Run Time),同时把JIT的编译器替代成AOT (Ahead of Time)。意思就是说,APP在下载后安装到手机上时同时把能编译的代码先编译成机器听得懂的101010。剩下不太好翻译的代码,就在用户使用时再叫醒解释器来翻译。AOT相比JIT的好处,就是不用每次打开APP都需要先编译一遍。但是,坏处就是用户安装APP的时间有点长。
越来越多的用户吐槽为什么安装一个APP也慢吞吞。于是,谷歌在2017年Android 7.0又做了一点改进,安装时先不编译中间代码,而是在用户空闲时将能够编译成机器码的那部分代码,通过AOT编译器先静态编译了。如果AOT还没来得及编译或者不能编译,再叫醒JIT+解释器两个难兄难弟来顶住。这种机制,相当于用时间换空间,既缩短了用户安装APP的等待时间,又将虚拟机里编译器和解释器能做的优化提升到最大效率了。
很多人以为华为方舟编译器就是Android 7.0的ART虚拟机,其实不然。

无论是编译器还是解释器,只是在虚拟机上打补丁。手机上的虚拟机+编译器+解释器本身不仅占用硬件资源,还无法最大发挥软件运行性能。正因如此,所以绝大部分手机厂商只能无奈的通过简单粗暴提升安卓手机的内存和存储空间,来弥补虚拟机的弊端。
这就是安卓的第一个命门,虚拟机先天不足。
第二个命门
Java的“原罪”——额外的JNI开销
JNI,全称Java Native Interface(Java原生接口),用来和C/C++等代码进行交互。

目前95%的TOP应用都是使用Java和C/C++等多种语言混合开发而成。Java和C/C++属于两种不同架构的语言,各有自己的使用规范。为了APP正常运行,它俩之间需要互通有无,这个互通有无的接口就是JNI。在数据访问、函数调用、生命周期维护、异常处理等方面都需要这两种代码互相调用。这就意味着手机硬件资源要分配一部分给JNI去做调度。不仅占用了硬件资源,而且这种机制本身就效率较低。
这便是额外的JNI开销。
第三个命门
代码优化空间有限
安卓虚拟机的编译器受限于手机硬件和代码优化模板单一,代码优化空间有限。
编译器包含三个部分。前端Front End,主要负责将源代码翻译成IR(Intermediate Representation,中间表示);中端的Optimizer主要负责代码优化,将前端翻译过来的IR代码优化得更高效;后端Back End则将优化后的IR编译成101010的机器码。

为了防止生态过于碎片化,安卓只为第三方开放了简单的编译代码优化模板,代码优化空间有限。
第四个命门
Java现有内存回收机制易造成间歇性卡顿
当手机内存资源不够用的时候,安卓虚拟机就会召唤GC(Garbage Collection)封锁公路,让所有手机运行的Java线程“Stop World”,全部暂停,等待它回收内存空间,避免“交通流量超载”。这个GC机制,无法精确控制和干预,用户也无法把它去掉,所以性能比较差的手机还存在“间歇性”卡顿。
十余年间,通过安卓系统的持续优化,以及内存的不断加持,安卓手机构筑了足够流畅的用户体验。
但是安卓的四大命门,如同达摩克利斯之剑,悬在安卓厂商的头上。华为科学家和工程师们,对此持续攻关了十年,只为再造安卓。
matic是什么

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|期货交易自动化论坛

GMT+8, 2024-11-29 19:49 , Processed in 0.086557 second(s), 28 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表