我们将继续审查新的家用计算机。简要了解Elbrus架构的功能之后,我们将考虑提供给我们的软件开发工具。
回忆一下文章的结构:- 硬件审查:
- 软件审查:
- 开发工具概述:
- 标杆绩效:
祝您阅读愉快!建筑特色
E2K体系结构的实质可以用以下语句表述:64位寄存器,指令执行的显式并行性和严格控制的内存访问。例如,隐含的 x86或SPARC体系结构处理器的每个周期能够执行多个指令(超标量),有时甚至是乱序的。并行性:处理器直接实时地分析一小段代码中指令之间的依赖关系,如果认为可能,则同时加载某些执行器。有时,他的行为过于乐观-推测性地,在预测失败的情况下放弃结果或回滚事务。相反,有时它太悲观了-假设寄存器值或寄存器部分的值之间存在依赖性,而这些依赖性实际上并不是从可执行程序的角度来看的。如果 明确并行性(显式并行指令计算,EPIC)在编译阶段进行相同的分析,并且为并行执行定义的所有机器指令均用一个非常大的指令字(VLIW)编写-Elbrus的长度为“字”不是固定的,可以是1到8个双字(在这种情况下,单个字的容量为32位)。毫无疑问,就所覆盖的代码量,所花费的时间和内存而言,编译器具有更大的功能,并且当手动编写机器代码时,程序员可以执行更智能的优化。但这是理论上的,实际上,您不太可能使用汇编器,因此,这全取决于优化编译器的性能,至少可以说,编写一个汇编器并非易事。另外,如果在隐式并行的情况下,“慢速”指令可以继续工作而不会在其他执行器上阻止以下指令的接收,则在显式并行的情况下,整个宽命令将等待完整完成。最后,优化的编译器对解释动态语言几乎没有帮助。当然,所有这些都在MCST上得到了很好的理解,因此,Elbrus还实现了推测执行技术,预加载的代码和数据以及组合的计算操作。因此,在理论的第四部分中,我们只是采取并评估了实际程序(应用程序和综合程序)的实际性能,而不是理论上和无限地怀疑该平台或平台在成功的情况下可以发出多少个假设的千兆位。VLIW:突破还是死胡同?, VLIW : , ‑ Transmeta Crusoe — «». , Efficeon ( ) . , x86- , . , Pentium M , Pentium 4 , . VIA C3, x86.
由于其特殊的性质,使用C / C ++语言保护程序执行的技术同样引人注目,在该技术中,使用指针提供了广泛的机会,可以用脚射击自己。上下文保护的概念,无论是访问私有类变量,另一个模块的私有数据还是调用函数的局部变量,在编译阶段由编译器在运行时由处理器,在运行时由处理器以及操作系统在内存管理方面共同实现时,都不会违反变量的范围。 。仅在减少权限的方向上允许进行任何更改访问级别的操作。禁止将链接保存到寿命长的结构中的寿命短的对象。还可以防止尝试使用无效链接:如果曾经收到链接的对象已被删除,即使另一个新设施位于同一地址,也不会被视为访问其内容的借口。鼓励将数据用作代码并在任何地方传输控制。确实,一旦我们从高级成语过渡到低级指针,那么所有这些可见性领域都不过是语法上的问题。一些(最简单的)滥用指针的情况有时可以帮助捕获静态源代码分析器。但是,当程序已经转换为x86或SPARC机器指令时,则不会阻止它从错误的存储单元或错误的大小中读取或写入值,这将导致崩溃在一个完全不同的位置-您坐在这里,看着损坏的堆栈而且您不知道从哪里开始调试,因为在另一台计算机上,同一代码可以成功执行。堆栈溢出和由此产生的漏洞只是流行平台的祸害。很高兴我们的开发人员系统地解决了这些问题,并且不限于安排越来越多的拐杖,其效果仍然类似于耙。毕竟,如果程序无法正常运行,没有人会在乎程序的运行速度。此外,编译器更严格的控制会迫使您重写“难闻的气味”和令人无法忍受的代码,这意味着它间接增强了编程文化。与SPARC不同,在Elbrus的内存中存储数字时的字节顺序是小尾数(低字节在前),即在x86上。同样,由于平台旨在支持x86代码,因此内存中的数据对齐没有限制。顺序,对齐方式和可移植性 , Intel, , (, 32‑ 0x04000005) — , , , . - , , , — , ( , UTF‑16), , , , ‑. , , — , SPARC, — .
您可以在《 Elbrus家族的微处理器和计算复杂体》一书中了解有关SPARC和E2K架构的MCST计算机设计的更多信息,该书由彼得出版社以最小的印刷版出版, 并已出售很久,但可以以PDF格式免费获得(6 MB)并在Google Play上支付少量费用 。在公共领域缺乏其他详细信息的背景下,该出版物只是一个知识库。但是本文主要集中在硬件,缓冲区和管道的操作算法,高速缓存和算术逻辑设备上–编写[有效]程序的主题完全没有解决,甚至只提到机器指令就可以指手可得。机器语言
除了编译高级语言C,C ++,Fortran之外,文档还不忘提及在Assembler中直接编写程序的可能性,但是在任何地方都没有具体说明您如何确切地参与到这种花丝技艺中,至少您可以在其中获得对机器指令的引用。幸运的是,该系统具有一个GDB调试器,该调试器可以反汇编以前编译的程序的代码。为了不超出本文的范围,我们编写了一个简单的算术函数,该函数具有良好的并行积压。uint64_t CalcParallel(
uint64_t a,
uint64_t b,
uint64_t c,
uint32_t d,
uint32_t e,
uint16_t f,
uint16_t g,
uint8_t h
) {
return (a * b) + (c * d) - (e * f) + (g / h);
}
这是在-O3模式下编译时的含义:0x0000000000010490 <+0>:
muld,1 %dr0, %dr1, %dg20
sxt,2 6, %r3, %dg19
getfs,3 %r6, _f32,_lts2 0x2400, %g17
getfs,4 %r5, _lit32_ref, _lts2 0x00002400, %g18
getfs,5 %r7, _f32,_lts3 0x200, %g16
return %ctpr3
setwd wsz = 0x5, nfx = 0x1
setbp psz = 0x0
0x00000000000104c8 <+56>:
nop 5
muld,0 %dr2, %dg19, %dg18
muls,3 %r4, %g18, %g17
sdivs,5 %g17, %g16, %g16
0x00000000000104e0 <+80>:
sxt,0 6, %g17, %dg17
addd,1 %dg20, %dg18, %dg18
0x00000000000104f0 <+96>:
nop 5
subd,0 %dg18, %dg17, %dg17
0x00000000000104f8 <+104>:
sxt,0 2, %g16, %dg16
0x0000000000010500 <+112>:
ct %ctpr3
ipd 3
addd,0 %dg17, %dg16, %dr0
引起您注意的第一件事是,每个命令都会立即解码为并行执行的多个指令。指令的助记符指定通常是直观的,尽管有些名称在Intel之后看起来很不寻常:例如,此处未签名的扩展指令称为sxt,而不是 movzx。除了操作数本身之外,许多计算命令的参数还包括执行设备的编号-ELBRUS并非没有理由代表明确的基本资源利用调度,即“明确计划使用基本资源”。要访问完整的64位寄存器值,前缀“ d“;从理论上讲,也可以访问该值的低16位和8位。全局通用寄存器的名称共有32个,在数字之前带有“ g ” 前缀,而在本地过程寄存器中则带有前缀“ r ”。setwd指令请求的本地寄存器的窗口大小可以达到224,然后根据需要将泵自动推入堆栈。应用某些说明的方式令人困惑:例如,返回您可能会猜到,它可以将控制权返回给调用过程,但是,在所有研究的代码示例中,此指令早于最后一条命令(也存在某种上下文操纵)发生之前,有时甚至在第一个命令字中也是如此。尽管上述书籍为这一问题付出了整整一整段时间,但对我们来说还不清楚。从2016年2月9日开始更新:注释建议return语句仅准备从子程序返回的方式,并允许处理器开始加载调用过程的下一个命令,并且控件本身在执行到ct指令时返回 。但是,就机器指令而言,“易读代码”和“高效代码”远非相同。如果不进行优化而进行编译,则代码会更一致,更类似于额头计算,但是代价是加长:代替6个饱和命令字,将生成8个稀疏命令字。在模拟咖啡的算命会议上,让我们结束,然后再幻想完全荒谬的假设。希望有一天,该命令参考以及编程和优化指南可以公开。开发工具
Elbrus操作系统中的标准C / C ++语言编译器是LCC,它是MCST公司的专有开发,与GCC兼容。尚未发布有关此编译器的结构和原理的详细信息,但根据对编译器几个已开发亚种之一的前开发人员的采访,爱迪生设计集团使用前端对源代码进行高级分析。 ,并且可以以不同的方式执行对机器指令的低级翻译-无需优化或进行优化。它是优化的编译器,不仅在E2K平台上交付了最终用户,对于E2K平台来说,根本没有替代的机器代码生成器,而且在SPARC系列平台上也可以使用,在该平台上也可以使用作为MSVS操作系统一部分的常规GCC。考虑到上面列出的体系结构功能-明显的并发性,程序的安全执行-LCC编译器显然实现了许多独特的解决方案,值得在实践中进行最严格的研究和测试。不幸的是,在撰写这些文章时,作者既没有足够的资格,也没有时间进行研究。我希望迟早这个问题将由IT界的广大代表解决,包括更有能力的代表。在构建用于测试性能的程序时,您设法肉眼注意到,在E2K上的LCC比其他代码更经常地警告您可能的错误,文盲的构造或代码中只是可疑的地方。没错,作者不太熟悉GCC,以保证区分俄语中的LCC唯一消息和简单翻译的LCC消息(此外,翻译是选择性的),而且我不确定警告更多的源源不是自动完成的装配配置。同样,由于不了解特定代码段的语义,有时很难理解编译器在寻找隐藏的错误或发出错误警报方面的聪明程度。例如,在Postgresql代码中,在同一文件中四次发现相同的构造,但略有不同:for (i = 0, ptr = cont->cells; *ptr; i++, ptr++) {
if ((*ptr)[strspn(*ptr, " \t")] == '\0')
fputs(" ", fout);
else
html_escaped_print(*ptr, fout);
}
编译器通过strspn函数的调用来预测字符串中的一维数组的可能出路。在什么情况下会发生这种情况,作者不理解(尽管检查模式为Warray-bounds,但在其他平台上也没有这样的警告是GCC的标准),但是,值得注意的是,同一非平凡设计的多次复制(因为有必要在注释中解释其用途),而不是将其放入一个单独的函数中,其雄辩的名字不需要解释。即使警报是错误的,检测臭味代码也是有用的。 PVS‑Studio静态分析仪的作者将不做任何工作。但认真的说,由于E2K架构的独特功能,比较LCC真正能够检测到的代码中的哪些其他错误将是有趣且有用的-同时,自由软件世界可能会收到另一批错误报告。与贫嘴LCC好奇熟人的另一个结果是教育的作者,然后自己更有经验的同事,什么三合(三合在C / C ++语言),以及他们为什么默认情况下不支持的,幸运的。您的生活是这样的,不要怀疑文本文字或注释中标点符号的无害组合可能是定时炸弹-或程序书签的绝佳材料,具体取决于您位于路障的哪一侧。LCC自给自足的不愉快结果是其消息格式不同于GCC的消息格式,并且从开发环境(例如Qt Creator)进行编译时,这些消息仅属于一般的工作日志,而不属于公认的问题列表。也许可以从编译器方面或在开发环境中以某种方式进行自定义,但是至少开箱即用,它彼此之间并不了解。传统上,对于家用平台而言,由于性能相对较低,因此存在交叉编译的问题,即使用功能更强大的计算机,不同的体系结构和其他软件的资源来汇编目标体系结构的程序和一组特定的系统库。从Elbrus系统核心和LCC编译器本身的标识行来看,它们是在Linux i386上组装的,但是用于x86的此工具包当然不包含在系统本身的分发包中。有趣,但是有可能做相反的事情:在Elbrus上收集其他平台的程序吗?(作者在i386的GCC大会的第一阶段没有取得更大的成功。)对开发人员而言最重要的软件包的版本:- 编译器:lcc 1.19.18(与gcc 4.4.0兼容);
- : erlang 15.b.1, gawk 4.0.2, lua 5.1.4, openjdk 1.6.0_27 (jvm 20.0‑b12), perl 5.16.3, php 5.4.11, python 2.7.3, slang 2.2.4, tcl 8.6.1;
- : autoconf 2.69, automake 1.13.1, cmake 2.8.10.2, distcc 3.1, m4 1.4.16, make 3.81, makedepend 1.0.4, pkgtools 13.1, pmake 1.45;
- : binutils 2.23.1, elfutils 0.153, patchelf 0.6;
- : boost 1.53.0, qt 4.8.4, qt 5.2.1;
- : expat 2.1.0, ffi 3.0.10, gettext 0.18.2, glib 2.36.3, glibc 2.16.0, gmp 4.3.1, gtk+ 2.24.17, mesa 10.0.4, ncurses 5.9, opencv 2.4.8, pcap 1.3.0, popt 1.7, protobuf 2.4.1, sdl 1.2.13, sqlite 3.6.13, tk 8.6.0, usb 1.0.9, wxgtk 2.8.12, xml‑parser 2.41, zlib 1.2.7;
- : cppunit 1.12.1, dprof 1.3, gdb 7.2, perf 3.5.7;
- : anjuta 2.32.1.1, glade 2.12.0, glade 3.5.1, qt‑creator 2.7.1;
- : bzr 2.2.4, cvs 1.11.22, git 1.8.0, patch 2.7, subversion 1.7.7.
同样,如果您期望使用GCC 5,PHP 7和Java 9,那么这就是您的问题,正如一位著名的足球运动员所说。在这种情况下,我还必须说,至少不像以前的Elbrus系统那样是GCC 3.4.6(LCC 1.16.12),也不是MSVS 3.0的GCC 3.3.6。顺便说一句,MSVS 3.0中的主要编译器仍然是GCC 2.95.4(为什么当有2.4分支的内核时会感到惊讶?)与以前的情况相比,当有可能偶然发现十年前在上游修复的GCC错误时,新系统几乎具有天生的条件-如果您不想保持向后兼容性,甚至可以在C ++ 11中对其进行轻扫。至少在某种形式上,OpenJDK的出现已经可以说是一个重大突破,因为对Java和Mono不满意。 在这样的系统中早已为人所知;当本地程序几乎不移动时,这种不喜欢就可以理解。由于作者的同事中有很多Javists,由于上述情况,被迫束缚了灵魂的美好冲动,因此决定进行一系列单独的性能测试来专门研究Java。展望未来,我们注意到,即使相对而言,结果也令人沮丧:如果获得相同的成功,则可以用PHP或Python编写解释性脚本。仅对C和C ++的支持不仅限于与GNU编译器集合的兼容性:系统仍然具有Fortran转换器。由于作者只熟悉Fortran教授,因此任何有兴趣的人都可以推荐12月的主题“与我们一起制作”,其中的评论涉及使用该语言作为基准。对于甜点,我们储备了最美味的:本文的最后一部分致力于与各种硬件和软件平台(包括家用平台)相比,研究Elbrus的性能。