JONY

优化MIC-1微体系结构

速度与价格 商用CPU的优化问题主要集中在对速度(性能)与价格(成本)这对矛盾的权衡,更高的性能往往意味着复杂的电路和更多的部件,进而需要更大面积,这又会导致功耗和散热难度的增加和芯片良品率的降低,也就是成本的增加。而且面积并不能无限增大,这会导致部件的电气性能变差,反而降低性能。所以如何合理利用面积也是个重要衍生问题,比如加法器曾有千种设计,速度快的往往面积大,盲目选最快的加法器会占用其他部件的面积,最后整体性能可能下降,这在工业上也有过案例。目前的商用CPU市场中,还没有一种完备的精确定价策略,目前定价所依据的是部件数量、晶体管数量这样的指标。 CPU在“速度与价格”上的进步(每代INTEL加速不加价),其实主要靠集成电路技术的发展,但这部分不是计算机系统的内容。那么,对于确定的指令系统层和集成电路技术,有如下几种提高速度的策略:… 阅读全文

使用预取技术的MIC-2

取指单元(IFU)回顾MIC-1微体系结构,可发现两个导致占用过多时钟周期的问题点: 1) 需要一次一字节的取操作数,并且还16位操作属还需要拼接。其中每取一个字节都对应于一次ALU的占用(一个时钟周期),因为其需要PC自增来提供内存地址。拼接过程同样如此; 2) ALU在很多时候并未用作“复杂”的算术逻辑计算,比如最简单的是让数据“直通”,其次是自增。其相对于ALU的面积是种浪费,且和复杂的ALU计算占用相同时间; 基于上述原因,可以考虑在MIC-1加一个面积小且能力弱的ALU,其“位置”和ALU类似,能和ALU并行工作于同一时刻。该方法能平衡面积(价格)与速度的矛盾,因为其用较少面积“分摊”了一部分的ALU占用时间。这种思路下的具体方案就是在MIC-1加入IFU(取指单元)。IFU通常基于2种预取策略:… 阅读全文

生态与开发环境

C语言的特征与应用场景 C语言是种古老的语言,其相对于现在流行的语言来说,有几个特征: 1) 对于同样的程序逻辑,其C语言实现的性能是非常高的,通常仅次于汇编语言(ASM); 2) C语言通常会被直接编译成目标机器与操作系统下的程序,中间没有解释器和虚拟机; 3) C语言没有内置面向对象(OOP)语法,但其提供了跟Class有点像的结构体类型。如果真的想要在C语言下进行OOP,往往需要间接的通过一些其他的软件设计方法; 4) C语言离机器与操作系统更近,比方说C语言直接对程序员提供了内存模型; 5)  具有一定的跨机器与跨系统移植的能力,但仅限于源码级。比如相比Java的“1份代码,1次编译,n处运行”,C最多只能“1份代码,n处编译,n处运行”; 6) 开发效率较低,同样的逻辑C语言的代码量可能是Java的几倍,是Python的几十倍;… 阅读全文

使用流水线技术的MIC-3

MIC-3的数据通路前面讨论了比MIC-1更快的MIC-2,但由于使用了IFU,MIC-2的成本比MIC-1更高。接下来继续讨论如何把MIC-2改进成速度更快的MIC-3,改进基于如下2个方面: 1) 缩短时钟周期:通过改进电路缩短周期,虽然集成电路技术对这方面作用更大,前面提过这点; 2) 提高并行度: MIC-2虽然比MIC-1有更大的并行度(IFU并行取指),但其并行度仍可继续提升; 集成电路水平给定时,MIC-2允许的最短时钟周期很大程度由3部分延迟的和决定: 1) 寄存器数据通过A、B总线的延迟; 2) 数据通过ALU、移位器的延迟; 3) 数据通过他总线(写寄存器)的延迟; 上图为了MIC-3的数据通路,相比MIC-2仅多了3条总线上的3个锁存器。这可以让数据分3个时钟周期通过数据通路,第1个周期寄存器把数据送入A、B锁存器,第2个周期把计算结果送入C锁存器,第3个周期让C锁存器写入寄存器。表面上看,数据通过数据通路的时间扩大到3个时钟周期,但由于这3个步骤的总延迟与之前1个步骤的延迟差不多,所以可认为MIC-3能使用快3倍的时钟(理想状态)。… 阅读全文

七段流水线的MIC-4

MIC-4的流水线MIC-4是对MIC-3的改进,其具有更深的流水线。其使用和MIC-3相似的数据通路和IFU,并引入新功能单元。上图是MIC-4的结构,图中没太多细节,简单了解各功能单元即可: 1) 译码单元:用于划分出包括操作数和操作码的整条指令。其组成包括一个内部ROM,其索引为操作码,数据为指令长度与队列单元的微操作ROM的索引。记录指令长度可能是为了避免误把操作数当操作码。有了译码单元处理WIDE指令就会更方便,可以直接把WIDE ILOAD作为整体映射到微操作ROM; 2) 队列单元:其组成包括1个ROM表和1个RAM队列,前者存储微程序,后者暂存微操作; 2.1) 微程序: MIC-4的微程序结构不同,每个ISA指令对应ROM表的一些顺序的行,这些行称为微操作,其类似于微指令,但微操作大都不含“下个微操作的索引”,所以对于ILOAD和WIDE… 阅读全文

二叉树的遍历与重建

遍历算法之前在讨论线性表时,用遍历指代“按该线性表的序依次访问所有元素(节点)”,并未详细定义什么是“遍历”。这是因为线性表的遍历通常都是按线性表本身的序来遍历的,并且在日常编程中不太区分遍历、循环、枚举等概念。准确来说遍历(Traversal)是一类特定的算法,其能够按算法设计者所要求的次序,访问且仅访问一次数据结构中的所有元素。比如对于数组,遍历既能是简单的顺序遍历,也可以是更复杂的“先访问全部偶数索引、再访问全部奇数索引”,具体如上图。 对于大部分简单且常见的遍历算法,代价通常都是\(O(n)\)且仅需\(O(1)\)额外空间。但在遇到复杂的数据结构、或需要复杂的访问次序时,可能会有更高的代价和空间复杂度,比如之后会讨论的图遍历。原因之一是当元素间的关系更复杂时,会无法避免的多次“物理访问”同个节点,这时“仅访问一次”的要求就成了“负担”,需要额外的步骤或空间才能区分“仅访问一次”。… 阅读全文

高速缓存技术

高速缓存在计算机发展的过程中,一直存在一个有挑战性的问题:如何设计与CPU速度匹配的内存系统。尤其是过去十几年来,内存系统和CPU的“相对速度”是越来越慢的。现代CPU对内存的延迟和带宽有高的要求,但是内存系统在这两方面通常是矛盾的,如果增大带宽会导致延迟的升高。比如说可以通过流水线技术来让多个内存访问“重叠”,从而增大总的带宽,但这会让每个单次内存访问的延迟更大。 解决内存慢的主流方案是在内存系统中使用高速缓存技术(cache),其中分离式高速缓存是种能有效解决带宽和延迟的矛盾的方案,其分别为数据和指令提供缓存,并允许在这2种缓存并行的进行访问。并行能让带宽翻倍,而这种带宽翻倍并不增加延迟。比如MIC-1就提供了用于指令和数据的两种内存访问端口,如果让这两个端口各有自己的缓存模块,那这两个缓存模块可独立的访问内存。… 阅读全文

HELLOWORLD程序

HelloWorld程序 给出C语言下的Hello,World程序hello.c。这个程序也会作为计算机系统中的分析案例。 C #include <stdio.h> int main(void) { printf("hello,world\n"); return 0; } 12345 #include <stdio.h>int main(void) {  printf("hello,world\n");  return 0;} 通过GCC编译器的命令“gcc ./hello.c”就可将代码编译为当前操作系统下的可执行文件“a.out”。然后通过命令“./a.out”就可执行它,其结果是在终端打印“hello,world!”。代码中的main函数是一种ANSI C标准给出的约定,其约定C程序执行入口是名叫main的函数,并且其返回值类型是int。main可以接受参数也可以不接受参数,接受参数的一种用法是接受执行时Shell传入的参数。… 阅读全文

变量、常量、作用域

变量 C语言是一种静态类型的语言,其在初始化变量时需要指定变量的类型,但其在语法层面不要求在变量初始化时必须赋值。比方说“int a”和“int a = 1”都是合法的变量初始化语法,在初始化后可以为变量再次的赋值。C语言中的变量分为如下几种: 1) 全局变量:不在花括号内的变量; 2) 局部变量:花括号内的变量; 3) 形式参数:函数传入的参数;   作用域 C语言的作用域靠花括号区分   C语言初始化新的变量是使用“int a = 1”这样的语法,这样的语句前还可以加入const关键字,这可以把a声明为常量,即执行完“const int a = 1”后a的值将不允许被改变。C语言中还有另一种“实现常量”的方式,就是利用预处理指令#define。比如“#define A 1”可以实现在程序中加入等于1的常量A。这两种方式的区别是const是程序的一部分,而#define不能算是程序的一部分,其会在非正式编译的预处理阶段把代码中的A换成1,然后再进行后续的正式编译。

基本数据类型

基本数据类型 — 空类型 C语言中的void关键字用于描述“没有具体类型或是没有内容”,其有3种常见使用场景: 1) 用于定义函数时说明其无返回值 (比如void f(int x,int y)的语法); 2) 用于定义函数时说明其没有参数(比如int f(void)的语法); 3) 用于定义无类型指针,可以指向任何类型的数据(void *p的语法);   基本数据类型 — int类型 整数(integer/int)类型由int关键字与long/short/unsigned组合而成。下面举例说明: 1) int:C90规定int取值范围至少为-32768~32767。这里的“至少”令人费解,因为在制定标准时考虑了对未来存储的兼容,在不同的机器/操作系统/编译器上,int可能允许更大范围的整数,比如在64位机器上,int会比16位机器的范围大;… 阅读全文
滚动至顶部